mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 03:31:26 +00:00
scst: Introduce scst_acg_repl_lun()
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
This commit is contained in:
@@ -4267,29 +4267,26 @@ out_free:
|
||||
goto out;
|
||||
}
|
||||
|
||||
int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
|
||||
bool gen_scst_report_luns_changed)
|
||||
static struct scst_acg_dev *__scst_acg_del_lun(struct scst_acg *acg,
|
||||
uint64_t lun,
|
||||
struct list_head *tgt_dev_list)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_acg_dev *acg_dev = NULL, *a;
|
||||
struct scst_tgt_dev *tgt_dev, *tt;
|
||||
struct scst_session *sess;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
lockdep_assert_held(&scst_mutex);
|
||||
|
||||
INIT_LIST_HEAD(tgt_dev_list);
|
||||
|
||||
list_for_each_entry(a, &acg->acg_dev_list, acg_dev_list_entry) {
|
||||
if (a->lun == lun) {
|
||||
acg_dev = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (acg_dev == NULL) {
|
||||
PRINT_ERROR("Device is not found in group %s", acg->acg_name);
|
||||
res = -EINVAL;
|
||||
if (acg_dev == NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(tgt_dev, tt, &acg_dev->dev->dev_tgt_dev_list,
|
||||
dev_tgt_dev_list_entry) {
|
||||
@@ -4300,15 +4297,46 @@ int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
|
||||
scst_del_tgt_dev(tgt_dev);
|
||||
mutex_unlock(&sess->tgt_dev_list_mutex);
|
||||
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
|
||||
tgt_dev_list);
|
||||
}
|
||||
}
|
||||
|
||||
scst_del_free_acg_dev(acg_dev, true);
|
||||
scst_del_acg_dev(acg_dev, true, true);
|
||||
|
||||
out:
|
||||
return acg_dev;
|
||||
}
|
||||
|
||||
int scst_acg_del_lun(struct scst_acg *acg, uint64_t lun,
|
||||
bool gen_scst_report_luns_changed)
|
||||
{
|
||||
int res = -EINVAL;
|
||||
struct scst_acg_dev *acg_dev;
|
||||
struct scst_tgt_dev *tgt_dev, *tt;
|
||||
struct list_head tgt_dev_list;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
lockdep_assert_held(&scst_mutex);
|
||||
|
||||
acg_dev = __scst_acg_del_lun(acg, lun, &tgt_dev_list);
|
||||
if (acg_dev == NULL) {
|
||||
PRINT_ERROR("Device is not found in group %s", acg->acg_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (gen_scst_report_luns_changed)
|
||||
scst_report_luns_changed(acg);
|
||||
|
||||
list_for_each_entry_safe(tgt_dev, tt, &tgt_dev_list,
|
||||
extra_tgt_dev_list_entry) {
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_free_acg_dev(acg_dev);
|
||||
|
||||
res = 0;
|
||||
|
||||
PRINT_INFO("Removed LUN %lld from group %s (target %s)",
|
||||
lun, acg->acg_name, acg->tgt ? acg->tgt->tgt_name : "?");
|
||||
|
||||
@@ -4317,6 +4345,49 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
int scst_acg_repl_lun(struct scst_acg *acg, struct kobject *parent,
|
||||
struct scst_device *dev, uint64_t lun,
|
||||
bool read_only)
|
||||
{
|
||||
struct scst_acg_dev *acg_dev;
|
||||
struct scst_tgt_dev *tgt_dev, *tt;
|
||||
struct list_head tgt_dev_list;
|
||||
int res = -EINVAL;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
lockdep_assert_held(&scst_mutex);
|
||||
|
||||
acg_dev = __scst_acg_del_lun(acg, lun, &tgt_dev_list);
|
||||
|
||||
res = scst_acg_add_lun(acg, parent, dev, lun, read_only, !acg_dev,
|
||||
NULL);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
if (acg_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));
|
||||
}
|
||||
}
|
||||
}
|
||||
list_for_each_entry_safe(tgt_dev, tt, &tgt_dev_list,
|
||||
extra_tgt_dev_list_entry) {
|
||||
scst_free_tgt_dev(tgt_dev);
|
||||
}
|
||||
scst_free_acg_dev(acg_dev);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
||||
@@ -364,6 +364,8 @@ int scst_acg_add_lun(struct scst_acg *acg, struct kobject *parent,
|
||||
bool gen_scst_report_luns_changed, 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);
|
||||
int scst_acg_repl_lun(struct scst_acg *acg, struct kobject *parent,
|
||||
struct scst_device *dev, uint64_t lun, bool read_only);
|
||||
|
||||
int scst_acg_add_acn(struct scst_acg *acg, const char *name);
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
|
||||
@@ -1409,7 +1409,6 @@ static int __scst_process_luns_mgmt_store(char *buffer,
|
||||
&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) {
|
||||
@@ -1418,7 +1417,6 @@ static int __scst_process_luns_mgmt_store(char *buffer,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (acg_dev) {
|
||||
PRINT_ERROR("virt lun %ld already exists in "
|
||||
"group %s", virt_lun, acg->acg_name);
|
||||
@@ -1434,54 +1432,16 @@ static int __scst_process_luns_mgmt_store(char *buffer,
|
||||
|
||||
break;
|
||||
case SCST_LUN_ACTION_REPLACE:
|
||||
{
|
||||
bool dev_replaced = false;
|
||||
|
||||
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) {
|
||||
res = scst_acg_del_lun(acg, acg_dev->lun, false);
|
||||
if (res != 0)
|
||||
goto out_unlock;
|
||||
|
||||
dev_replaced = true;
|
||||
}
|
||||
|
||||
res = scst_acg_add_lun(acg,
|
||||
res = scst_acg_repl_lun(acg,
|
||||
tgt_kobj ? tgt->tgt_luns_kobj : acg->luns_kobj,
|
||||
dev, virt_lun, read_only, !dev_replaced, NULL);
|
||||
dev, virt_lun, read_only);
|
||||
if (res != 0)
|
||||
goto out_unlock;
|
||||
|
||||
if (dev_replaced) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SCST_LUN_ACTION_DEL:
|
||||
p = scst_get_next_lexem(&pp);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
|
||||
|
||||
Reference in New Issue
Block a user