diff options
Diffstat (limited to 'module/zfs')
-rw-r--r-- | module/zfs/zvol.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 9dda04077..0aaa268fa 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -534,6 +534,17 @@ zvol_write(void *arg) dmu_tx_t *tx; rl_t *rl; + if (req->cmd_flags & VDEV_REQ_FLUSH) + zil_commit(zv->zv_zilog, ZVOL_OBJ); + + /* + * Some requests are just for flush and nothing else. + */ + if (size == 0) { + blk_end_request(req, 0, size); + return; + } + rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_WRITER); tx = dmu_tx_create(zv->zv_objset); @@ -550,12 +561,14 @@ zvol_write(void *arg) error = dmu_write_req(zv->zv_objset, ZVOL_OBJ, req, tx); if (error == 0) - zvol_log_write(zv, tx, offset, size, rq_is_sync(req)); + zvol_log_write(zv, tx, offset, size, + req->cmd_flags & VDEV_REQ_FUA); dmu_tx_commit(tx); zfs_range_unlock(rl); - if (rq_is_sync(req) || zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS) + if ((req->cmd_flags & VDEV_REQ_FUA) || + zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS) zil_commit(zv->zv_zilog, ZVOL_OBJ); blk_end_request(req, -error, size); @@ -578,6 +591,11 @@ zvol_read(void *arg) int error; rl_t *rl; + if (size == 0) { + blk_end_request(req, 0, size); + return; + } + rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_READER); error = dmu_read_req(zv->zv_objset, ZVOL_OBJ, req); @@ -627,7 +645,7 @@ zvol_request(struct request_queue *q) while ((req = blk_fetch_request(q)) != NULL) { size = blk_rq_bytes(req); - if (blk_rq_pos(req) + blk_rq_sectors(req) > + if (size != 0 && blk_rq_pos(req) + blk_rq_sectors(req) > get_capacity(zv->zv_disk)) { printk(KERN_INFO "%s: bad access: block=%llu, count=%lu\n", @@ -1062,6 +1080,12 @@ zvol_alloc(dev_t dev, const char *name) if (zv->zv_queue == NULL) goto out_kmem; +#ifdef HAVE_BLK_QUEUE_FLUSH + blk_queue_flush(zv->zv_queue, VDEV_REQ_FLUSH | VDEV_REQ_FUA); +#else + blk_queue_ordered(zv->zv_queue, QUEUE_ORDERED_DRAIN, NULL); +#endif /* HAVE_BLK_QUEUE_FLUSH */ + zv->zv_disk = alloc_disk(ZVOL_MINORS); if (zv->zv_disk == NULL) goto out_queue; |