diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 6df6a71d8..91aeac18f 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -316,9 +316,6 @@ static enum compl_status_e vdisk_exec_read_capacity16(struct vdisk_cmd_params *p static enum compl_status_e vdisk_exec_get_lba_status(struct vdisk_cmd_params *p); static enum compl_status_e vdisk_exec_report_tpgs(struct vdisk_cmd_params *p); static enum compl_status_e vdisk_exec_set_tpgs(struct vdisk_cmd_params *p); -static int vdisk_fsync(loff_t loff, - loff_t len, struct scst_device *dev, gfp_t gfp_flags, - struct scst_cmd *cmd, bool async); static int vdisk_unmap_range(struct scst_cmd *cmd, struct scst_vdisk_dev *virt_dev, uint64_t start_lba, uint32_t blocks); @@ -1397,6 +1394,153 @@ static void vdisk_detach_tgt(struct scst_tgt_dev *tgt_dev) return; } +static int __vdisk_fsync_fileio(loff_t loff, + loff_t len, struct scst_device *dev, struct scst_cmd *cmd, + struct file *file) +{ + int res; + + TRACE_ENTRY(); + + /** + ** !!! CAUTION !!!: cmd can be NULL here! Don't use it for + ** anything without checking for NULL at first !!! + **/ + + /* BLOCKIO can be here for DIF tags fsync */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) + res = sync_page_range(file_inode(file), file->f_mapping, loff, len); +#else +#if 0 /* For sparse files we might need to sync metadata as well */ + res = generic_write_sync(file, loff, len); +#else + res = filemap_write_and_wait_range(file->f_mapping, loff, len); +#endif +#endif + if (unlikely(res != 0)) { + PRINT_ERROR("sync range failed (%d)", res); + if (cmd != NULL) { + if (res == -ENOMEM) + scst_set_busy(cmd); + else + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_write_error)); + } + } + + TRACE_EXIT_RES(res); + return res; +} + +static int vdisk_fsync_blockio(loff_t loff, + loff_t len, struct scst_device *dev, gfp_t gfp_flags, + struct scst_cmd *cmd, bool async) +{ + int res; + 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); + + /* Must be first, because vdisk_blockio_flush() can call scst_cmd_done()! */ + if (virt_dev->dif_fd != NULL) { + loff = (loff >> dev->block_shift) << SCST_DIF_TAG_SHIFT; + len = (len >> dev->block_shift) << SCST_DIF_TAG_SHIFT; + res = __vdisk_fsync_fileio(loff, len, dev, cmd, + virt_dev->dif_fd); + if (unlikely(res != 0)) + goto out; + } + + res = vdisk_blockio_flush(virt_dev->bdev, gfp_flags, true, + cmd, async); + +out: + TRACE_EXIT_RES(res); + return res; +} + +static int vdisk_fsync_fileio(loff_t loff, + loff_t len, struct scst_device *dev, struct scst_cmd *cmd, bool async) +{ + int res; + 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 !!! + **/ + + res = __vdisk_fsync_fileio(loff, len, dev, cmd, virt_dev->fd); + if (unlikely(res != 0)) + goto done; + + if (virt_dev->dif_fd != NULL) { + loff = (loff >> dev->block_shift) << SCST_DIF_TAG_SHIFT; + len = (len >> dev->block_shift) << SCST_DIF_TAG_SHIFT; + res = __vdisk_fsync_fileio(loff, len, dev, cmd, + virt_dev->dif_fd); + } + +done: + 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(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->nullio) + ; + else if (virt_dev->blockio) + res = vdisk_fsync_blockio(loff, len, dev, gfp_flags, cmd, async); + else + res = vdisk_fsync_fileio(loff, len, dev, cmd, async); + +out: + TRACE_EXIT_RES(res); + return res; +} + static enum compl_status_e vdisk_synchronize_cache(struct vdisk_cmd_params *p) { struct scst_cmd *cmd = p->cmd; @@ -4774,153 +4918,6 @@ static enum compl_status_e vdisk_exec_prevent_allow_medium_removal(struct vdisk_ return CMD_SUCCEEDED; } -static int __vdisk_fsync_fileio(loff_t loff, - loff_t len, struct scst_device *dev, struct scst_cmd *cmd, - struct file *file) -{ - int res; - - TRACE_ENTRY(); - - /** - ** !!! CAUTION !!!: cmd can be NULL here! Don't use it for - ** anything without checking for NULL at first !!! - **/ - - /* BLOCKIO can be here for DIF tags fsync */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) - res = sync_page_range(file_inode(file), file->f_mapping, loff, len); -#else -#if 0 /* For sparse files we might need to sync metadata as well */ - res = generic_write_sync(file, loff, len); -#else - res = filemap_write_and_wait_range(file->f_mapping, loff, len); -#endif -#endif - if (unlikely(res != 0)) { - PRINT_ERROR("sync range failed (%d)", res); - if (cmd != NULL) { - if (res == -ENOMEM) - scst_set_busy(cmd); - else - scst_set_cmd_error(cmd, - SCST_LOAD_SENSE(scst_sense_write_error)); - } - } - - TRACE_EXIT_RES(res); - return res; -} - -static int vdisk_fsync_blockio(loff_t loff, - loff_t len, struct scst_device *dev, gfp_t gfp_flags, - struct scst_cmd *cmd, bool async) -{ - int res; - 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); - - /* Must be first, because vdisk_blockio_flush() can call scst_cmd_done()! */ - if (virt_dev->dif_fd != NULL) { - loff = (loff >> dev->block_shift) << SCST_DIF_TAG_SHIFT; - len = (len >> dev->block_shift) << SCST_DIF_TAG_SHIFT; - res = __vdisk_fsync_fileio(loff, len, dev, cmd, - virt_dev->dif_fd); - if (unlikely(res != 0)) - goto out; - } - - res = vdisk_blockio_flush(virt_dev->bdev, gfp_flags, true, - cmd, async); - -out: - TRACE_EXIT_RES(res); - return res; -} - -static int vdisk_fsync_fileio(loff_t loff, - loff_t len, struct scst_device *dev, struct scst_cmd *cmd, bool async) -{ - int res; - 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 !!! - **/ - - res = __vdisk_fsync_fileio(loff, len, dev, cmd, virt_dev->fd); - if (unlikely(res != 0)) - goto done; - - if (virt_dev->dif_fd != NULL) { - loff = (loff >> dev->block_shift) << SCST_DIF_TAG_SHIFT; - len = (len >> dev->block_shift) << SCST_DIF_TAG_SHIFT; - res = __vdisk_fsync_fileio(loff, len, dev, cmd, - virt_dev->dif_fd); - } - -done: - 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(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->nullio) - ; - else if (virt_dev->blockio) - res = vdisk_fsync_blockio(loff, len, dev, gfp_flags, cmd, async); - else - res = vdisk_fsync_fileio(loff, len, dev, cmd, async); - -out: - TRACE_EXIT_RES(res); - return res; -} - static struct iovec *vdisk_alloc_iv(struct scst_cmd *cmd, struct vdisk_cmd_params *p) {