From 2a236649c137243d545c5abd8dd64587678cbeb3 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Fri, 27 May 2016 02:40:43 +0000 Subject: [PATCH] Merged revisions 6883,6885,6889,6892 via svnmerge from svn+ssh://svn.code.sf.net/p/scst/svn/trunk ........ r6883 | vlnb | 2016-05-03 19:43:06 -0700 (Tue, 03 May 2016) | 48 lines When trying to remove a megaraid_sas device, the scst will hang inside scst_free_device: [ 380.448608] [4]: scst: Detached from scsi0, channel 2, id 1, lun 0, type 0 [ 601.138688] INFO: task kworker/0:0:4 blocked for more than 120 seconds. [ 601.138756] Tainted: P OE 3.19.0-58-quantastor #64~14.04.1 [ 601.138810] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 601.138869] kworker/0:0 D ffff88085c6fba58 0 4 2 0x00000000 [ 601.138926] Workqueue: events megasas_aen_polling [megaraid_sas] [ 601.138930] ffff88085c6fba58 ffff88085c6f09d0 0000000000013e80 ffff88085c6fbfd8 [ 601.138934] 0000000000013e80 ffffffff81c1d4e0 ffff88085c6f09d0 ffff88085c6fba38 [ 601.138938] ffff88085c6fbbd8 7fffffffffffffff ffff88085c6fbbd0 ffff88085c6f09d0 [ 601.138942] Call Trace: [ 601.138955] [] schedule+0x29/0x70 [ 601.138960] [] schedule_timeout+0x244/0x2c0 [ 601.138968] [] ? irq_work_queue+0x6b/0x90 [ 601.138975] [] ? wake_up_klogd+0x32/0x40 [ 601.138979] [] ? console_unlock+0x208/0x480 [ 601.138983] [] wait_for_completion+0xa4/0x170 [ 601.138989] [] ? wake_up_state+0x20/0x20 [ 601.138995] [] flush_workqueue+0x10c/0x5b0 [ 601.139002] [] flush_scheduled_work+0x15/0x20 [ 601.139044] [] scst_free_device+0x16/0x50 [scst] [ 601.139051] [] scst_remove+0x2df/0x3a0 [scst] [ 601.139056] [] ? enclosure_find+0x93/0xa0 [enclosure] [ 601.139061] [] device_del+0xe1/0x270 [ 601.139062] [] device_unregister+0x22/0x70 [ 601.139066] [] __scsi_remove_device+0xbb/0xd0 [ 601.139068] [] scsi_remove_device+0x26/0x40 [ 601.139074] [] megasas_aen_polling+0x362/0x610 [megaraid_sas] [ 601.139076] [] process_one_work+0x14f/0x440 [ 601.139077] [] worker_thread+0x118/0x510 [ 601.139079] [] ? rescuer_thread+0x3d0/0x3d0 [ 601.139082] [] kthread+0xc9/0xe0 [ 601.139084] [] ? kthread_create_on_node+0x1c0/0x1c0 [ 601.139087] [] ret_from_fork+0x58/0x90 [ 601.139089] [] ? kthread_create_on_node+0x1c0/0x1c0 The problem is that scst_free_device will call flush_scheduled_work to wait for ext_blockers_work, but scst_free_device itself is called from schedule_work, thus creating deadlock. Instead of using heavy-handed flush_scheduled_work, we use flush_work to wait for ext_blockers_work to finish. Signed-off-by: Chunwei Chen ........ r6885 | vlnb | 2016-05-04 18:53:17 -0700 (Wed, 04 May 2016) | 3 lines Make copy manager update internal data on INQUIRY changing vdisk events ........ r6889 | vlnb | 2016-05-06 17:47:57 -0700 (Fri, 06 May 2016) | 3 lines qla2x00t: clarify that NPIV is not supported in this version ........ r6892 | vlnb | 2016-05-26 18:02:11 -0700 (Thu, 26 May 2016) | 6 lines scst: update README how to configure SCST, so VMware start using EXTENDED COPY between datastores Based on information from Artur Piechocki Tested-By: Isaac Goldbaum ........ git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.1.x@6894 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t/qla2x00-target/README | 5 +++ scst/README | 28 ++++++++++++ scst/README_in-tree | 28 ++++++++++++ scst/include/scst.h | 2 + scst/src/dev_handlers/scst_vdisk.c | 49 ++++++++++++++++++++- scst/src/scst_copy_mgr.c | 69 +++++++++++++++++++++++++++++- scst/src/scst_lib.c | 26 ++++++++++- scst/src/scst_priv.h | 2 + 8 files changed, 206 insertions(+), 3 deletions(-) diff --git a/qla2x00t/qla2x00-target/README b/qla2x00t/qla2x00-target/README index 741b0671e..1acbfeaf1 100644 --- a/qla2x00t/qla2x00-target/README +++ b/qla2x00t/qla2x00-target/README @@ -185,6 +185,11 @@ default. N_Port ID Virtualization ------------------------ +Unfortunately, due to severe problems in the original qla2xxx driver, +NPIV in this version is not supported. If you need NPIV, you can use +previous version 2.1 of this driver. + + N_Port ID Virtualization (NPIV) is a Fibre Channel facility allowing multiple N_Port IDs to share a single physical N_Port. NPIV is fully supported by this driver. You must have 24xx+ ISPs with NPIV-supporting diff --git a/scst/README b/scst/README index b6ca4f3b8..4dd08bf3a 100644 --- a/scst/README +++ b/scst/README @@ -1810,6 +1810,34 @@ benefit from SCST VAAI implementation. Those actions described in the implementation notes below. For vdisk and fileio_tgt handlers they have already been implemented. +IMPORTANT: To use EXTENDED COPY command between LUNs (datastores) they all +========= MUST have the same PRODUCT IDENTIFICATION INQUIRY field. By + default, to simplify remote devices identification, SCST uses + vdisk names as PRODUCT IDENTIFICATION, so SCST devices look + differently from the initiators. However, for some reasons, + VMware does not use EXTENDED COPY between LUNs with different + PRODUCT IDENTIFICATION. Thus, to be able to use full VAAI in + your VMware setups you must manually set PRODUCT + IDENTIFICATION for all your VMware LUNs to the same value, + for instance, "SCST", via using "prod_id" attribute. It could + be done either by adding "prod_id" attribute to scstadmin + scst.conf, or by directly writing to SCST sysfs attribute. + For example: + + HANDLER vdisk_blockio { + DEVICE blockio1 { + filename /dev/sda5 + prod_id SCST + } + + or + + echo SCST >/sys/kernel/scst_tgt/devices/blockio1/prod_id + correspondingly. + + Note, this prod_id modification must be done on all + datastores BEFORE VMware connects to them. + Implementation notes .................... diff --git a/scst/README_in-tree b/scst/README_in-tree index 0b62d61e7..19a2f71ff 100644 --- a/scst/README_in-tree +++ b/scst/README_in-tree @@ -1663,6 +1663,34 @@ benefit from SCST VAAI implementation. Those actions described in the implementation notes below. For vdisk and fileio_tgt handlers they have already been implemented. +IMPORTANT: To use EXTENDED COPY command between LUNs (datastores) they all +========= MUST have the same PRODUCT IDENTIFICATION INQUIRY field. By + default, to simplify remote devices identification, SCST uses + vdisk names as PRODUCT IDENTIFICATION, so SCST devices look + differently from the initiators. However, for some reasons, + VMware does not use EXTENDED COPY between LUNs with different + PRODUCT IDENTIFICATION. Thus, to be able to use full VAAI in + your VMware setups you must manually set PRODUCT + IDENTIFICATION for all your VMware LUNs to the same value, + for instance, "SCST", via using "prod_id" attribute. It could + be done either by adding "prod_id" attribute to scstadmin + scst.conf, or by directly writing to SCST sysfs attribute. + For example: + + HANDLER vdisk_blockio { + DEVICE blockio1 { + filename /dev/sda5 + prod_id SCST + } + + or + + echo SCST >/sys/kernel/scst_tgt/devices/blockio1/prod_id + correspondingly. + + Note, this prod_id modification must be done on all + datastores BEFORE VMware connects to them. + Implementation notes .................... diff --git a/scst/include/scst.h b/scst/include/scst.h index 34314dc78..3d709322e 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -5424,6 +5424,8 @@ void scst_reassign_retained_sess_states(struct scst_session *new_sess, int scst_get_max_lun_commands(struct scst_session *sess, uint64_t lun); +void scst_dev_inquiry_data_changed(struct scst_device *dev); + /* * Has to be put here open coded, because Linux doesn't have equivalent, which * allows exclusive wake ups of threads in LIFO order. We need it to let (yet) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index cf8508070..c551da8aa 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -233,6 +233,8 @@ struct scst_vdisk_dev { char *dif_filename; + struct work_struct vdev_inq_changed_work; + /* Only to pass it to attach() callback. Don't use them anywhere else! */ int blk_shift; enum scst_dif_mode dif_mode; @@ -652,7 +654,10 @@ static const struct attribute *vcdrom_attrs[] = { #endif /* CONFIG_SCST_PROC */ -/* Protects vdisks addition/deletion and related activities, like search */ +/* + * Protects vdisks addition/deletion and related activities, like search. + * Outer mutex regarding scst_mutex. + */ static DEFINE_MUTEX(scst_vdisk_mutex); /* @@ -7654,6 +7659,23 @@ static void vdisk_free_bioset(struct scst_vdisk_dev *virt_dev) } #endif +static void vdev_inq_changed_fn(struct work_struct *work) +{ + struct scst_vdisk_dev *virt_dev = container_of(work, + struct scst_vdisk_dev, vdev_inq_changed_work); + struct scst_device *dev = virt_dev->dev; + + TRACE_ENTRY(); + + TRACE_DBG("Updating INQUIRY data for virt_dev %p (dev %s)", + virt_dev, dev->virt_name); + + scst_dev_inquiry_data_changed(dev); + + TRACE_EXIT(); + return; +} + /* scst_vdisk_mutex supposed to be held */ static int vdev_create(struct scst_dev_type *devt, const char *name, struct scst_vdisk_dev **res_virt_dev) @@ -7687,6 +7709,7 @@ static int vdev_create(struct scst_dev_type *devt, virt_dev->thin_provisioned = DEF_THIN_PROVISIONED; virt_dev->tst = DEF_TST; virt_dev->expl_alua = DEF_EXPL_ALUA; + INIT_WORK(&virt_dev->vdev_inq_changed_work, vdev_inq_changed_fn); virt_dev->blk_shift = DEF_DISK_BLOCK_SHIFT; @@ -7748,6 +7771,8 @@ out_free: static void vdev_destroy(struct scst_vdisk_dev *virt_dev) { + cancel_work_sync(&virt_dev->vdev_inq_changed_work); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) vdisk_free_bioset(virt_dev); #endif @@ -9287,6 +9312,8 @@ static ssize_t vdev_sysfs_t10_vend_id_store(struct kobject *kobj, virt_dev->t10_vend_id_set = 1; write_unlock(&vdisk_serial_rwlock); + schedule_work(&virt_dev->vdev_inq_changed_work); + res = count; out: @@ -9346,6 +9373,8 @@ static ssize_t vdev_sysfs_vend_specific_id_store(struct kobject *kobj, virt_dev->vend_specific_id_set = 1; write_unlock(&vdisk_serial_rwlock); + schedule_work(&virt_dev->vdev_inq_changed_work); + res = count; out: @@ -9404,6 +9433,8 @@ static ssize_t vdev_sysfs_prod_id_store(struct kobject *kobj, virt_dev->prod_id_set = 1; write_unlock(&vdisk_serial_rwlock); + schedule_work(&virt_dev->vdev_inq_changed_work); + res = count; out: @@ -9462,6 +9493,8 @@ static ssize_t vdev_sysfs_prod_rev_lvl_store(struct kobject *kobj, virt_dev->prod_rev_lvl_set = 1; write_unlock(&vdisk_serial_rwlock); + schedule_work(&virt_dev->vdev_inq_changed_work); + res = count; out: @@ -9523,6 +9556,8 @@ static ssize_t vdev_sysfs_scsi_device_name_store(struct kobject *kobj, virt_dev->scsi_device_name_set = 0; write_unlock(&vdisk_serial_rwlock); + schedule_work(&virt_dev->vdev_inq_changed_work); + res = count; out: @@ -9593,6 +9628,8 @@ static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj, virt_dev->t10_dev_id_set = 1; + schedule_work(&virt_dev->vdev_inq_changed_work); + res = count; PRINT_INFO("T10 device id for device %s changed to %s", virt_dev->name, @@ -9675,6 +9712,9 @@ static ssize_t vdev_sysfs_eui64_id_store(struct kobject *kobj, #endif write_unlock(&vdisk_serial_rwlock); + if (res >= 0) + schedule_work(&virt_dev->vdev_inq_changed_work); + out: return res; } @@ -9756,6 +9796,9 @@ static ssize_t vdev_sysfs_naa_id_store(struct kobject *kobj, #endif write_unlock(&vdisk_serial_rwlock); + if (res >= 0) + schedule_work(&virt_dev->vdev_inq_changed_work); + out: return res; } @@ -9819,6 +9862,8 @@ static ssize_t vdev_sysfs_usn_store(struct kobject *kobj, virt_dev->usn_set = 1; + schedule_work(&virt_dev->vdev_inq_changed_work); + res = count; PRINT_INFO("USN for device %s changed to %s", virt_dev->name, @@ -9873,6 +9918,8 @@ static ssize_t vdev_sysfs_inq_vend_specific_store(struct kobject *kobj, virt_dev->inq_vend_specific_len = len; write_unlock(&vdisk_serial_rwlock); + schedule_work(&virt_dev->vdev_inq_changed_work); + res = count; out: diff --git a/scst/src/scst_copy_mgr.c b/scst/src/scst_copy_mgr.c index 0422aef72..e18b222c2 100644 --- a/scst/src/scst_copy_mgr.c +++ b/scst/src/scst_copy_mgr.c @@ -2518,6 +2518,36 @@ static bool scst_cm_is_lun_free(unsigned int lun) return res; } +/* scst_mutex supposed to be held and activities suspended */ +static unsigned int scst_cm_get_lun(const struct scst_device *dev) +{ + unsigned int res = -1; + int i; + bool found = false; + + TRACE_ENTRY(); + + for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { + struct list_head *head = &scst_cm_sess->sess_tgt_dev_list[i]; + struct scst_tgt_dev *tgt_dev; + list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) { + if (tgt_dev->dev == dev) { + res = tgt_dev->lun; + found = true; + TRACE_DBG("LUN %d found (full LUN %lld)", + res, tgt_dev->lun); + goto out; + } + } + } + + sBUG_ON(!found); + +out: + TRACE_EXIT_RES(res); + return res; +} + /* scst_mutex supposed to be held and activities suspended */ static int scst_cm_dev_register(struct scst_device *dev, uint64_t lun) { @@ -2583,6 +2613,7 @@ out_unblock: spin_lock_bh(&dev->dev_lock); scst_unblock_dev(dev); spin_unlock_bh(&dev->dev_lock); + scst_acg_del_lun(scst_cm_tgt->default_acg, lun, false); out_err: @@ -2629,6 +2660,41 @@ out: return; } +void scst_cm_update_dev(struct scst_device *dev) +{ + int rc; + + TRACE_ENTRY(); + + TRACE_MGMT_DBG("copy manager: updating device %s", dev->virt_name); + + scst_suspend_activity(SCST_SUSPEND_TIMEOUT_UNLIMITED); + mutex_lock(&scst_mutex); + + scst_cm_dev_unregister(dev, false); + + spin_lock_bh(&dev->dev_lock); + scst_block_dev(dev); + spin_unlock_bh(&dev->dev_lock); + + rc = scst_cm_send_init_inquiry(dev, scst_cm_get_lun(dev), NULL); + if (rc != 0) + goto out_unblock; + +out_resume: + mutex_unlock(&scst_mutex); + scst_resume_activity(); + + TRACE_EXIT(); + return; + +out_unblock: + spin_lock_bh(&dev->dev_lock); + scst_unblock_dev(dev); + spin_unlock_bh(&dev->dev_lock); + goto out_resume; +} + /* scst_mutex supposed to be held and activities suspended */ int scst_cm_on_dev_register(struct scst_device *dev) { @@ -3650,7 +3716,8 @@ static void scst_cm_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd) static int scst_cm_report_aen(struct scst_aen *aen) { /* Nothing to do */ - return 0; + scst_aen_done(aen); + return SCST_AEN_RES_SUCCESS; } static struct scst_tgt_template scst_cm_tgtt = { diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 843ceb886..2c9979601 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -2855,6 +2855,30 @@ void scst_requeue_ua(struct scst_cmd *cmd, const uint8_t *buf, int size) return; } +void scst_dev_inquiry_data_changed(struct scst_device *dev) +{ + struct scst_tgt_dev *tgt_dev; + + TRACE_ENTRY(); + + TRACE_MGMT_DBG("Updating INQUIRY data for dev %s", dev->virt_name); + + mutex_lock(&scst_mutex); + + list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) { + TRACE_DBG("INQUIRY DATA HAS CHANGED on tgt_dev %p", tgt_dev); + scst_gen_aen_or_ua(tgt_dev, SCST_LOAD_SENSE(scst_sense_inquiry_data_changed)); + } + + mutex_unlock(&scst_mutex); + + scst_cm_update_dev(dev); + + TRACE_EXIT(); + return; +} +EXPORT_SYMBOL(scst_dev_inquiry_data_changed); + /* The activity supposed to be suspended and scst_mutex held */ static void scst_check_reassign_sess(struct scst_session *sess) { @@ -4206,7 +4230,7 @@ void scst_free_device(struct scst_device *dev) #endif /* Ensure that ext_blockers_work is done */ - flush_scheduled_work(); + flush_work(&dev->ext_blockers_work); scst_deinit_threads(&dev->dev_cmd_threads); diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index df240b1fc..cccfc5c1f 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -857,6 +857,7 @@ static inline bool scst_lba1_inside_lba2(int64_t lba1, #ifndef CONFIG_SCST_PROC +void scst_cm_update_dev(struct scst_device *dev); int scst_cm_on_dev_register(struct scst_device *dev); void scst_cm_on_dev_unregister(struct scst_device *dev); @@ -890,6 +891,7 @@ void scst_cm_exit(void); #else /* #ifndef CONFIG_SCST_PROC */ +static inline void scst_cm_update_dev(struct scst_device *dev) {} static inline int scst_cm_on_dev_register(struct scst_device *dev) { return 0; } static inline void scst_cm_on_dev_unregister(struct scst_device *dev) {}