From 4cefa1b830a47385d15f5285c41a6201fed1047e Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Wed, 24 Oct 2012 21:22:23 +0000 Subject: [PATCH] vdisk_fsync() fixes and cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4567 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/dev_handlers/scst_vdisk.c | 100 ++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 23 deletions(-) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index d32218a12..383e0bf39 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -3251,7 +3251,30 @@ static enum compl_status_e vdisk_exec_prevent_allow_medium_removal(struct vdisk_ return CMD_SUCCEEDED; } -static int vdisk_fsync(struct vdisk_cmd_params *p, loff_t loff, +static int vdisk_fsync_blockio(struct vdisk_cmd_params *p, loff_t loff, + loff_t len, struct scst_device *dev, gfp_t gfp_flags, + struct scst_cmd *cmd, bool async) +{ + int res = 0; + struct scst_vdisk_dev *virt_dev = dev->dh_priv; + + TRACE_ENTRY(); + + /** + ** !!! CAUTION !!!: cmd can be NULL here! Don't use it for + ** anything without checking for NULL at first !!! + **/ + + EXTRACHECKS_BUG_ON(!virt_dev->blockio); + + res = vdisk_blockio_flush(virt_dev->bdev, gfp_flags, true, + cmd, async); + + TRACE_EXIT_RES(res); + return res; +} + +static int vdisk_fsync_fileio(struct vdisk_cmd_params *p, loff_t loff, loff_t len, struct scst_device *dev, gfp_t gfp_flags, struct scst_cmd *cmd, bool async) { @@ -3266,16 +3289,7 @@ static int vdisk_fsync(struct vdisk_cmd_params *p, loff_t loff, ** anything without checking for NULL at first !!! **/ - /* It should be generated by compiler as a single comparison */ - if (virt_dev->nv_cache || virt_dev->wt_flag || - virt_dev->o_direct_flag || virt_dev->nullio) - goto out; - - if (virt_dev->blockio) { - res = vdisk_blockio_flush(virt_dev->bdev, gfp_flags, true, - cmd, async); - goto out_check; - } + EXTRACHECKS_BUG_ON(virt_dev->blockio); file = virt_dev->fd; @@ -3290,7 +3304,6 @@ static int vdisk_fsync(struct vdisk_cmd_params *p, loff_t loff, #endif #endif -out_check: if (unlikely(res != 0)) { PRINT_ERROR("sync range failed (%d)", res); if (cmd != NULL) { @@ -3299,14 +3312,51 @@ out_check: else scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_write_error)); - if (async) { - cmd->completed = 1; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, - scst_estimate_context()); - } } } + if (async) { + if (cmd != NULL) { + cmd->completed = 1; + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, + scst_estimate_context()); + } + } + + TRACE_EXIT_RES(res); + return res; +} + +static int vdisk_fsync(struct vdisk_cmd_params *p, loff_t loff, + loff_t len, struct scst_device *dev, gfp_t gfp_flags, + struct scst_cmd *cmd, bool async) +{ + int res = 0; + struct scst_vdisk_dev *virt_dev = dev->dh_priv; + + TRACE_ENTRY(); + + /** + ** !!! CAUTION !!!: cmd can be NULL here! Don't use it for + ** anything without checking for NULL at first !!! + **/ + + /* It should be generated by compiler as a single comparison */ + if (virt_dev->nv_cache || virt_dev->wt_flag || + virt_dev->o_direct_flag || virt_dev->nullio) { + if (async) { + cmd->completed = 1; + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, + scst_estimate_context()); + } + goto out; + } + + if (virt_dev->blockio) + res = vdisk_fsync_blockio(p, loff, len, dev, gfp_flags, cmd, async); + else + res = vdisk_fsync_fileio(p, loff, len, dev, gfp_flags, cmd, async); + out: TRACE_EXIT_RES(res); return res; @@ -3907,6 +3957,7 @@ static int vdisk_blockio_flush(struct block_device *bdev, gfp_t gfp_mask, bio->bi_private = cmd; bio->bi_bdev = bdev; submit_bio(WRITE_FLUSH, bio); + goto out; } else { #else { @@ -3924,17 +3975,20 @@ static int vdisk_blockio_flush(struct block_device *bdev, gfp_t gfp_mask, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) out_rep: -#else - if (async && (res == 0)) { - cmd->completed = 1; - cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, - scst_estimate_context()); - } #endif if ((res != 0) && report_error) PRINT_ERROR("%s() failed: %d", async ? "bio_alloc" : "blkdev_issue_flush", res); + if (async && (cmd != NULL)) { + cmd->completed = 1; + cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, + scst_estimate_context()); + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +out: +#endif TRACE_EXIT_RES(res); return res; }