[PATCH] Add support for the read/write interface of SG v3
authorJens Axboe <axboe@suse.de>
Fri, 17 Feb 2006 09:10:12 +0000 (10:10 +0100)
committerJens Axboe <axboe@suse.de>
Fri, 17 Feb 2006 09:10:12 +0000 (10:10 +0100)
fio-ini.c
fio-io.c
fio.c
fio.h

index 234058980b3d11ab9e7e45f4c896e1d8495eaea3..c94062279989285ed20a0326e2297f86bf94029b 100644 (file)
--- 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')
index dee02ab5e067ba8bf74188d56f429f00a361b129..b688fa288de75a8ec59ed14a09ee8f54aec69f12 100644 (file)
--- 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 9dd8e249122ddfc75122cebb1fbca58d0901a06a..5c45cae7f64103e0a8e30b16d7f704a2680f45e8 100644 (file)
--- 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 bb5b8dd16fc584d155cecfd8af4ce57537e280f6..5fcdfddb65050171e34b42ff04730e0efafe4939 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -259,6 +259,7 @@ enum {
 enum {
        FIO_TYPE_FILE = 1,
        FIO_TYPE_BD,
+       FIO_TYPE_CHAR,
 };
 
 enum {