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) {}