From 660fd30d8539dd58e26a833787fb98a204e4c35e Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Thu, 21 Apr 2016 01:00:41 +0000 Subject: [PATCH] Merged revisions 6821,6824-6825,6827-6828,6835,6858,6863,6865-6867 via svnmerge from svn+ssh://svn.code.sf.net/p/scst/svn/trunk ........ r6821 | vlnb | 2016-03-01 20:13:42 -0800 (Tue, 01 Mar 2016) | 8 lines iscsi-scst: fix possible recursive locking cmnd_done() called from cmnd_put() can take cmd_list_lock, so it must not be called under it. Reported and tested by David Chen ........ r6824 | bvassche | 2016-03-08 10:24:23 -0800 (Tue, 08 Mar 2016) | 8 lines scst_vdisk: Fix kfree() argument in vdev_size_store() error path The wrong variable is freed in the vdev_size_store() error path. Pass 'new_size' instead of 'buf' to kfree(). Signed-off-by: Sebastian Parschauer [ bvanassche: edited patch description ] ........ r6825 | vlnb | 2016-03-09 21:00:01 -0800 (Wed, 09 Mar 2016) | 6 lines qla2x00t: decrease severity of 2 log messages Those messages don't necessare mean any error. Some harmless race conditions between the target driver and FW can lead to them as well. ........ r6827 | vlnb | 2016-03-10 19:10:04 -0800 (Thu, 10 Mar 2016) | 8 lines This limits target group state changes to only apply to targets local to the host. This prevents the devices being blocked offline by changes to non-local targets. Signed-off-by: Adrian Saul with some minor corrections ........ r6828 | vlnb | 2016-03-10 19:27:53 -0800 (Thu, 10 Mar 2016) | 3 lines scst_vdisk: warning clarification ........ r6835 | bvassche | 2016-03-23 21:08:12 -0700 (Wed, 23 Mar 2016) | 2 lines scst: Port to Linux kernel v4.6 ........ r6858 | bvassche | 2016-04-11 12:59:59 -0700 (Mon, 11 Apr 2016) | 5 lines scst: Kernel v4.6-rc3 build fix See also patch "mm: drop PAGE_CACHE_* and page_cache_{get,release} definition". ........ r6863 | vlnb | 2016-04-19 21:00:00 -0700 (Tue, 19 Apr 2016) | 3 lines scst_user: improve backward compatibility with handlers relying on obsolete SCST_USER_UNREGISTER_DEVICE call ........ r6865 | vlnb | 2016-04-19 21:29:34 -0700 (Tue, 19 Apr 2016) | 3 lines scst: decrease severity of "Copy Manager already registered" message, because it is harmless ........ r6866 | vlnb | 2016-04-19 21:34:43 -0700 (Tue, 19 Apr 2016) | 3 lines Follow-up for the previous commit ........ r6867 | vlnb | 2016-04-19 21:52:58 -0700 (Tue, 19 Apr 2016) | 5 lines scstadmin: prevent saving statistical dif_checks_failed attribute From Marc Smith ........ git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.1.x@6869 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/nthread.c | 2 +- scst/include/backport.h | 34 +++++++++++++++ scst/src/dev_handlers/scst_user.c | 24 ++++++++--- scst/src/dev_handlers/scst_vdisk.c | 67 ++++++++++++++--------------- scst/src/scst_copy_mgr.c | 8 +++- scst/src/scst_tg.c | 11 +++-- scstadmin/scstadmin.sysfs/scstadmin | 1 + 7 files changed, 102 insertions(+), 45 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 334dd3daa..09f998e47 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -1365,7 +1365,7 @@ retry: set_fs(KERNEL_DS); res = vfs_writev(file, (struct iovec __force __user *)iop, - count, &off); + count, &off, 0); set_fs(oldfs); TRACE_WRITE("sid %#Lx, cid %u, res %d, iov_len %zd", (unsigned long long int)conn->session->sid, diff --git a/scst/include/backport.h b/scst/include/backport.h index d379b735b..d81f27fd1 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -212,6 +212,25 @@ static inline struct inode *file_inode(const struct file *f) } #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) +static inline ssize_t vfs_readv_backport(struct file *file, + const struct iovec __user *vec, + unsigned long vlen, loff_t *pos, + int flags) +{ + return vfs_readv(file, vec, vlen, pos); +} +static inline ssize_t vfs_writev_backport(struct file *file, + const struct iovec __user *vec, + unsigned long vlen, loff_t *pos, + int flags) +{ + return vfs_writev(file, vec, vlen, pos); +} +#define vfs_readv vfs_readv_backport +#define vfs_writev vfs_writev_backport +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) static inline int vfs_fsync_backport(struct file *file, int datasync) { @@ -325,6 +344,21 @@ static inline bool list_entry_in_list(const struct list_head *entry) #define lockdep_assert_held(l) do { (void)(l); } while (0) #endif +/* */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) +static inline long get_user_pages_backport(unsigned long start, + unsigned long nr_pages, + int write, int force, + struct page **pages, + struct vm_area_struct **vmas) +{ + return get_user_pages(current, current->mm, start, nr_pages, write, + force, pages, vmas); +} +#define get_user_pages get_user_pages_backport +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index a319a9382..8fa13ce50 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -462,7 +462,7 @@ static void dev_user_unmap_buf(struct scst_user_cmd *ucmd) if (ucmd->buf_dirty) SetPageDirty(page); - page_cache_release(page); + put_page(page); } kfree(ucmd->data_pages); @@ -1267,8 +1267,8 @@ static int dev_user_map_buf(struct scst_user_cmd *ucmd, unsigned long ubuff, (ucmd->cmd != NULL) ? ucmd->cmd->bufflen : -1); down_read(&tsk->mm->mmap_sem); - rc = get_user_pages(tsk, tsk->mm, ubuff, ucmd->num_data_pages, - 1/*writable*/, 0/*don't force*/, ucmd->data_pages, NULL); + rc = get_user_pages(ubuff, ucmd->num_data_pages, 1/*writable*/, + 0/*don't force*/, ucmd->data_pages, NULL); up_read(&tsk->mm->mmap_sem); /* get_user_pages() flushes dcache */ @@ -1298,7 +1298,7 @@ out_unmap: ucmd->num_data_pages, rc); if (rc > 0) { for (i = 0; i < rc; i++) - page_cache_release(ucmd->data_pages[i]); + put_page(ucmd->data_pages[i]); } kfree(ucmd->data_pages); ucmd->data_pages = NULL; @@ -3533,9 +3533,23 @@ out_put: static int dev_user_unregister_dev(struct file *file) { + struct scst_user_dev *dev; + int res; + + dev = file->private_data; + res = dev_user_check_reg(dev); + if (unlikely(res != 0)) + goto out; + PRINT_WARNING("SCST_USER_UNREGISTER_DEVICE is obsolete and NOOP. " "Closing fd should be used instead."); - return 0; + + /* For backward compatibility unblock possibly blocked sync threads */ + dev->blocking = 0; + wake_up_all(&dev->udev_cmd_threads.cmd_list_waitQ); + +out: + return res; } static int dev_user_flush_cache(struct file *file) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 812466490..cf8508070 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -2023,8 +2023,8 @@ static int vdisk_format_dif(struct scst_cmd *cmd, uint64_t start_lba, full_len, (long long)loff); /* WRITE */ - err = vfs_writev(fd, (struct iovec __force __user *)iv, iv_count, - &loff); + err = vfs_writev(fd, (struct iovec __force __user *)iv, + iv_count, &loff, 0); if (err < 0) { PRINT_ERROR("Formatting DIF write() returned %lld from " "%zd", (long long)err, full_len); @@ -3053,7 +3053,7 @@ static void finish_read(struct scatterlist *sg, int sg_cnt) for (i = 0; i < sg_cnt; ++i) { page = sg_page(&sg[i]); EXTRACHECKS_BUG_ON(!page); - page_cache_release(page); + put_page(page); } TRACE_EXIT(); @@ -3093,13 +3093,13 @@ static int prepare_read_page(struct file *filp, int len, TRACE_ENTRY(); - WARN((offset & ~PAGE_CACHE_MASK) + len > PAGE_CACHE_SIZE, - "offset = %lld + %lld, len = %d\n", offset & PAGE_CACHE_MASK, - offset & ~PAGE_CACHE_MASK, len); + WARN((offset & ~PAGE_MASK) + len > PAGE_SIZE, + "offset = %lld + %lld, len = %d\n", offset & PAGE_MASK, + offset & ~PAGE_MASK, len); sBUG_ON(!mapping->a_ops); - index = offset >> PAGE_CACHE_SHIFT; - last_index = (last + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + index = offset >> PAGE_SHIFT; + last_index = (last + PAGE_SIZE - 1) >> PAGE_SHIFT; find_page: page = find_get_page(mapping, index); @@ -3119,7 +3119,7 @@ find_page: error = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL); if (error) { - page_cache_release(page); + put_page(page); if (error == -EEXIST) goto find_page; else @@ -3133,7 +3133,7 @@ find_page: page_cache_async_readahead(mapping, ra, filp, page, index, last_index - index); if (!PageUptodate(page)) { - if (inode->i_blkbits == PAGE_CACHE_SHIFT || + if (inode->i_blkbits == PAGE_SHIFT || !mapping->a_ops->is_partially_uptodate) goto page_not_up_to_date; if (!trylock_page(page)) @@ -3143,10 +3143,10 @@ find_page: goto page_not_up_to_date_locked; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) if (!mapping->a_ops->is_partially_uptodate(page, - offset & ~PAGE_CACHE_MASK, len)) + offset & ~PAGE_MASK, len)) #else if (!mapping->a_ops->is_partially_uptodate(page, &desc, - offset & ~PAGE_CACHE_MASK)) + offset & ~PAGE_MASK)) #endif goto page_not_up_to_date_locked; unlock_page(page); @@ -3162,20 +3162,19 @@ page_ok: */ isize = i_size_read(inode); - end_index = (isize - 1) >> PAGE_CACHE_SHIFT; + end_index = (isize - 1) >> PAGE_SHIFT; if (unlikely(isize == 0 || index > end_index)) { - page_cache_release(page); + put_page(page); goto eof; } /* nr is the maximum number of bytes to copy from this page */ if (index < end_index) { - nr = PAGE_CACHE_SIZE - (offset & ~PAGE_CACHE_MASK); + nr = PAGE_SIZE - (offset & ~PAGE_MASK); } else { - nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1 - - (offset & ~PAGE_CACHE_MASK); + nr = ((isize - 1) & ~PAGE_MASK) + 1 - (offset & ~PAGE_MASK); if (nr <= 0) { - page_cache_release(page); + put_page(page); goto eof; } } @@ -3205,7 +3204,7 @@ page_not_up_to_date: /* Try to get exclusive access to the page. */ error = lock_page_killable(page); if (unlikely(error != 0)) { - page_cache_release(page); + put_page(page); goto err; } @@ -3213,7 +3212,7 @@ page_not_up_to_date_locked: /* Did it get truncated before we got the lock? */ if (!page->mapping) { unlock_page(page); - page_cache_release(page); + put_page(page); goto find_page; } @@ -3234,18 +3233,18 @@ readpage: error = mapping->a_ops->readpage(filp, page); if (unlikely(error)) { if (error == AOP_TRUNCATED_PAGE) { - page_cache_release(page); + put_page(page); goto find_page; } WARN(error >= 0, "error = %d\n", error); - page_cache_release(page); + put_page(page); goto err; } if (!PageUptodate(page)) { error = lock_page_killable(page); if (unlikely(error != 0)) { - page_cache_release(page); + put_page(page); goto err; } if (!PageUptodate(page)) { @@ -3254,11 +3253,11 @@ readpage: * invalidate_mapping_pages got it */ unlock_page(page); - page_cache_release(page); + put_page(page); goto find_page; } unlock_page(page); - page_cache_release(page); + put_page(page); error = -EIO; goto err; } @@ -3291,7 +3290,7 @@ static int prepare_read(struct file *filp, struct scatterlist *sg, int sg_cnt, if (res <= 0) goto err; if (res < sg[i].length) { - page_cache_release(page); + put_page(page); goto err; } sg_assign_page(&sg[i], page); @@ -3622,8 +3621,8 @@ static int blockio_exec(struct scst_cmd *cmd) * "DRBD and other replication/failover SW * compatibility" section in SCST README. */ - PRINT_WARNING("Closed FD on exec. Secondary DRBD or not " - "blocked dev before ALUA state change? " + PRINT_WARNING("Closed FD on exec. Not active ALUA state " + "or not blocked dev before ALUA state change? " "(cmd %p, op %s, dev %s)", cmd, cmd->op_name, cmd->dev->virt_name); scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_no_medium)); @@ -5855,7 +5854,7 @@ static int vdev_read_dif_tags(struct vdisk_cmd_params *p) /* READ */ err = vfs_readv(fd, (struct iovec __force __user *)iv, iv_count, - &loff); + &loff, 0); if ((err < 0) || (err < full_len)) { unsigned long flags; @@ -5989,8 +5988,8 @@ restart: TRACE_DBG("Writing DIF: eiv_count %d, full_len %zd", eiv_count, full_len); /* WRITE */ - err = vfs_writev(fd, (struct iovec __force __user *)eiv, eiv_count, - &loff); + err = vfs_writev(fd, (struct iovec __force __user *)eiv, + eiv_count, &loff, 0); if (err < 0) { unsigned long flags; @@ -6136,7 +6135,7 @@ static enum compl_status_e fileio_exec_read(struct vdisk_cmd_params *p) /* READ */ err = vfs_readv(fd, (struct iovec __force __user *)iv, iv_count, - &loff); + &loff, 0); if ((err < 0) || (err < full_len)) { PRINT_ERROR("readv() returned %lld from %zd", (unsigned long long int)err, @@ -6329,8 +6328,8 @@ restart: TRACE_DBG("Writing: eiv_count %d, full_len %zd", eiv_count, full_len); /* WRITE */ - err = vfs_writev(fd, (struct iovec __force __user *)eiv, eiv_count, - &loff); + err = vfs_writev(fd, (struct iovec __force __user *)eiv, + eiv_count, &loff, 0); if (err < 0) { PRINT_ERROR("write() returned %lld from %zd", (unsigned long long int)err, diff --git a/scst/src/scst_copy_mgr.c b/scst/src/scst_copy_mgr.c index 6fcfbfea7..0422aef72 100644 --- a/scst/src/scst_copy_mgr.c +++ b/scst/src/scst_copy_mgr.c @@ -2535,9 +2535,13 @@ static int scst_cm_dev_register(struct scst_device *dev, uint64_t lun) list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { if (tgt_dev->dev == dev) { - PRINT_ERROR("Copy Manager already registered " + /* + * It's OK, because the copy manager could + * auto register some devices + */ + TRACE_DBG("Copy Manager already registered " "device %s", dev->virt_name); - res = -EEXIST; + res = 0; goto out; } } diff --git a/scst/src/scst_tg.c b/scst/src/scst_tg.c index 20bea55c5..825d6e396 100644 --- a/scst/src/scst_tg.c +++ b/scst/src/scst_tg.c @@ -965,6 +965,7 @@ static void __scst_tg_set_state(struct scst_target_group *tg, struct scst_tg_tgt *tg_tgt; struct scst_tgt *tgt; enum scst_tg_state old_state = tg->state; + bool dev_changed; sBUG_ON(state >= ARRAY_SIZE(scst_alua_filter)); lockdep_assert_held(&scst_dg_mutex); @@ -976,8 +977,7 @@ static void __scst_tg_set_state(struct scst_target_group *tg, list_for_each_entry(dg_dev, &tg->dg->dev_list, entry) { dev = dg_dev->dev; - if (dev->handler->on_alua_state_change_start != NULL) - dev->handler->on_alua_state_change_start(dev, old_state, state); + dev_changed = false; list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) { tgt = tgt_dev->sess->tgt; @@ -985,6 +985,11 @@ static void __scst_tg_set_state(struct scst_target_group *tg, if (tg_tgt->tgt == tgt) { bool gen_ua = (state != SCST_TG_STATE_TRANSITIONING); + if ((dev->handler->on_alua_state_change_start != NULL) && !dev_changed) { + dev->handler->on_alua_state_change_start(dev, old_state, state); + dev_changed = true; + } + if ((tg->dg->stpg_rel_tgt_id == tgt_dev->sess->tgt->rel_tgt_id) && tid_equal(tg->dg->stpg_transport_id, tgt_dev->sess->transport_id)) gen_ua = false; @@ -994,7 +999,7 @@ static void __scst_tg_set_state(struct scst_target_group *tg, } } } - if (dev->handler->on_alua_state_change_finish != NULL) + if ((dev->handler->on_alua_state_change_finish != NULL) && dev_changed) dev->handler->on_alua_state_change_finish(dev, old_state, state); } diff --git a/scstadmin/scstadmin.sysfs/scstadmin b/scstadmin/scstadmin.sysfs/scstadmin index b6bac0e8d..e65ce3fc8 100755 --- a/scstadmin/scstadmin.sysfs/scstadmin +++ b/scstadmin/scstadmin.sysfs/scstadmin @@ -1499,6 +1499,7 @@ sub serializeNkAttr { || defined($attr_filter) && defined($$attr_filter{$attribute})) && !defined($$attributes{$attribute}->{'keys'}) + && $attribute ne 'dif_checks_failed' && $attribute ne 'enabled' && $attribute ne 'hw_target') { my $value = $$attributes{$attribute}->{'value'};