From 0af7b542b69af5ab2400a9960a5bcde82c05723f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 17 Feb 2006 10:10:12 +0100 Subject: [PATCH] [PATCH] Add support for the read/write interface of SG v3 --- fio-ini.c | 8 ++++-- fio-io.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++--------- fio.c | 17 ++++++++---- fio.h | 1 + 4 files changed, 86 insertions(+), 20 deletions(-) diff --git a/fio-ini.c b/fio-ini.c index 23405898..c9406227 100644 --- a/fio-ini.c +++ b/fio-ini.c @@ -204,8 +204,12 @@ static int add_job(struct thread_data *td, const char *jobname, int prioclass, td->zone_size = 0; td->filetype = FIO_TYPE_FILE; - if (!stat(jobname, &sb) && S_ISBLK(sb.st_mode)) - td->filetype = FIO_TYPE_BD; + if (!stat(jobname, &sb)) { + if (S_ISBLK(sb.st_mode)) + td->filetype = FIO_TYPE_BD; + else if (S_ISCHR(sb.st_mode)) + td->filetype = FIO_TYPE_CHAR; + } if (td->filetype == FIO_TYPE_FILE) { if (td->directory[0] != '\0') diff --git a/fio-io.c b/fio-io.c index dee02ab5..b688fa28 100644 --- a/fio-io.c +++ b/fio-io.c @@ -481,6 +481,24 @@ static inline void sgio_hdr_init(struct sgio_data *sd, struct sg_io_hdr *hdr, } } +static int fio_sgio_doio(struct thread_data *td, struct sg_io_hdr *hdr) +{ + int ret; + + if (td->filetype == FIO_TYPE_BD) + return ioctl(td->fd, SG_IO, &hdr); + + ret = write(td->fd, hdr, sizeof(*hdr)); + if (ret < 0) + return errno; + + ret = read(td->fd, hdr, sizeof(*hdr)); + if (ret < 0) + return errno; + + return 0; +} + static int fio_sgio_sync(struct thread_data *td) { struct sgio_data *sd = td->io_data; @@ -491,7 +509,7 @@ static int fio_sgio_sync(struct thread_data *td) hdr.cmdp[0] = 0x35; - return ioctl(td->fd, SG_IO, &hdr); + return fio_sgio_doio(td, &hdr); } static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) @@ -532,7 +550,8 @@ static int fio_sgio_queue(struct thread_data *td, struct io_u *io_u) struct sgio_data *sd = td->io_data; int ret; - ret = ioctl(td->fd, SG_IO, hdr); + ret = fio_sgio_doio(td, hdr); + if (ret < 0) io_u->error = errno; else if (hdr->status) { @@ -555,22 +574,60 @@ static struct io_u *fio_sgio_event(struct thread_data *td, int event) return sd->last_io_u; } +static int fio_sgio_get_bs(struct thread_data *td, unsigned int *bs) +{ + struct sgio_data *sd = td->io_data; + struct sg_io_hdr hdr; + unsigned char buf[8]; + int ret; + + sgio_hdr_init(sd, &hdr, NULL); + memset(buf, 0, sizeof(buf)); + + hdr.cmdp[0] = 0x25; + hdr.dxfer_direction = SG_DXFER_FROM_DEV; + hdr.dxferp = buf; + hdr.dxfer_len = sizeof(buf); + + ret = fio_sgio_doio(td, &hdr); + if (ret) + return ret; + + *bs = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; + return 0; +} + int fio_sgio_init(struct thread_data *td) { struct sgio_data *sd; - int bs; + unsigned int bs; + int ret; - if (td->filetype != FIO_TYPE_BD) { - fprintf(stderr, "ioengine sgio only works on block devices\n"); - return 1; - } + sd = malloc(sizeof(*sd)); + sd->last_io_u = NULL; + td->io_data = sd; - if (ioctl(td->fd, BLKSSZGET, &bs) < 0) { - td_verror(td, errno); + if (td->filetype == FIO_TYPE_BD) { + if (ioctl(td->fd, BLKSSZGET, &bs) < 0) { + td_verror(td, errno); + return 1; + } + } else if (td->filetype == FIO_TYPE_CHAR) { + int version; + + if (ioctl(td->fd, SG_GET_VERSION_NUM, &version) < 0) { + td_verror(td, errno); + return 1; + } + + ret = fio_sgio_get_bs(td, &bs); + if (ret) + return ret; + } else { + fprintf(stderr, "ioengine sgio only works on block devices\n"); return 1; } - sd = malloc(sizeof(*sd)); sd->bs = bs; td->io_prep = fio_sgio_prep; @@ -585,9 +642,6 @@ int fio_sgio_init(struct thread_data *td) * we want to do it, regardless of whether odirect is set or not */ td->override_sync = 1; - - sd->last_io_u = NULL; - td->io_data = sd; return 0; } diff --git a/fio.c b/fio.c index 9dd8e249..5c45cae7 100644 --- a/fio.c +++ b/fio.c @@ -1235,12 +1235,14 @@ static int bdev_size(struct thread_data *td) static int get_file_size(struct thread_data *td) { - int ret; + int ret = 0; if (td->filetype == FIO_TYPE_FILE) ret = file_size(td); - else + else if (td->filetype == FIO_TYPE_BD) ret = bdev_size(td); + else + td->real_file_size = -1; if (ret) return ret; @@ -1356,9 +1358,14 @@ static int setup_file(struct thread_data *td) if (td->odirect) flags |= O_DIRECT; - if (td_read(td)) - td->fd = open(td->file_name, flags | O_RDONLY); - else { + if (td_read(td)) { + if (td->filetype == FIO_TYPE_CHAR) + flags |= O_RDWR; + else + flags |= O_RDONLY; + + td->fd = open(td->file_name, flags); + } else { if (td->filetype == FIO_TYPE_FILE) { if (!td->overwrite) flags |= O_TRUNC; diff --git a/fio.h b/fio.h index bb5b8dd1..5fcdfddb 100644 --- a/fio.h +++ b/fio.h @@ -259,6 +259,7 @@ enum { enum { FIO_TYPE_FILE = 1, FIO_TYPE_BD, + FIO_TYPE_CHAR, }; enum { -- 2.25.1