From 48858f0aeceeb62fd7ad9f9a6488009cdc67d5c2 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 21 Mar 2019 02:53:32 +0000 Subject: [PATCH 1/4] scstadmin: Write output of test 09 into a file with 09 in its name git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8063 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- .../scstadmin.sysfs/scst-1.0.0/t/09-scstadmin-invalid-args.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scstadmin/scstadmin.sysfs/scst-1.0.0/t/09-scstadmin-invalid-args.t b/scstadmin/scstadmin.sysfs/scst-1.0.0/t/09-scstadmin-invalid-args.t index 8ab2fc455..89b23a8f1 100644 --- a/scstadmin/scstadmin.sysfs/scst-1.0.0/t/09-scstadmin-invalid-args.t +++ b/scstadmin/scstadmin.sysfs/scst-1.0.0/t/09-scstadmin-invalid-args.t @@ -15,7 +15,7 @@ my $redirect_file; my $redirect; BEGIN { - $redirect_file = "/tmp/scstadmin-test-06-output.txt"; + $redirect_file = "/tmp/scstadmin-test-09-output.txt"; unlink($redirect_file); $testdir = dirname(abs_path($0)); $scstadmin_pm_dir = dirname($testdir); From 43a252aef2a52eeada9b928b399da1fa862bd648 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 21 Mar 2019 02:54:31 +0000 Subject: [PATCH 2/4] scst, ib_srpt: Add support for kernel version v5.1 git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8064 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/backport.h | 13 ++++++++++--- scst/src/scst_lib.c | 6 ++++++ scst_local/scst_local.c | 5 +++-- srpt/src/ib_srpt.c | 2 +- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/scst/include/backport.h b/scst/include/backport.h index f4f6ce8fa..4ecbe034c 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -902,6 +902,11 @@ static inline struct ib_pd *ib_alloc_pd_backport(struct ib_device *device) }) #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) +#define ib_sg_dma_len(dev, sg) sg_dma_len(sg) +#define ib_sg_dma_address(dev, sg) sg_dma_address(sg) +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) && \ @@ -1245,10 +1250,12 @@ static inline void *vzalloc(unsigned long size) /* */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) || \ + LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) /* - * See also patch "[SCSI] bidirectional command support" - * (commit ID 6f9a35e2dafa). + * See also patch "[SCSI] bidirectional command support" (commit ID + * 6f9a35e2dafa). See also commit ae3d56d81507 ("scsi: remove bidirectional + * command support") # v5.1. */ static inline int scsi_bidi_cmnd(struct scsi_cmnd *cmd) { diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 9c86e5be4..63ae3c320 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -8606,6 +8606,7 @@ int scst_scsi_exec_async(struct scst_cmd *cmd, void *data, } if (cmd->data_direction == SCST_DATA_BIDI) { +#ifdef QUEUE_FLAG_BIDI struct request *next_rq; if (!test_bit(QUEUE_FLAG_BIDI, &q->queue_flags)) { @@ -8628,6 +8629,9 @@ int scst_scsi_exec_async(struct scst_cmd *cmd, void *data, goto out_free_unmap; } rq->next_rq = next_rq; +#else + return -EOPNOTSUPP; +#endif } else { rq = blk_map_kern_sg(q, cmd->sg, cmd->sg_cnt, gfp, reading); if (IS_ERR(rq)) { @@ -8668,6 +8672,7 @@ int scst_scsi_exec_async(struct scst_cmd *cmd, void *data, out: return res; +#ifdef QUEUE_FLAG_BIDI out_free_unmap: { struct bio *bio = rq->bio, *b; @@ -8690,6 +8695,7 @@ out_free_unmap: rq->bio = NULL; blk_put_request(rq); +#endif out_free_sioc: kmem_cache_free(scsi_io_context_cache, sioc); diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index d37afe927..9fa1e4209 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -1010,7 +1010,8 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *scmd, #endif if (scsi_bidi_cmnd(scmd)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 24) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 24) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) /* Some of these symbols are only defined after 2.6.24 */ dir = SCST_DATA_BIDI; scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(scmd)); @@ -1177,7 +1178,7 @@ static int scst_local_slave_alloc(struct scsi_device *sdev) #if !defined(RHEL_MAJOR) || RHEL_MAJOR -0 >= 6 queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdev->request_queue); #endif -#else +#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) blk_queue_flag_set(QUEUE_FLAG_BIDI, sdev->request_queue); #endif diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 03c8f3a4c..2f127e40a 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -3231,7 +3231,7 @@ static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch, struct srpt_send_ioctx *ioctx, struct scst_cmd *cmd) { - struct ib_device *dev; + struct ib_device *dev __maybe_unused; struct scatterlist *sg, *cur_sg; int sg_cnt; scst_data_direction dir; From 94018a42e35bf3e137ef011706d17b02a8208916 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 21 Mar 2019 02:56:02 +0000 Subject: [PATCH 3/4] scst: Use kernel_{read,write}() instead of scst_{read,write}() This patch does not change any functionality. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8065 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/backport.h | 18 ++++++++ scst/include/scst.h | 3 -- scst/src/dev_handlers/scst_vdisk.c | 17 +------- scst/src/scst_lib.c | 70 +++++++++--------------------- scst/src/scst_pres.c | 45 +++++++------------ 5 files changed, 54 insertions(+), 99 deletions(-) diff --git a/scst/include/backport.h b/scst/include/backport.h index 4ecbe034c..2e8603c03 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -452,6 +452,24 @@ kernel_read_backport(struct file *file, void *buf, size_t count, loff_t *pos) #define kernel_read(file, buf, count, pos) \ kernel_read_backport((file), (buf), (count), (pos)) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) +/* + * See also commit 7bb307e894d5 ("export kernel_write(), convert open-coded + * instances") # v3.9. + */ +static inline ssize_t +kernel_write_backport(struct file *file, const void *buf, size_t count, + loff_t *pos) +{ + return kernel_write(file, buf, count, *pos); +} + +#define kernel_write kernel_write_backport +#else +ssize_t kernel_write(struct file *file, const void *buf, size_t count, + loff_t *pos); +#endif #endif /* */ diff --git a/scst/include/scst.h b/scst/include/scst.h index bdb88a519..0db3a4a73 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -5599,9 +5599,6 @@ struct scst_data_descriptor { uint64_t sdd_blocks; }; -ssize_t scst_read(struct file *file, void *buf, size_t count, loff_t *pos); -ssize_t scst_write(struct file *file, const void *buf, size_t count, - loff_t *pos); ssize_t scst_readv(struct file *file, const struct iovec *vec, unsigned long vlen, loff_t *pos); ssize_t scst_writev(struct file *file, const struct iovec *vec, diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 385969140..d602c9237 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -2995,21 +2995,6 @@ out: return ret; } -/* Note: Updates *@loff if reading succeeded. */ -static ssize_t fileio_read_sync(struct file *fd, void *buf, size_t len, - loff_t *loff) -{ - mm_segment_t old_fs; - ssize_t ret; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = scst_read(fd, buf, len, loff); - set_fs(old_fs); - - return ret; -} - /* Note: Updates *@loff if reading succeeded except for NULLIO devices. */ static ssize_t vdev_read_sync(struct scst_vdisk_dev *virt_dev, void *buf, size_t len, loff_t *loff) @@ -3027,7 +3012,7 @@ static ssize_t vdev_read_sync(struct scst_vdisk_dev *virt_dev, void *buf, } return read; } else { - return fileio_read_sync(virt_dev->fd, buf, len, loff); + return kernel_read(virt_dev->fd, buf, len, loff); } } diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 63ae3c320..2979789a1 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -5933,44 +5933,31 @@ static int scst_cmp_fs_ds(void) return memcmp(&fs, &ds, sizeof(fs)); } -ssize_t scst_read(struct file *file, void *buf, size_t count, loff_t *pos) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) && !defined(RHEL_MAJOR) +ssize_t kernel_write(struct file *file, const void *buf, size_t count, + loff_t *pos) { + mm_segment_t old_fs = get_fs(); + ssize_t result; + set_fs(KERNEL_DS); + { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) struct iovec iov = { .iov_base = (void __force __user *)buf, .iov_len = count }; - WARN_ON_ONCE(scst_cmp_fs_ds() != 0); - - return scst_readv(file, &iov, 1, pos); + result = scst_writev(file, &iov, 1, pos); #else - WARN_ON_ONCE(scst_cmp_fs_ds() != 0); - - return vfs_read(file, (void __force __user *)buf, count, pos); + result = vfs_write(file, (void __force __user *)buf, count, pos); #endif + } + set_fs(old_fs); + + return result; } -EXPORT_SYMBOL(scst_read); - -ssize_t scst_write(struct file *file, const void *buf, size_t count, - loff_t *pos) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) - struct iovec iov = { - .iov_base = (void __force __user *)buf, - .iov_len = count - }; - - WARN_ON_ONCE(scst_cmp_fs_ds() != 0); - - return scst_writev(file, &iov, 1, pos); -#else - WARN_ON_ONCE(scst_cmp_fs_ds() != 0); - - return vfs_write(file, (void __force __user *)buf, count, pos); +EXPORT_SYMBOL(kernel_write); #endif -} -EXPORT_SYMBOL(scst_write); ssize_t scst_readv(struct file *file, const struct iovec *vec, unsigned long vlen, loff_t *pos) @@ -15044,7 +15031,6 @@ int scst_copy_file(const char *src, const char *dest) loff_t file_size, pos; uint8_t *buf = NULL; struct file *file_src = NULL, *file_dest = NULL; - mm_segment_t old_fs = get_fs(); TRACE_ENTRY(); @@ -15057,8 +15043,6 @@ int scst_copy_file(const char *src, const char *dest) TRACE_DBG("Copying '%s' into '%s'", src, dest); - set_fs(KERNEL_DS); - file_src = filp_open(src, O_RDONLY, 0); if (IS_ERR(file_src)) { res = PTR_ERR(file_src); @@ -15083,7 +15067,6 @@ int scst_copy_file(const char *src, const char *dest) } else { PRINT_ERROR("Invalid file mode 0x%x", inode->i_mode); res = -EINVAL; - set_fs(old_fs); goto out_skip; } @@ -15097,14 +15080,14 @@ int scst_copy_file(const char *src, const char *dest) } pos = 0; - res = scst_read(file_src, buf, file_size, &pos); + res = kernel_read(file_src, buf, file_size, &pos); if (res != file_size) { PRINT_ERROR("Unable to read file '%s' - error %d", src, res); goto out_skip; } pos = 0; - res = scst_write(file_dest, buf, file_size, &pos); + res = kernel_write(file_dest, buf, file_size, &pos); if (res != file_size) { PRINT_ERROR("Unable to write to '%s' - error %d", dest, res); goto out_skip; @@ -15126,8 +15109,6 @@ out_free: if (buf != NULL) vfree(buf); - set_fs(old_fs); - out: TRACE_EXIT_RES(res); return res; @@ -15174,7 +15155,6 @@ int scst_write_file_transactional(const char *name, const char *name1, { int res; struct file *file; - mm_segment_t old_fs = get_fs(); loff_t pos = 0; char n = '\n'; @@ -15184,8 +15164,6 @@ int scst_write_file_transactional(const char *name, const char *name1, if ((res != 0) && (res != -ENOENT)) goto out; - set_fs(KERNEL_DS); - file = filp_open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (IS_ERR(file)) { res = PTR_ERR(file); @@ -15198,7 +15176,7 @@ int scst_write_file_transactional(const char *name, const char *name1, pos = signature_len+1; - res = scst_write(file, buf, size, &pos); + res = kernel_write(file, buf, size, &pos); if (res != size) goto write_error; @@ -15209,11 +15187,11 @@ int scst_write_file_transactional(const char *name, const char *name1, } pos = 0; - res = scst_write(file, signature, signature_len, &pos); + res = kernel_write(file, signature, signature_len, &pos); if (res != signature_len) goto write_error; - res = scst_write(file, &n, sizeof(n), &pos); + res = kernel_write(file, &n, sizeof(n), &pos); if (res != sizeof(n)) goto write_error; @@ -15228,8 +15206,6 @@ int scst_write_file_transactional(const char *name, const char *name1, filp_close(file, NULL); out_set_fs: - set_fs(old_fs); - if (res == 0) scst_remove_file(name1); else @@ -15257,13 +15233,9 @@ static int __scst_read_file_transactional(const char *file_name, struct file *file = NULL; struct inode *inode; loff_t file_size, pos; - mm_segment_t old_fs; TRACE_ENTRY(); - old_fs = get_fs(); - set_fs(KERNEL_DS); - TRACE_DBG("Loading file '%s'", file_name); file = filp_open(file_name, O_RDONLY, 0); @@ -15295,7 +15267,7 @@ static int __scst_read_file_transactional(const char *file_name, } pos = 0; - res = scst_read(file, buf, file_size, &pos); + res = kernel_read(file, buf, file_size, &pos); if (res != file_size) { PRINT_ERROR("Unable to read file '%s' - error %d", file_name, res); if (res > 0) @@ -15313,8 +15285,6 @@ out_close: filp_close(file, NULL); out: - set_fs(old_fs); - TRACE_EXIT_RES(res); return res; } diff --git a/scst/src/scst_pres.c b/scst/src/scst_pres.c index 8b86d0530..b3022c644 100644 --- a/scst/src/scst_pres.c +++ b/scst/src/scst_pres.c @@ -664,7 +664,6 @@ static int scst_pr_do_load_device_file(struct scst_device *dev, char *buf = NULL; loff_t file_size, pos, data_size; uint64_t sign, version; - mm_segment_t old_fs; uint8_t pr_is_set, aptpl; __be64 key; uint16_t rel_tgt_id; @@ -675,9 +674,6 @@ static int scst_pr_do_load_device_file(struct scst_device *dev, scst_pr_remove_registrants(dev); - old_fs = get_fs(); - set_fs(KERNEL_DS); - TRACE_PR("Loading persistent file '%s'", file_name); file = filp_open(file_name, O_RDONLY, 0); @@ -715,7 +711,7 @@ static int scst_pr_do_load_device_file(struct scst_device *dev, } pos = 0; - rc = scst_read(file, buf, file_size, &pos); + rc = kernel_read(file, buf, file_size, &pos); if (rc != file_size) { PRINT_ERROR("Unable to read file '%s' - error %d", file_name, rc); @@ -822,8 +818,6 @@ out: if (buf != NULL) vfree(buf); - set_fs(old_fs); - TRACE_EXIT_RES(res); return res; } @@ -885,7 +879,6 @@ void scst_pr_sync_device_file(struct scst_device *dev) { int res = 0; struct file *file; - mm_segment_t old_fs = get_fs(); loff_t pos = 0; uint64_t sign; uint64_t version; @@ -903,14 +896,12 @@ void scst_pr_sync_device_file(struct scst_device *dev) scst_copy_file(dev->pr_file_name, dev->pr_file_name1); - set_fs(KERNEL_DS); - file = filp_open(dev->pr_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (IS_ERR(file)) { res = PTR_ERR(file); PRINT_ERROR("Unable to (re)create PR file '%s' - error %d", dev->pr_file_name, res); - goto out_set_fs; + goto out; } TRACE_PR("Updating pr file '%s'", dev->pr_file_name); @@ -920,7 +911,7 @@ void scst_pr_sync_device_file(struct scst_device *dev) */ sign = 0; pos = 0; - res = scst_write(file, &sign, sizeof(sign), &pos); + res = kernel_write(file, &sign, sizeof(sign), &pos); if (res != sizeof(sign)) goto write_error; @@ -928,7 +919,7 @@ void scst_pr_sync_device_file(struct scst_device *dev) * version */ version = SCST_PR_FILE_VERSION; - res = scst_write(file, &version, sizeof(version), &pos); + res = kernel_write(file, &version, sizeof(version), &pos); if (res != sizeof(version)) goto write_error; @@ -936,7 +927,7 @@ void scst_pr_sync_device_file(struct scst_device *dev) * APTPL */ aptpl = dev->pr_aptpl; - res = scst_write(file, &aptpl, sizeof(aptpl), &pos); + res = kernel_write(file, &aptpl, sizeof(aptpl), &pos); if (res != sizeof(aptpl)) goto write_error; @@ -944,15 +935,15 @@ void scst_pr_sync_device_file(struct scst_device *dev) * reservation */ pr_is_set = dev->pr_is_set; - res = scst_write(file, &pr_is_set, sizeof(pr_is_set), &pos); + res = kernel_write(file, &pr_is_set, sizeof(pr_is_set), &pos); if (res != sizeof(pr_is_set)) goto write_error; - res = scst_write(file, &dev->pr_type, sizeof(dev->pr_type), &pos); + res = kernel_write(file, &dev->pr_type, sizeof(dev->pr_type), &pos); if (res != sizeof(dev->pr_type)) goto write_error; - res = scst_write(file, &dev->pr_scope, sizeof(dev->pr_scope), &pos); + res = kernel_write(file, &dev->pr_scope, sizeof(dev->pr_scope), &pos); if (res != sizeof(dev->pr_scope)) goto write_error; @@ -966,24 +957,21 @@ void scst_pr_sync_device_file(struct scst_device *dev) is_holder = (dev->pr_holder == reg); - res = scst_write(file, &is_holder, - sizeof(is_holder), &pos); + res = kernel_write(file, &is_holder, sizeof(is_holder), &pos); if (res != sizeof(is_holder)) goto write_error; size = scst_tid_size(reg->transport_id); - res = scst_write(file, reg->transport_id, - size, &pos); + res = kernel_write(file, reg->transport_id, size, &pos); if (res != size) goto write_error; - res = scst_write(file, ®->key, - sizeof(reg->key), &pos); + res = kernel_write(file, ®->key, sizeof(reg->key), &pos); if (res != sizeof(reg->key)) goto write_error; - res = scst_write(file, ®->rel_tgt_id, - sizeof(reg->rel_tgt_id), &pos); + res = kernel_write(file, ®->rel_tgt_id, + sizeof(reg->rel_tgt_id), &pos); if (res != sizeof(reg->rel_tgt_id)) goto write_error; } @@ -996,7 +984,7 @@ void scst_pr_sync_device_file(struct scst_device *dev) sign = SCST_PR_FILE_SIGN; pos = 0; - res = scst_write(file, &sign, sizeof(sign), &pos); + res = kernel_write(file, &sign, sizeof(sign), &pos); if (res != sizeof(sign)) goto write_error; @@ -1010,9 +998,6 @@ void scst_pr_sync_device_file(struct scst_device *dev) filp_close(file, NULL); -out_set_fs: - set_fs(old_fs); - out: if (res != 0) { PRINT_CRIT_ERROR("Unable to save persistent information " @@ -1057,7 +1042,7 @@ write_error_close: dev->pr_file_name, rc); } #endif - goto out_set_fs; + goto out; } From a94c8eaf0f68ce931c3ac31fe1fbc3ec1cfaa092 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 21 Mar 2019 02:56:46 +0000 Subject: [PATCH 4/4] scst: Move the set_fs() calls into scst_{read,write}v() This patch does not change any functionality. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@8066 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/nthread.c | 4 --- scst/src/dev_handlers/scst_vdisk.c | 58 +++++++----------------------- scst/src/scst_lib.c | 56 ++++++++++++++++------------- 3 files changed, 44 insertions(+), 74 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 729324b26..e36727230 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -1099,7 +1099,6 @@ out: static int write_data(struct iscsi_conn *conn) { - mm_segment_t oldfs; struct file *file; struct iovec *iop; struct socket *sock; @@ -1142,10 +1141,7 @@ static int write_data(struct iscsi_conn *conn) sBUG_ON(count > ARRAY_SIZE(conn->write_iov)); retry: - oldfs = get_fs(); - set_fs(KERNEL_DS); res = scst_writev(file, iop, count, &off); - set_fs(oldfs); TRACE_WRITE("sid %#Lx, cid %u, res %d, iov_len %zd", (unsigned long long)conn->session->sid, conn->cid, res, iop->iov_len); diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index d602c9237..d17df0968 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -1677,7 +1677,6 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba, struct scst_device *dev = cmd->dev; struct scst_vdisk_dev *virt_dev = dev->dh_priv; loff_t loff; - mm_segment_t old_fs; loff_t err = 0; ssize_t full_len; struct file *fd = virt_dev->dif_fd; @@ -1719,9 +1718,6 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba, for (i = 0; i < max_iv_count; i++) iv[i].iov_base = (uint8_t __force __user *)data_buf; - old_fs = get_fs(); - set_fs(KERNEL_DS); - loff = start_lba << SCST_DIF_TAG_SHIFT; left = blocks << SCST_DIF_TAG_SHIFT; done = 0; @@ -1757,7 +1753,7 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba, scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_write_error)); res = err; - goto out_set_fs; + goto out_free_data_page; } else if (err < full_len) { /* * If a write() is interrupted by a signal handler before @@ -1773,9 +1769,7 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba, virt_dev->format_progress_done = done; } -out_set_fs: - set_fs(old_fs); - +out_free_data_page: __free_page(data_page); out_free_iv: @@ -5335,7 +5329,6 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p) int res = 0; struct scst_cmd *cmd = p->cmd; loff_t loff; - mm_segment_t old_fs; loff_t err = 0; ssize_t length, full_len; uint8_t *address; @@ -5378,9 +5371,6 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p) } max_iv_count = p->sync.iv_count; - old_fs = get_fs(); - set_fs(KERNEL_DS); - tags_sg = NULL; loff = (p->loff >> cmd->dev->block_shift) << SCST_DIF_TAG_SHIFT; while (1) { @@ -5428,7 +5418,7 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p) } spin_unlock_irqrestore(&vdev_err_lock, flags); res = err; - goto out_set_fs; + goto out_put_dif_buf; } for (i = 0; i < iv_count; i++) @@ -5438,14 +5428,11 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p) break; } - set_fs(old_fs); - out: TRACE_EXIT_RES(res); return res; -out_set_fs: - set_fs(old_fs); +out_put_dif_buf: for (i = 0; i < iv_count; i++) scst_put_dif_buf(cmd, (void __force *)(iv[i].iov_base)); goto out; @@ -5456,7 +5443,6 @@ static int vdev_write_dif_tags(struct vdisk_cmd_params *p) int res = 0; struct scst_cmd *cmd = p->cmd; loff_t loff; - mm_segment_t old_fs; loff_t err = 0; ssize_t length, full_len; uint8_t *address; @@ -5499,9 +5485,6 @@ static int vdev_write_dif_tags(struct vdisk_cmd_params *p) } max_iv_count = p->sync.iv_count; - old_fs = get_fs(); - set_fs(KERNEL_DS); - tags_sg = NULL; loff = (p->loff >> cmd->dev->block_shift) << SCST_DIF_TAG_SHIFT; while (1) { @@ -5550,7 +5533,7 @@ restart: } spin_unlock_irqrestore(&vdev_err_lock, flags); res = err; - goto out_set_fs; + goto out_put_dif_buf; } else if (err < full_len) { /* * Probably that's wrong, but sometimes write() returns @@ -5588,14 +5571,11 @@ restart: break; } - set_fs(old_fs); - out: TRACE_EXIT_RES(res); return res; -out_set_fs: - set_fs(old_fs); +out_put_dif_buf: for (i = 0; i < iv_count; i++) scst_put_dif_buf(cmd, (void __force *)(iv[i].iov_base)); goto out; @@ -5650,7 +5630,6 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p) struct scst_cmd *cmd = p->cmd; struct scst_device *dev = cmd->dev; loff_t loff = p->loff; - mm_segment_t old_fs; loff_t err = 0; ssize_t length, full_len; uint8_t *address; @@ -5685,9 +5664,6 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p) goto out; } - old_fs = get_fs(); - set_fs(KERNEL_DS); - while (1) { iv_count = 0; full_len = 0; @@ -5710,7 +5686,7 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p) PRINT_ERROR("scst_get_buf_next() failed: %zd", length); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_internal_failure)); - goto out_set_fs; + goto out_put_buf; } eiv = iv; @@ -5733,7 +5709,7 @@ restart: } else scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_write_error)); - goto out_set_fs; + goto out_put_buf; } else if (err < full_len) { /* * Probably that's wrong, but sometimes write() returns @@ -5772,8 +5748,6 @@ restart: length = scst_get_buf_next(cmd, &address); } - set_fs(old_fs); - if ((dev->dev_dif_mode & SCST_DIF_MODE_DEV_STORE) && (scst_get_dif_action(scst_get_dev_dif_actions(cmd->cmd_dif_actions)) != SCST_DIF_ACTION_NONE)) { err = vdev_write_dif_tags(p); @@ -5790,8 +5764,7 @@ out: TRACE_EXIT(); return CMD_SUCCEEDED; -out_set_fs: - set_fs(old_fs); +out_put_buf: for (i = 0; i < iv_count; i++) scst_put_buf(cmd, (void __force *)(iv[i].iov_base)); goto out_sync; @@ -6367,7 +6340,6 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p) { struct scst_cmd *cmd = p->cmd; loff_t loff = p->loff; - mm_segment_t old_fs; loff_t err = 0; ssize_t length, full_len; uint8_t __user *address; @@ -6399,9 +6371,6 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p) goto out; } - old_fs = get_fs(); - set_fs(KERNEL_DS); - while (1) { iv_count = 0; full_len = 0; @@ -6425,7 +6394,7 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p) PRINT_ERROR("scst_get_buf_next() failed: %zd", length); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_internal_failure)); - goto out_set_fs; + goto out_put_buf; } TRACE_DBG("Reading iv_count %d, full_len %zd", iv_count, full_len); @@ -6442,7 +6411,7 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p) scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_read_error)); } - goto out_set_fs; + goto out_put_buf; } for (i = 0; i < iv_count; i++) @@ -6454,8 +6423,6 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p) length = scst_get_buf_next(cmd, (uint8_t __force **)&address); } - set_fs(old_fs); - if ((dev->dev_dif_mode & SCST_DIF_MODE_DEV_STORE) && (scst_get_dif_action(scst_get_dev_dif_actions(cmd->cmd_dif_actions)) != SCST_DIF_ACTION_NONE)) { err = vdev_read_dif_tags(p); @@ -6469,8 +6436,7 @@ out: TRACE_EXIT(); return CMD_SUCCEEDED; -out_set_fs: - set_fs(old_fs); +out_put_buf: for (i = 0; i < iv_count; i++) scst_put_buf(cmd, (void __force *)(iv[i].iov_base)); goto out; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 2979789a1..f8287e598 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -5962,33 +5962,37 @@ EXPORT_SYMBOL(kernel_write); ssize_t scst_readv(struct file *file, const struct iovec *vec, unsigned long vlen, loff_t *pos) { + mm_segment_t old_fs = get_fs(); + ssize_t result; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; struct iov_iter iter; - ssize_t ret; WARN_ON_ONCE(scst_cmp_fs_ds() != 0); - ret = import_iovec(READ, (const struct iovec __force __user *)vec, vlen, - ARRAY_SIZE(iovstack), &iov, &iter); - if (ret < 0) - return ret; - ret = vfs_iter_read(file, &iter, pos, 0); - BUG_ON(iov == iovstack); - kfree(iov); - return ret; + result = import_iovec(READ, (const struct iovec __force __user *)vec, + vlen, ARRAY_SIZE(iovstack), &iov, &iter); + if (result >= 0) { + result = vfs_iter_read(file, &iter, pos, 0); + BUG_ON(iov == iovstack); + kfree(iov); + } #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) || \ (defined(CONFIG_SUSE_KERNEL) && \ LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) WARN_ON_ONCE(scst_cmp_fs_ds() != 0); - return vfs_readv(file, (const struct iovec __user *)vec, vlen, pos, 0); + result = vfs_readv(file, (const struct iovec __user *)vec, vlen, pos, + 0); #else WARN_ON_ONCE(scst_cmp_fs_ds() != 0); - return vfs_readv(file, (const struct iovec __user *)vec, vlen, pos); + result = vfs_readv(file, (const struct iovec __user *)vec, vlen, pos); #endif + set_fs(old_fs); + + return result; } EXPORT_SYMBOL(scst_readv); @@ -6005,31 +6009,35 @@ EXPORT_SYMBOL(scst_readv); ssize_t scst_writev(struct file *file, const struct iovec *vec, unsigned long vlen, loff_t *pos) { + mm_segment_t old_fs = get_fs(); + ssize_t result; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; struct iov_iter iter; - ssize_t ret; WARN_ON_ONCE(scst_cmp_fs_ds() != 0); - ret = import_iovec(WRITE, (const struct iovec __force __user *)vec, - vlen, ARRAY_SIZE(iovstack), &iov, &iter); - if (ret < 0) - return ret; - file_start_write(file); - ret = vfs_iter_write(file, &iter, pos, 0); - file_end_write(file); - BUG_ON(iov == iovstack); - kfree(iov); - return ret; + result = import_iovec(WRITE, (const struct iovec __force __user *)vec, + vlen, ARRAY_SIZE(iovstack), &iov, &iter); + if (result >= 0) { + file_start_write(file); + result = vfs_iter_write(file, &iter, pos, 0); + file_end_write(file); + BUG_ON(iov == iovstack); + kfree(iov); + } #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) || \ (defined(CONFIG_SUSE_KERNEL) && \ LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) - return vfs_writev(file, (const struct iovec __user *)vec, vlen, pos, 0); + result = vfs_writev(file, (const struct iovec __user *)vec, vlen, pos, + 0); #else - return vfs_writev(file, (const struct iovec __user *)vec, vlen, pos); + result = vfs_writev(file, (const struct iovec __user *)vec, vlen, pos); #endif + set_fs(old_fs); + + return result; } EXPORT_SYMBOL(scst_writev);