mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-26 18:12:42 +00:00
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] [<ffffffff817b5469>] schedule+0x29/0x70 [ 601.138960] [<ffffffff817b8574>] schedule_timeout+0x244/0x2c0 [ 601.138968] [<ffffffff8115fbcb>] ? irq_work_queue+0x6b/0x90 [ 601.138975] [<ffffffff810cb8e2>] ? wake_up_klogd+0x32/0x40 [ 601.138979] [<ffffffff810cbaf8>] ? console_unlock+0x208/0x480 [ 601.138983] [<ffffffff817b61c4>] wait_for_completion+0xa4/0x170 [ 601.138989] [<ffffffff810a1ea0>] ? wake_up_state+0x20/0x20 [ 601.138995] [<ffffffff8108d94c>] flush_workqueue+0x10c/0x5b0 [ 601.139002] [<ffffffff8108de05>] flush_scheduled_work+0x15/0x20 [ 601.139044] [<ffffffffc09314f6>] scst_free_device+0x16/0x50 [scst] [ 601.139051] [<ffffffffc091a86f>] scst_remove+0x2df/0x3a0 [scst] [ 601.139056] [<ffffffffc028c093>] ? enclosure_find+0x93/0xa0 [enclosure] [ 601.139061] [<ffffffff814f3971>] device_del+0xe1/0x270 [ 601.139062] [<ffffffff814f3b22>] device_unregister+0x22/0x70 [ 601.139066] [<ffffffff815549ab>] __scsi_remove_device+0xbb/0xd0 [ 601.139068] [<ffffffff815549e6>] scsi_remove_device+0x26/0x40 [ 601.139074] [<ffffffffc039fb22>] megasas_aen_polling+0x362/0x610 [megaraid_sas] [ 601.139076] [<ffffffff8108eeaf>] process_one_work+0x14f/0x440 [ 601.139077] [<ffffffff8108fab8>] worker_thread+0x118/0x510 [ 601.139079] [<ffffffff8108f9a0>] ? rescuer_thread+0x3d0/0x3d0 [ 601.139082] [<ffffffff81094b49>] kthread+0xc9/0xe0 [ 601.139084] [<ffffffff81094a80>] ? kthread_create_on_node+0x1c0/0x1c0 [ 601.139087] [<ffffffff817b9798>] ret_from_fork+0x58/0x90 [ 601.139089] [<ffffffff81094a80>] ? 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 <david.chen@osnexus.com> ........ 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 <artur.piechocki@open-e.com> Tested-By: Isaac Goldbaum <isaac.goldbaum@mail.ru> ........ git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.1.x@6894 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -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
|
||||
|
||||
+28
@@ -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
|
||||
....................
|
||||
|
||||
@@ -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
|
||||
....................
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
+25
-1
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user