[PATCH] Add support for the read/write interface of SG v3
diff --git a/fio-ini.c b/fio-ini.c
index 2340589..c940622 100644
--- a/fio-ini.c
+++ b/fio-ini.c
@@ -204,8 +204,12 @@
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 dee02ab..b688fa2 100644
--- a/fio-io.c
+++ b/fio-io.c
@@ -481,6 +481,24 @@
}
}
+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 @@
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 @@
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 @@
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) {
+ sd = malloc(sizeof(*sd));
+ sd->last_io_u = NULL;
+ td->io_data = sd;
+
+ 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;
}
- if (ioctl(td->fd, BLKSSZGET, &bs) < 0) {
- td_verror(td, errno);
- return 1;
- }
-
- sd = malloc(sizeof(*sd));
sd->bs = bs;
td->io_prep = fio_sgio_prep;
@@ -585,9 +642,6 @@
* 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 9dd8e24..5c45cae 100644
--- a/fio.c
+++ b/fio.c
@@ -1235,12 +1235,14 @@
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 @@
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 bb5b8dd..5fcdfdd 100644
--- a/fio.h
+++ b/fio.h
@@ -259,6 +259,7 @@
enum {
FIO_TYPE_FILE = 1,
FIO_TYPE_BD,
+ FIO_TYPE_CHAR,
};
enum {