diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 8cc9a22b1..4e4cd6bbd 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -4527,6 +4527,47 @@ out: return res; } +/* + * Either add or replace a LUN. The repl_gen_ua argument controls whether or + * not a unit attention is triggered if LUN reassignment is performed. + */ +int scst_acg_repl_lun(struct scst_acg *acg, struct kobject *parent, + struct scst_device *dev, uint64_t lun, + unsigned flags) +{ + struct scst_acg_dev *acg_dev; + bool del_gen_ua = false; + int res = -EINVAL; + + scst_assert_activity_suspended(); + lockdep_assert_held(&scst_mutex); + + acg_dev = __scst_acg_del_lun(acg, lun, &del_gen_ua); + if (!acg_dev) + flags |= SCST_ADD_LUN_GEN_UA; + res = scst_acg_add_lun(acg, parent, dev, lun, flags, NULL); + if (res != 0) + goto out; + + if (acg_dev && (flags & SCST_REPL_LUN_GEN_UA)) { + struct scst_tgt_dev *tgt_dev; + + list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, + dev_tgt_dev_list_entry) { + if (tgt_dev->acg_dev->acg == acg && + tgt_dev->lun == lun) { + TRACE_MGMT_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)); + } + } + } + +out: + return res; +} + /* The activity supposed to be suspended and scst_mutex held */ int scst_alloc_add_acg(struct scst_tgt *tgt, const char *acg_name, bool tgt_acg, struct scst_acg **out_acg) diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index 9347d4daf..5a5c63a30 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -366,11 +366,16 @@ void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA); #define SCST_ADD_LUN_READ_ONLY 1 #define SCST_ADD_LUN_GEN_UA 2 #define SCST_ADD_LUN_CM 4 +#define SCST_REPL_LUN_GEN_UA 8 + int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent, struct scst_device *dev, uint64_t lun, unsigned int flags, struct scst_acg_dev **out_acg_dev); int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun, bool gen_report_luns_changed); +int scst_acg_repl_lun(struct scst_acg *acg, struct kobject *parent, + struct scst_device *dev, uint64_t lun, + unsigned flags); int scst_acg_add_acn(struct scst_acg *acg, const char *name); #ifdef CONFIG_SCST_PROC diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index e253b888d..73abe11f4 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -1436,57 +1436,17 @@ static int __scst_process_luns_mgmt_store(char *buffer, } case SCST_LUN_ACTION_REPLACE: { - bool dev_replaced = false; - unsigned int flags = 0; + unsigned int flags = (read_only ? SCST_ADD_LUN_READ_ONLY : 0) | + (replace_gen_ua ? SCST_REPL_LUN_GEN_UA : 0); res = scst_parse_add_repl_param(acg, dev, pp, &virt_lun, &read_only); if (res != 0) goto out_unlock; - acg_dev = NULL; - list_for_each_entry(acg_dev_tmp, &acg->acg_dev_list, - acg_dev_list_entry) { - if (acg_dev_tmp->lun == virt_lun) { - acg_dev = acg_dev_tmp; - break; - } - } - - if (acg_dev != NULL) { - /* Replace */ - res = scst_acg_del_lun(acg, acg_dev->lun, false); - if (res != 0) - goto out_unlock; - - dev_replaced = true; - } - - if (read_only) - flags |= SCST_ADD_LUN_READ_ONLY; - if (!dev_replaced) - flags |= SCST_ADD_LUN_GEN_UA; - res = scst_acg_add_lun(acg, - tgt_kobj ? tgt->tgt_luns_kobj : acg->luns_kobj, - dev, virt_lun, flags, NULL); - if (res != 0) - goto out_unlock; - - if (dev_replaced && replace_gen_ua) { - struct scst_tgt_dev *tgt_dev; - - list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) { - if ((tgt_dev->acg_dev->acg == acg) && - (tgt_dev->lun == virt_lun)) { - TRACE_MGMT_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)); - } - } - } - + res = scst_acg_repl_lun(acg, tgt_kobj ? tgt->tgt_luns_kobj : + acg->luns_kobj, dev, virt_lun, + flags); break; } case SCST_LUN_ACTION_DEL: