From 1c9b1f0baad8cc0674e0e0d44bf65fa3b0fa78a8 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Wed, 18 Nov 2015 04:09:50 +0000 Subject: [PATCH] scst: Rework Copy Manager's sysfs interface The old version had management incompatible with scstadmin and had issues with LUNs management. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6694 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/README | 25 ++-- scst/README_in-tree | 25 ++-- scst/src/scst_copy_mgr.c | 273 +++++++++++++++++---------------------- scst/src/scst_lib.c | 60 ++++++--- scst/src/scst_main.c | 10 +- scst/src/scst_priv.h | 20 ++- scst/src/scst_proc.c | 8 +- scst/src/scst_sysfs.c | 11 +- 8 files changed, 206 insertions(+), 226 deletions(-) diff --git a/scst/README b/scst/README index 395be9cc6..8da5009cc 100644 --- a/scst/README +++ b/scst/README @@ -1859,34 +1859,25 @@ EXTENDED COPY ~~~~~~~~~~~~~ SCST implements EXTENDED COPY via internal Copy Manager target. This -target has the following specific attributes in its sysfs: +target has the following specific attribute in its sysfs: - allow_not_connected_copy - if not set (default), an initiator can perform copy only between devices it has direct access to via any target/session. If set, any initiator can copy between any devices in the system. - - mgmt - this attribute allows to control data from which devices can -be copied using Copy Manager. By default, devices belonging to dev -handlers with flag auto_cm_assignment_possible set are auto assigned to -the Copy Manager on the registration. Currently, only vdisk has this -flag set, so all other devices (pass-through, user space, etc.) should -be assigned to the Copy Manager manually. - -Mgmt attribute supports the following commands: - - - add [vname|H:C:I:L] - adds device with name vname or H:C:I:L numbers -(pass-through) to the Copy Manager. - - - del [vname|H:C:I:L] - deletes device with name vname or H:C:I:L numbers -(pass-through) from the Copy Manager. - +The Copy Manager has access only to those devices, for which it has LUNs +in /sys/kernel/scst_tgt/targets/copy_manager/copy_manager_tgt/luns/. +Devices from scst_vdisk dev handler added to it automatically upon +registration, but for other devices you need to manually add LUNs there +the same way as for any target driver. You can also delete any device at +any time from the Copy Manager visibility by deleting the corresponding +LUN from the sysfs. It might be useful during ALUA state switching. Internally SCST implements EXTENDED COPY as generation of sets of internal READ(16) and WRITE(16) SCSI commands. Dev handlers don't need any manual actions to use it. - Also SCST provides for dev handlers possibility to remap blocks instead of copy them, if they support this feature. It allows them to perform EXTENDED COPY command much faster by just metadata update of their diff --git a/scst/README_in-tree b/scst/README_in-tree index d1bcc9d59..669f97f44 100644 --- a/scst/README_in-tree +++ b/scst/README_in-tree @@ -1712,34 +1712,25 @@ EXTENDED COPY ~~~~~~~~~~~~~ SCST implements EXTENDED COPY via internal Copy Manager target. This -target has the following specific attributes in its sysfs: +target has the following specific attribute in its sysfs: - allow_not_connected_copy - if not set (default), an initiator can perform copy only between devices it has direct access to via any target/session. If set, any initiator can copy between any devices in the system. - - mgmt - this attribute allows to control data from which devices can -be copied using Copy Manager. By default, devices belonging to dev -handlers with flag auto_cm_assignment_possible set are auto assigned to -the Copy Manager on the registration. Currently, only vdisk has this -flag set, so all other devices (pass-through, user space, etc.) should -be assigned to the Copy Manager manually. - -Mgmt attribute supports the following commands: - - - add [vname|H:C:I:L] - adds device with name vname or H:C:I:L numbers -(pass-through) to the Copy Manager. - - - del [vname|H:C:I:L] - deletes device with name vname or H:C:I:L numbers -(pass-through) from the Copy Manager. - +The Copy Manager has access only to those devices, for which it has LUNs +in /sys/kernel/scst_tgt/targets/copy_manager/copy_manager_tgt/luns/. +Devices from scst_vdisk dev handler added to it automatically upon +registration, but for other devices you need to manually add LUNs there +the same way as for any target driver. You can also delete any device at +any time from the Copy Manager visibility by deleting the corresponding +LUN from the sysfs. It might be useful during ALUA state switching. Internally SCST implements EXTENDED COPY as generation of sets of internal READ(16) and WRITE(16) SCSI commands. Dev handlers don't need any manual actions to use it. - Also SCST provides for dev handlers possibility to remap blocks instead of copy them, if they support this feature. It allows them to perform EXTENDED COPY command much faster by just metadata update of their diff --git a/scst/src/scst_copy_mgr.c b/scst/src/scst_copy_mgr.c index c59233ba8..6fcfbfea7 100644 --- a/scst/src/scst_copy_mgr.c +++ b/scst/src/scst_copy_mgr.c @@ -2519,14 +2519,16 @@ static bool scst_cm_is_lun_free(unsigned int lun) } /* scst_mutex supposed to be held and activities suspended */ -static int scst_cm_dev_register(struct scst_device *dev) +static int scst_cm_dev_register(struct scst_device *dev, uint64_t lun) { int res, i; - unsigned int lun; struct scst_acg_dev *acg_dev; + bool add_lun; TRACE_ENTRY(); + TRACE_DBG("dev %s, LUN %ld", dev->virt_name, (unsigned long)lun); + for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { struct scst_tgt_dev *tgt_dev; struct list_head *head = &scst_cm_sess->sess_tgt_dev_list[i]; @@ -2541,18 +2543,25 @@ static int scst_cm_dev_register(struct scst_device *dev) } } - while (1) { - lun = scst_cm_next_lun++; - if (lun == SCST_MAX_LUN) - continue; - if (scst_cm_is_lun_free(lun)) - break; - }; + if (lun == SCST_MAX_LUN) { + add_lun = true; + while (1) { + lun = scst_cm_next_lun++; + if (lun == SCST_MAX_LUN) + continue; + if (scst_cm_is_lun_free(lun)) + break; + } + } else + add_lun = false; - res = scst_acg_add_lun(scst_cm_tgt->default_acg, - scst_cm_tgt->tgt_luns_kobj, dev, lun, false, false, &acg_dev); - if (res != 0) - goto out_err; + if (add_lun) { + res = scst_acg_add_lun(scst_cm_tgt->default_acg, + scst_cm_tgt->tgt_luns_kobj, dev, lun, SCST_ADD_LUN_CM, + &acg_dev); + if (res != 0) + goto out_err; + } spin_lock_bh(&dev->dev_lock); scst_block_dev(dev); @@ -2578,13 +2587,15 @@ out_err: } /* scst_mutex supposed to be held and activities suspended */ -static void scst_cm_dev_unregister(struct scst_device *dev) +static void scst_cm_dev_unregister(struct scst_device *dev, bool del_lun) { int i; struct scst_cm_desig *des, *t; TRACE_ENTRY(); + TRACE_DBG("dev %s, del_lun %d", dev->virt_name, del_lun); + list_for_each_entry_safe(des, t, &scst_cm_desig_list, cm_desig_list_entry) { if (des->desig_tgt_dev->dev == dev) { TRACE_DBG("Deleting des %p", des); @@ -2593,6 +2604,9 @@ static void scst_cm_dev_unregister(struct scst_device *dev) } } + if (!del_lun) + goto out; + for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) { struct scst_tgt_dev *tgt_dev; struct list_head *head = &scst_cm_sess->sess_tgt_dev_list[i]; @@ -2606,6 +2620,7 @@ static void scst_cm_dev_unregister(struct scst_device *dev) } } +out: TRACE_EXIT(); return; } @@ -2620,7 +2635,7 @@ int scst_cm_on_dev_register(struct scst_device *dev) if (!dev->handler->auto_cm_assignment_possible) goto out; - res = scst_cm_dev_register(dev); + res = scst_cm_dev_register(dev, SCST_MAX_LUN); out: TRACE_EXIT_RES(res); @@ -2632,12 +2647,87 @@ void scst_cm_on_dev_unregister(struct scst_device *dev) { TRACE_ENTRY(); - scst_cm_dev_unregister(dev); + scst_cm_dev_unregister(dev, true); TRACE_EXIT(); return; } +/* scst_mutex supposed to be held and activities suspended */ +int scst_cm_on_add_acg(struct scst_acg *acg) +{ + int res = 0; + + TRACE_ENTRY(); + + if (scst_cm_tgt == NULL) + goto out; + + if (acg->tgt != scst_cm_tgt) + goto out; + + if (acg != scst_cm_tgt->default_acg) { + PRINT_ERROR("Copy Manager does not support security groups"); + res = -EINVAL; + goto out; + } + +out: + TRACE_EXIT_RES(res); + return res; +} + +/* scst_mutex supposed to be held and activities suspended */ +void scst_cm_on_del_acg(struct scst_acg *acg) +{ + /* Nothing to do */ +} + +/* scst_mutex supposed to be held and activities suspended */ +int scst_cm_on_add_lun(struct scst_acg_dev *acg_dev, uint64_t lun, + unsigned int *flags) +{ + int res = 0; + + TRACE_ENTRY(); + + if (acg_dev->acg != scst_cm_tgt->default_acg) + goto out; + + if (acg_dev->acg_dev_rd_only || acg_dev->dev->dev_rd_only) { + PRINT_ERROR("Copy Manager does not support read only devices"); + res = -EINVAL; + goto out; + } + + *flags &= ~SCST_ADD_LUN_GEN_UA; + + res = scst_cm_dev_register(acg_dev->dev, lun); + +out: + TRACE_EXIT_RES(res); + return res; +} + +/* scst_mutex supposed to be held and activities suspended */ +bool scst_cm_on_del_lun(struct scst_acg_dev *acg_dev, bool gen_report_luns_changed) +{ + bool res = gen_report_luns_changed; + + TRACE_ENTRY(); + + if (acg_dev->acg != scst_cm_tgt->default_acg) + goto out; + + scst_cm_dev_unregister(acg_dev->dev, false); + + res = false; + +out: + TRACE_EXIT_RES(res); + return res; +} + /* scst_mutex supposed to be locked */ static bool scst_cm_check_access_acg(const char *initiator_name, const struct scst_device *dev, const struct scst_acg *acg, @@ -3480,148 +3570,8 @@ static struct kobj_attribute scst_cm_allow_not_conn_copy_attr = scst_cm_allow_not_conn_copy_show, scst_cm_allow_not_conn_copy_store); -static ssize_t scst_cm_mgmt_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - static const char help[] = - "Usage: echo \"add H:C:I:L\" >mgmt\n" - " echo \"add VNAME\" >mgmt\n" - " echo \"del H:C:I:L\" >mgmt\n" - " echo \"del VNAME\" >mgmt\n"; - - return sprintf(buf, "%s", help); -} - -static int scst_cm_mgmt(struct scst_sysfs_work_item *work) -{ - int res = 0; - char *pp, *action, *devstr; - unsigned int host, channel, id, lun; - char *buf = work->buf; - bool vdev; - struct scst_device *d, *dev = NULL; - - TRACE_ENTRY(); - - TRACE_DBG("buffer %s", buf); - - pp = buf; - action = scst_get_next_lexem(&pp); - devstr = scst_get_next_lexem(&pp); - if (*devstr == '\0') { - PRINT_ERROR("%s", "Device required"); - res = -EINVAL; - goto out; - } - - if (*scst_get_next_lexem(&pp) != '\0') { - PRINT_ERROR("%s", "Too many parameters"); - res = -EINVAL; - goto out_syntax_err; - } - - if (sscanf(devstr, "%u:%u:%u:%u", &host, &channel, &id, &lun) != 4) { - vdev = true; - TRACE_DBG("Virt dev %s", devstr); - } else { - vdev = false; - TRACE_DBG("Pass-through dev %d:%d:%d:%d", host, channel, id, lun); - } - - res = scst_suspend_activity(SCST_SUSPEND_TIMEOUT_USER); - if (res != 0) - goto out; - - res = mutex_lock_interruptible(&scst_mutex); - if (res != 0) - goto out_resume; - - list_for_each_entry(d, &scst_dev_list, dev_list_entry) { - if (vdev) { - if ((d->scsi_dev == NULL) && - (strcmp(d->virt_name, devstr) == 0)) { - dev = d; - break; - } - } else if (d->scsi_dev != NULL && - d->scsi_dev->host->host_no == host && - d->scsi_dev->channel == channel && - d->scsi_dev->id == id && - d->scsi_dev->lun == lun) { - dev = d; - break; - } - } - if (dev == NULL) { - PRINT_ERROR("Device %s not found", devstr); - res = -EINVAL; - goto out_unlock; - } else - TRACE_DBG("Dev %p (%s) found", dev, dev->virt_name); - - if (strcasecmp("add", action) == 0) - res = scst_cm_dev_register(dev); - else if (strcasecmp("del", action) == 0) - scst_cm_dev_unregister(dev); - else { - PRINT_ERROR("Action %s not understood", action); - res = -EINVAL; - } - -out_unlock: - mutex_unlock(&scst_mutex); - -out_resume: - scst_resume_activity(); - -out: - TRACE_EXIT_RES(res); - return res; - -out_syntax_err: - PRINT_ERROR("Syntax error on \"%s\"", buf); - res = -EINVAL; - goto out; -} - -static ssize_t scst_cm_mgmt_store(struct kobject *kobj, - struct kobj_attribute *attr, const char *buffer, size_t size) -{ - int res; - struct scst_sysfs_work_item *work; - char *i_buf; - - TRACE_ENTRY(); - - i_buf = kasprintf(GFP_KERNEL, "%.*s", (int)size, buffer); - if (i_buf == NULL) { - PRINT_ERROR("Unable to alloc intermediate buffer with size %zd", - size+1); - res = -ENOMEM; - goto out; - } - - res = scst_alloc_sysfs_work(scst_cm_mgmt, false, &work); - if (res != 0) - goto out; - - work->buf = i_buf; - - res = scst_sysfs_queue_wait_work(work); - if (res == 0) - res = size; - -out: - TRACE_EXIT_RES(res); - return res; -} - -static struct kobj_attribute scst_cm_mgmt_attr = - __ATTR(mgmt, S_IRUGO|S_IWUSR, scst_cm_mgmt_show, scst_cm_mgmt_store); - -static const struct attribute *scst_cm_attrs[] = { +static const struct attribute *scst_cm_tgtt_attrs[] = { &scst_cm_allow_not_conn_copy_attr.attr, - &scst_cm_mgmt_attr.attr, NULL, }; @@ -3693,6 +3643,12 @@ static void scst_cm_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd) return; } +static int scst_cm_report_aen(struct scst_aen *aen) +{ + /* Nothing to do */ + return 0; +} + static struct scst_tgt_template scst_cm_tgtt = { .name = SCST_CM_NAME, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) @@ -3710,9 +3666,10 @@ static struct scst_tgt_template scst_cm_tgtt = { .release = scst_cm_release, .xmit_response = scst_cm_xmit_response, .task_mgmt_fn_done = scst_cm_task_mgmt_fn_done, + .report_aen = scst_cm_report_aen, .get_initiator_port_transport_id = scst_cm_get_initiator_port_transport_id, #ifndef CONFIG_SCST_PROC - .tgtt_attrs = scst_cm_attrs, + .tgtt_attrs = scst_cm_tgtt_attrs, #endif }; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 8cd269cc7..2a5599948 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -4373,8 +4373,8 @@ out: /* The activity supposed to be suspended and scst_mutex held */ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent, - struct scst_device *dev, uint64_t lun, int read_only, - bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev) + struct scst_device *dev, uint64_t lun, unsigned int flags, + struct scst_acg_dev **out_acg_dev) { int res; struct scst_acg_dev *acg_dev; @@ -4395,7 +4395,7 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent, res = -ENOMEM; goto out; } - acg_dev->acg_dev_rd_only = read_only; + acg_dev->acg_dev_rd_only = ((flags & SCST_ADD_LUN_READ_ONLY) != 0); if (dev->dev_dif_mode & SCST_DIF_MODE_DEV_STORE) { /* Devices are allowed to store only CRCs */ acg_dev->acg_dev_dif_guard_format = SCST_DIF_GUARD_FORMAT_CRC; @@ -4410,6 +4410,12 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent, list_add_tail(&acg_dev->acg_dev_list_entry, &acg->acg_dev_list); list_add_tail(&acg_dev->dev_acg_dev_list_entry, &dev->dev_acg_dev_list); + if (!(flags & SCST_ADD_LUN_CM)) { + res = scst_cm_on_add_lun(acg_dev, lun, &flags); + if (res != 0) + goto out_free; + } + list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) { res = scst_alloc_add_tgt_dev(sess, acg_dev, &tgt_dev); if (res == -EPERM) @@ -4423,14 +4429,14 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent, res = scst_acg_dev_sysfs_create(acg_dev, parent); if (res != 0) - goto out_free; + goto out_on_del; - if (gen_scst_report_luns_changed) + if (flags & SCST_ADD_LUN_GEN_UA) scst_report_luns_changed(acg); PRINT_INFO("Added device %s to group %s (LUN %lld, " - "rd_only %d) to target %s", dev->virt_name, acg->acg_name, - lun, read_only, acg->tgt ? acg->tgt->tgt_name : "?"); + "flags 0x%x) to target %s", dev->virt_name, acg->acg_name, + lun, flags, acg->tgt ? acg->tgt->tgt_name : "?"); if (out_acg_dev != NULL) *out_acg_dev = acg_dev; @@ -4439,6 +4445,10 @@ out: TRACE_EXIT_RES(res); return res; +out_on_del: + if (!(flags & SCST_ADD_LUN_CM)) + scst_cm_on_del_lun(acg_dev, false); + out_free: list_for_each_entry_safe(tgt_dev, tt, &tmp_tgt_dev_list, extra_tgt_dev_list_entry) { @@ -4450,7 +4460,7 @@ out_free: /* The activity supposed to be suspended and scst_mutex held */ int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun, - bool gen_scst_report_luns_changed) + bool gen_report_luns_changed) { int res = 0; struct scst_acg_dev *acg_dev = NULL, *a; @@ -4470,6 +4480,8 @@ int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun, goto out; } + gen_report_luns_changed = scst_cm_on_del_lun(acg_dev, gen_report_luns_changed); + list_for_each_entry_safe(tgt_dev, tt, &acg_dev->dev->dev_tgt_dev_list, dev_tgt_dev_list_entry) { if (tgt_dev->acg_dev == acg_dev) @@ -4478,7 +4490,7 @@ int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun, scst_del_free_acg_dev(acg_dev, true); - if (gen_scst_report_luns_changed) + if (gen_report_luns_changed) scst_report_luns_changed(acg); PRINT_INFO("Removed LUN %lld from group %s (target %s)", @@ -4490,16 +4502,18 @@ out: } /* The activity supposed to be suspended and scst_mutex held */ -struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt, - const char *acg_name, bool tgt_acg) +int scst_alloc_add_acg(struct scst_tgt *tgt, const char *acg_name, + bool tgt_acg, struct scst_acg **out_acg) { struct scst_acg *acg; + int res; TRACE_ENTRY(); acg = kzalloc(sizeof(*acg), GFP_KERNEL); if (acg == NULL) { PRINT_ERROR("%s", "Allocation of acg failed"); + res = -ENOMEM; goto out; } @@ -4512,9 +4526,14 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt, acg->acg_name = kstrdup(acg_name, GFP_KERNEL); if (acg->acg_name == NULL) { PRINT_ERROR("%s", "Allocation of acg_name failed"); + res = -ENOMEM; goto out_free; } + res = scst_cm_on_add_acg(acg); + if (res != 0) + goto out_undup; + #ifdef CONFIG_SCST_PROC acg->addr_method = tgt && tgt->tgtt ? tgt->tgtt->preferred_addr_method : SCST_LUN_ADDR_METHOD_PERIPHERAL; @@ -4527,30 +4546,35 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt, acg->addr_method = tgt->tgtt->preferred_addr_method; if (tgt_acg) { - int rc; - TRACE_DBG("Adding acg '%s' to device '%s' acg_list", acg_name, tgt->tgt_name); list_add_tail(&acg->acg_list_entry, &tgt->tgt_acg_list); acg->tgt_acg = 1; - rc = scst_acg_sysfs_create(tgt, acg); - if (rc != 0) + res = scst_acg_sysfs_create(tgt, acg); + if (res != 0) goto out_del; } kobject_get(&tgt->tgt_kobj); #endif + res = 0; + out: - TRACE_EXIT_HRES(acg); - return acg; + *out_acg = acg; + + TRACE_EXIT_RES(res); + return res; #ifndef CONFIG_SCST_PROC out_del: list_del(&acg->acg_list_entry); #endif +out_undup: + kfree(acg->acg_name); + out_free: kfree(acg); acg = NULL; @@ -4573,6 +4597,8 @@ static void scst_del_acg(struct scst_acg *acg) scst_assert_activity_suspended(); lockdep_assert_held(&scst_mutex); + scst_cm_on_del_acg(acg); + list_for_each_entry_safe(acg_dev, acg_dev_tmp, &acg->acg_dev_list, acg_dev_list_entry) scst_del_acg_dev(acg_dev, true); diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 4bfde9df1..b5b3851e9 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -550,8 +550,8 @@ struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt, if (rc < 0) goto out_unlock; - tgt->default_acg = scst_alloc_add_acg(tgt, tgt->tgt_name, false); - if (tgt->default_acg == NULL) + rc = scst_alloc_add_acg(tgt, tgt->tgt_name, false, &tgt->default_acg); + if (rc != 0) goto out_sysfs_del; #endif @@ -2650,11 +2650,9 @@ static int __init init_scst(void) goto out_sysfs_cleanup; #ifdef CONFIG_SCST_PROC - scst_default_acg = scst_alloc_add_acg(NULL, SCST_DEFAULT_ACG_NAME, false); - if (scst_default_acg == NULL) { - res = -ENOMEM; + res = scst_alloc_add_acg(NULL, SCST_DEFAULT_ACG_NAME, false, &scst_default_acg); + if (res != 0) goto out_destroy_sgv_pool; - } #endif res = scsi_register_interface(&scst_interface); diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index 6740845c6..ae1157d36 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -347,8 +347,8 @@ int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev); void scst_free_device(struct scst_device *dev); bool scst_device_is_exported(struct scst_device *dev); -struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt, - const char *acg_name, bool tgt_acg); +int scst_alloc_add_acg(struct scst_tgt *tgt, const char *acg_name, + bool tgt_acg, struct scst_acg **out_acg); int scst_del_free_acg(struct scst_acg *acg, bool close_sessions); void scst_get_acg(struct scst_acg *acg); void scst_put_acg(struct scst_acg *acg); @@ -363,11 +363,14 @@ void scst_sess_free_tgt_devs(struct scst_session *sess); struct scst_tgt_dev *scst_lookup_tgt_dev(struct scst_session *sess, u64 lun); 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 int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent, - struct scst_device *dev, uint64_t lun, int read_only, - bool gen_scst_report_luns_changed, struct scst_acg_dev **out_acg_dev); + 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_scst_report_luns_changed); + bool gen_report_luns_changed); int scst_acg_add_acn(struct scst_acg *acg, const char *name); #ifdef CONFIG_SCST_PROC @@ -857,6 +860,13 @@ static inline bool scst_lba1_inside_lba2(int64_t lba1, int scst_cm_on_dev_register(struct scst_device *dev); void scst_cm_on_dev_unregister(struct scst_device *dev); +int scst_cm_on_add_acg(struct scst_acg *acg); +void scst_cm_on_del_acg(struct scst_acg *acg); +int scst_cm_on_add_lun(struct scst_acg_dev *acg_dev, uint64_t lun, + unsigned int *flags); +bool scst_cm_on_del_lun(struct scst_acg_dev *acg_dev, + bool gen_report_luns_changed); + int scst_cm_parse_descriptors(struct scst_cmd *cmd); void scst_cm_free_descriptors(struct scst_cmd *cmd); diff --git a/scst/src/scst_proc.c b/scst/src/scst_proc.c index 1d4dc3c25..26b99c3fe 100644 --- a/scst/src/scst_proc.c +++ b/scst/src/scst_proc.c @@ -948,8 +948,8 @@ static int scst_proc_group_add(const char *p, unsigned int addr_method) } strlcpy(name, p, len); - acg = scst_alloc_add_acg(NULL, name, false); - if (acg == NULL) { + res = scst_alloc_add_acg(NULL, name, false, &acg); + if (res != 0) { PRINT_ERROR("scst_alloc_add_acg() (name %s) failed", name); goto out_free; } @@ -969,6 +969,7 @@ out_free_acg: out_free: kfree(name); + goto out; out_nomem: res = -ENOMEM; @@ -2069,7 +2070,8 @@ static ssize_t scst_proc_groups_devices_write(struct file *file, } } - rc = scst_acg_add_lun(acg, NULL, dev, virt_lun, read_only, + rc = scst_acg_add_lun(acg, NULL, dev, virt_lun, + read_only ? SCST_ADD_LUN_READ_ONLY : 0, false, NULL); if (rc) { res = rc; diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 62497ecdc..cc939175e 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -1327,6 +1327,7 @@ static int __scst_process_luns_mgmt_store(char *buffer, case SCST_LUN_ACTION_REPLACE: { bool dev_replaced = false; + unsigned int flags = 0; e = scst_get_next_lexem(&pp); res = kstrtoul(e, 0, &virt_lun); @@ -1414,9 +1415,13 @@ static int __scst_process_luns_mgmt_store(char *buffer, } } + 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, read_only, !dev_replaced, NULL); + dev, virt_lun, flags, NULL); if (res != 0) goto out_unlock; @@ -2174,8 +2179,8 @@ static int scst_process_ini_group_mgmt_store(char *buffer, res = -EINVAL; goto out_unlock; } - acg = scst_alloc_add_acg(tgt, p, true); - if (acg == NULL) + res = scst_alloc_add_acg(tgt, p, true, &acg); + if (res != 0) goto out_unlock; break; case SCST_INI_GROUP_ACTION_DEL: