X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fsg.c;h=57c3834add235362acdd18ee672c176456ae9e16;hp=d32007022aeb8388c6e0fcfef0d5f4ee50393acc;hb=a1c58075279454a91ec43366846b93e8dcf9753c;hpb=dc0deca2b89bea896e8eb8133961cec68c4ba8b9 diff --git a/engines/sg.c b/engines/sg.c index d3200702..57c3834a 100644 --- a/engines/sg.c +++ b/engines/sg.c @@ -1,5 +1,7 @@ /* - * scsi generic sg v3 io engine + * sg engine + * + * IO engine that uses the Linux SG v3 interface to talk to SCSI devices * */ #include @@ -10,7 +12,6 @@ #include #include "../fio.h" -#include "../os.h" #ifdef FIO_HAVE_SGIO @@ -26,6 +27,7 @@ struct sgio_data { int *fd_flags; void *sgbuf; unsigned int bs; + int type_checked; }; static void sgio_hdr_init(struct sgio_data *sd, struct sg_io_hdr *hdr, @@ -48,21 +50,6 @@ static void sgio_hdr_init(struct sgio_data *sd, struct sg_io_hdr *hdr, } } -static int fio_sgio_ioctl_getevents(struct thread_data *td, int fio_unused min, - int max, struct timespec fio_unused *t) -{ - assert(max <= 1); - - /* - * we can only have one finished io_u for sync io, since the depth - * is always 1 - */ - if (list_empty(&td->io_u_busylist)) - return 0; - - return 1; -} - static int pollin_events(struct pollfd *pfds, int fds) { int i; @@ -74,17 +61,14 @@ static int pollin_events(struct pollfd *pfds, int fds) return 0; } -static int fio_sgio_getevents(struct thread_data *td, int min, int max, - struct timespec fio_unused *t) +static int fio_sgio_getevents(struct thread_data *td, unsigned int min, + unsigned int max, struct timespec fio_unused *t) { - /* - * normally hard coding &td->files[0] is a bug that needs to be fixed, - * but it's ok here as all files should point to the same device. - */ - struct fio_file *f = &td->files[0]; struct sgio_data *sd = td->io_ops->data; - int left = max, ret, events, i, r = 0; + int left = max, ret, r = 0; void *buf = sd->sgbuf; + unsigned int i, events; + struct fio_file *f; /* * Fill in the file descriptors @@ -108,16 +92,16 @@ static int fio_sgio_getevents(struct thread_data *td, int min, int max, if (!min) break; - ret = poll(sd->pfds, td->nr_files, -1); + ret = poll(sd->pfds, td->o.nr_files, -1); if (ret < 0) { - td_verror(td, errno); if (!r) - r = -1; + r = -errno; + td_verror(td, errno, "poll"); break; } else if (!ret) continue; - if (pollin_events(sd->pfds, td->nr_files)) + if (pollin_events(sd->pfds, td->o.nr_files)) break; } while (1); @@ -132,8 +116,8 @@ re_read: if (ret < 0) { if (errno == EAGAIN) continue; - td_verror(td, errno); - r = -1; + r = -errno; + td_verror(td, errno, "read"); break; } else if (ret) { p += ret; @@ -171,10 +155,15 @@ static int fio_sgio_ioctl_doio(struct thread_data *td, { struct sgio_data *sd = td->io_ops->data; struct sg_io_hdr *hdr = &io_u->hdr; + int ret; sd->events[0] = io_u; - return ioctl(f->fd, SG_IO, hdr); + ret = ioctl(f->fd, SG_IO, hdr); + if (ret < 0) + return ret; + + return FIO_Q_COMPLETED; } static int fio_sgio_rw_doio(struct fio_file *f, struct io_u *io_u, int sync) @@ -184,22 +173,23 @@ static int fio_sgio_rw_doio(struct fio_file *f, struct io_u *io_u, int sync) ret = write(f->fd, hdr, sizeof(*hdr)); if (ret < 0) - return errno; + return ret; if (sync) { ret = read(f->fd, hdr, sizeof(*hdr)); if (ret < 0) - return errno; + return ret; + return FIO_Q_COMPLETED; } - return 0; + return FIO_Q_QUEUED; } static int fio_sgio_doio(struct thread_data *td, struct io_u *io_u, int sync) { struct fio_file *f = io_u->file; - if (td->filetype == FIO_TYPE_BD) + if (f->filetype == FIO_TYPE_BD) return fio_sgio_ioctl_doio(td, f, io_u); return fio_sgio_rw_doio(f, io_u, sync); @@ -250,9 +240,14 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) static int fio_sgio_queue(struct thread_data *td, struct io_u *io_u) { struct sg_io_hdr *hdr = &io_u->hdr; - int ret; + int ret, do_sync = 0; - ret = fio_sgio_doio(td, io_u, io_u->ddir == DDIR_SYNC); + fio_ro_check(td, io_u); + + if (td->o.sync_io || td->o.odirect || ddir_sync(io_u->ddir)) + do_sync = 1; + + ret = fio_sgio_doio(td, io_u, do_sync); if (ret < 0) io_u->error = errno; @@ -261,7 +256,12 @@ static int fio_sgio_queue(struct thread_data *td, struct io_u *io_u) io_u->error = EIO; } - return io_u->error; + if (io_u->error) { + td_verror(td, io_u->error, "xfer"); + return FIO_Q_COMPLETED; + } + + return ret; } static struct io_u *fio_sgio_event(struct thread_data *td, int event) @@ -280,7 +280,7 @@ static int fio_sgio_get_bs(struct thread_data *td, unsigned int *bs) int ret; io_u = __get_io_u(td); - io_u->file = &td->files[0]; + io_u->file = td->files[0]; assert(io_u); hdr = &io_u->hdr; @@ -314,75 +314,86 @@ static void fio_sgio_cleanup(struct thread_data *td) free(sd->pfds); free(sd->sgbuf); free(sd); - - td->io_ops->data = NULL; } } static int fio_sgio_init(struct thread_data *td) { - struct fio_file *f = &td->files[0]; struct sgio_data *sd; - unsigned int bs; - int ret; sd = malloc(sizeof(*sd)); memset(sd, 0, sizeof(*sd)); - sd->cmds = malloc(td->iodepth * sizeof(struct sgio_cmd)); - memset(sd->cmds, 0, td->iodepth * sizeof(struct sgio_cmd)); - sd->events = malloc(td->iodepth * sizeof(struct io_u *)); - memset(sd->events, 0, td->iodepth * sizeof(struct io_u *)); - sd->pfds = malloc(sizeof(struct pollfd) * td->nr_files); - memset(sd->pfds, 0, sizeof(struct pollfd) * td->nr_files); - sd->fd_flags = malloc(sizeof(int) * td->nr_files); - memset(sd->fd_flags, 0, sizeof(int) * td->nr_files); - sd->sgbuf = malloc(sizeof(struct sg_io_hdr) * td->iodepth); - memset(sd->sgbuf, 0, sizeof(struct sg_io_hdr) * td->iodepth); + sd->cmds = malloc(td->o.iodepth * sizeof(struct sgio_cmd)); + memset(sd->cmds, 0, td->o.iodepth * sizeof(struct sgio_cmd)); + sd->events = malloc(td->o.iodepth * sizeof(struct io_u *)); + memset(sd->events, 0, td->o.iodepth * sizeof(struct io_u *)); + sd->pfds = malloc(sizeof(struct pollfd) * td->o.nr_files); + memset(sd->pfds, 0, sizeof(struct pollfd) * td->o.nr_files); + sd->fd_flags = malloc(sizeof(int) * td->o.nr_files); + memset(sd->fd_flags, 0, sizeof(int) * td->o.nr_files); + sd->sgbuf = malloc(sizeof(struct sg_io_hdr) * td->o.iodepth); + memset(sd->sgbuf, 0, sizeof(struct sg_io_hdr) * td->o.iodepth); td->io_ops->data = sd; - if (td->filetype == FIO_TYPE_BD) { + /* + * we want to do it, regardless of whether odirect is set or not + */ + td->o.override_sync = 1; + return 0; +} + +static int fio_sgio_type_check(struct thread_data *td, struct fio_file *f) +{ + struct sgio_data *sd = td->io_ops->data; + unsigned int bs; + + if (f->filetype == FIO_TYPE_BD) { if (ioctl(f->fd, BLKSSZGET, &bs) < 0) { - td_verror(td, errno); - goto err; + td_verror(td, errno, "ioctl"); + return 1; } - } else if (td->filetype == FIO_TYPE_CHAR) { - int version; + } else if (f->filetype == FIO_TYPE_CHAR) { + int version, ret; if (ioctl(f->fd, SG_GET_VERSION_NUM, &version) < 0) { - td_verror(td, errno); - goto err; + td_verror(td, errno, "ioctl"); + return 1; } ret = fio_sgio_get_bs(td, &bs); if (ret) - goto err; + return 1; } else { - log_err("ioengine sgio only works on block devices\n"); - goto err; + log_err("ioengine sg only works on block devices\n"); + return 1; } sd->bs = bs; - if (td->filetype == FIO_TYPE_BD) - td->io_ops->getevents = fio_sgio_ioctl_getevents; - else - td->io_ops->getevents = fio_sgio_getevents; + if (f->filetype == FIO_TYPE_BD) { + td->io_ops->getevents = NULL; + td->io_ops->event = NULL; + } + + return 0; +} + +static int fio_sgio_open(struct thread_data *td, struct fio_file *f) +{ + struct sgio_data *sd = td->io_ops->data; + int ret; + + ret = generic_open_file(td, f); + if (ret) + return ret; + + if (sd && !sd->type_checked && fio_sgio_type_check(td, f)) { + ret = generic_close_file(td, f); + return 1; + } - /* - * we want to do it, regardless of whether odirect is set or not - */ - td->override_sync = 1; return 0; -err: - free(sd->events); - free(sd->cmds); - free(sd->fd_flags); - free(sd->pfds); - free(sd->sgbuf); - free(sd); - td->io_ops->data = NULL; - return 1; } static struct ioengine_ops ioengine = { @@ -394,6 +405,9 @@ static struct ioengine_ops ioengine = { .getevents = fio_sgio_getevents, .event = fio_sgio_event, .cleanup = fio_sgio_cleanup, + .open_file = fio_sgio_open, + .close_file = generic_close_file, + .get_file_size = generic_get_file_size, .flags = FIO_SYNCIO | FIO_RAWIO, }; @@ -406,12 +420,12 @@ static struct ioengine_ops ioengine = { */ static int fio_sgio_init(struct thread_data fio_unused *td) { - fprintf(stderr, "fio: sgio not available\n"); + fprintf(stderr, "fio: ioengine sg not available\n"); return 1; } static struct ioengine_ops ioengine = { - .name = "sgio", + .name = "sg", .version = FIO_IOOPS_VERSION, .init = fio_sgio_init, };