#define MAX_10B_LBA 0xFFFFFFFFULL
#define SCSI_TIMEOUT_MS 30000 // 30 second timeout; currently no method to override
#define MAX_SB 64 // sense block maximum return size
+/*
+#define FIO_SGIO_DEBUG
+*/
struct sgio_cmd {
unsigned char cdb[16]; // enhanced from 10 to support 16 byte commands
int type_checked;
struct sgio_trim **trim_queues;
int current_queue;
+#ifdef FIO_SGIO_DEBUG
unsigned int *trim_queue_map;
+#endif
};
static inline bool sgio_unbuffered(struct thread_data *td)
if (io_u->ddir == DDIR_TRIM) {
struct sgio_trim *st = sd->trim_queues[io_u->index];
+#ifdef FIO_SGIO_DEBUG
assert(st->trim_io_us[0] == io_u);
+ assert(sd->trim_queue_map[io_u->index] == io_u->index);
dprint(FD_IO, "sgio_getevents: reaping %d io_us from trim queue %d\n", st->unmap_range_count, io_u->index);
dprint(FD_IO, "sgio_getevents: reaped io_u %d and stored in events[%d]\n", io_u->index, i+trims);
+#endif
for (j = 1; j < st->unmap_range_count; j++) {
++trims;
sd->events[i + trims] = st->trim_io_us[j];
+#ifdef FIO_SGIO_DEBUG
dprint(FD_IO, "sgio_getevents: reaped io_u %d and stored in events[%d]\n", st->trim_io_us[j]->index, i+trims);
+ assert(sd->trim_queue_map[st->trim_io_us[j]->index] == io_u->index);
+#endif
if (hdr->info & SG_INFO_CHECK) {
/* record if an io error occurred, ignore resid */
memcpy(&st->trim_io_us[j]->hdr, hdr, sizeof(struct sg_io_hdr));
sd->current_queue = io_u->index;
st = sd->trim_queues[sd->current_queue];
hdr->dxferp = st->unmap_param;
+#ifdef FIO_SGIO_DEBUG
assert(sd->trim_queues[io_u->index]->unmap_range_count == 0);
dprint(FD_IO, "sg: creating new queue based on io_u %d\n", io_u->index);
+#endif
}
else
st = sd->trim_queues[sd->current_queue];
dprint(FD_IO, "sg: adding io_u %d to trim queue %d\n", io_u->index, sd->current_queue);
st->trim_io_us[st->unmap_range_count] = io_u;
+#ifdef FIO_SGIO_DEBUG
sd->trim_queue_map[io_u->index] = sd->current_queue;
+#endif
offset = 8 + 16 * st->unmap_range_count;
st->unmap_param[offset] = (unsigned char) ((lba >> 56) & 0xff);
/* finish cdb setup for unmap because we are
** doing unmap commands synchronously */
+#ifdef FIO_SGIO_DEBUG
assert(st->unmap_range_count == 1);
assert(io_u == st->trim_io_us[0]);
+#endif
hdr = &io_u->hdr;
fio_sgio_unmap_setup(hdr, st);
ret = fio_sgio_rw_doio(io_u->file, io_u, 0);
- if (ret < 0)
- for (i = 0; i < st->unmap_range_count; i++)
- st->trim_io_us[i]->error = errno;
- else if (hdr->status)
- for (i = 0; i < st->unmap_range_count; i++) {
- st->trim_io_us[i]->resid = hdr->resid;
- st->trim_io_us[i]->error = EIO;
+ if (ret < 0 || hdr->status) {
+ int error;
+
+ if (ret < 0)
+ error = errno;
+ else {
+ error = EIO;
+ ret = -EIO;
}
- else {
- if (fio_fill_issue_time(td)) {
- fio_gettime(&now, NULL);
- for (i = 0; i < st->unmap_range_count; i++) {
- struct io_u *io_u = st->trim_io_us[i];
-
- memcpy(&io_u->issue_time, &now, sizeof(now));
- io_u_queued(td, io_u);
- }
+
+ for (i = 0; i < st->unmap_range_count; i++) {
+ st->trim_io_us[i]->error = error;
+ clear_io_u(td, st->trim_io_us[i]);
+ if (hdr->status)
+ st->trim_io_us[i]->resid = hdr->resid;
}
- io_u_mark_submit(td, st->unmap_range_count);
+
+ td_verror(td, error, "xfer");
+ return ret;
}
- if (io_u->error) {
- td_verror(td, io_u->error, "xfer");
- return 0;
+ if (fio_fill_issue_time(td)) {
+ fio_gettime(&now, NULL);
+ for (i = 0; i < st->unmap_range_count; i++) {
+ memcpy(&st->trim_io_us[i]->issue_time, &now, sizeof(now));
+ io_u_queued(td, io_u);
+ }
}
+ io_u_mark_submit(td, st->unmap_range_count);
- if (ret == FIO_Q_QUEUED)
- return 0;
- else
- return ret;
+ return 0;
}
static struct io_u *fio_sgio_event(struct thread_data *td, int event)
free(sd->fd_flags);
free(sd->pfds);
free(sd->sgbuf);
+#ifdef FIO_SGIO_DEBUG
free(sd->trim_queue_map);
+#endif
for (i = 0; i < td->o.iodepth; i++) {
free(sd->trim_queues[i]->unmap_param);
sd->trim_queues = calloc(td->o.iodepth, sizeof(struct sgio_trim *));
sd->current_queue = -1;
+#ifdef FIO_SGIO_DEBUG
sd->trim_queue_map = calloc(td->o.iodepth, sizeof(int));
+#endif
for (i = 0; i < td->o.iodepth; i++) {
sd->trim_queues[i] = calloc(1, sizeof(struct sgio_trim));
st = sd->trim_queues[i];