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')
}
}
+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;
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)
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) {
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;
* 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;
}
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;
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;