Skip to content

Commit

Permalink
zvol: Make Block IO DIRECT operations synchronous
Browse files Browse the repository at this point in the history
Signed-off-by: Ameer Hamza <[email protected]>
  • Loading branch information
ixhamza committed Nov 12, 2023
1 parent f586620 commit 171f061
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
57 changes: 57 additions & 0 deletions include/os/linux/kernel/linux/blkdev_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,39 @@ bio_is_fua(struct bio *bio)
#endif
}

/*
* 4.8 API,
* REQ_SYNC flag moved to bio->bi_opf
*
* 2.6.x - 4.7 API,
* REQ_SYNC
*/
static inline boolean_t
bio_is_sync(struct bio *bio)
{
#if defined(HAVE_BIO_BI_OPF)
return (!!(bio->bi_opf & REQ_SYNC));
#elif defined(REQ_SYNC)
return (!!(bio->bi_rw & REQ_SYNC));
#else
#error "Allowing the build will cause sync requests to be ignored."
#endif
}

/*
* 4.10 API,
* REQ_IDLE flag replaced by REQ_NOIDLE
*/
static inline boolean_t
bio_is_idle(struct bio *bio)
{
#if defined(HAVE_BIO_BI_OPF) && defined(REQ_IDLE)
return (!!(bio->bi_opf & REQ_IDLE));
#else
return (0);
#endif
}

/*
* 4.8 API,
* REQ_OP_DISCARD
Expand Down Expand Up @@ -778,4 +811,28 @@ io_has_data(struct bio *bio, struct request *rq)
#endif
return (bio_has_data(bio));
}

static inline int
io_is_sync(struct bio *bio, struct request *rq)
{
#ifdef HAVE_BLK_MQ
if (rq != NULL)
return (!!(rq->cmd_flags & REQ_SYNC));
#else
ASSERT3P(rq, ==, NULL);
#endif
return (bio_is_sync(bio));
}

static inline int
io_is_idle(struct bio *bio, struct request *rq)
{
#ifdef HAVE_BLK_MQ
if (rq != NULL)
return (!!(rq->cmd_flags & REQ_IDLE));
#else
ASSERT3P(rq, ==, NULL);
#endif
return (bio_is_idle(bio));
}
#endif /* _ZFS_BLKDEV_H */
15 changes: 14 additions & 1 deletion module/os/linux/zfs/zvol_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,9 +518,22 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
uint64_t offset = io_offset(bio, rq);
uint64_t size = io_size(bio, rq);
int rw = io_data_dir(bio, rq);
int is_sync_io = io_is_sync(bio, rq);
int is_idle_io = io_is_idle(bio, rq);

if (zvol_request_sync)
/*
* For Direct IO Writes, the block layer sets both the REQ_IDLE
* and REQ_SYNC flags (see dio_bio_write_op). For Direct IO
* Reads (up to 1MB IO size), REQ_SYNC is set by
* submit_bio_wait(). In both cases, since the caller already
* waits for the bio to complete, we should force these
* operations to be synchronous to avoid additional threading
* overhead.
*/
if (zvol_request_sync || (rw == READ && is_sync_io) ||
(rw == WRITE && is_sync_io && is_idle_io)) {
force_sync = 1;
}

zv_request_t zvr = {
.zv = zv,
Expand Down

0 comments on commit 171f061

Please sign in to comment.