Automatic sessions reassignment implemented

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1017 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2009-08-06 11:47:18 +00:00
parent 7286d22319
commit a65caa9b9b
7 changed files with 399 additions and 132 deletions
+21 -18
View File
@@ -448,40 +448,43 @@ names of initiators, which allowed to access devices in this group.
To configure access and devices visibility management SCST provides the
following files and directories under /proc/scsi_tgt:
- "add_group GROUP" to /proc/scsi_tgt/scsi_tgt adds group "GROUP"
- "add_group GROUP_NAME" to /proc/scsi_tgt/scsi_tgt adds group "GROUP_NAME"
- "del_group GROUP" to /proc/scsi_tgt/scsi_tgt deletes group "GROUP"
- "del_group GROUP_NAME" to /proc/scsi_tgt/scsi_tgt deletes group "GROUP_NAME"
- "add H:C:I:L lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP/devices adds
device with host:channel:id:lun with LUN "lun" in group "GROUP". Optionally,
- "rename_group OLD_NAME NEW_NAME" to /proc/scsi_tgt/scsi_tgt renames
group "OLD_NAME" to "NEW_NAME".
- "add H:C:I:L lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP_NAME/devices adds
device with host:channel:id:lun with LUN "lun" in group "GROUP_NAME". Optionally,
the device could be marked as read only. The recommended way to find out
H:C:I:L numbers is use of lsscsi utility.
- "del H:C:I:L" to /proc/scsi_tgt/groups/GROUP/devices deletes device with
host:channel:id:lun from group "GROUP". The recommended way to find out
- "del H:C:I:L" to /proc/scsi_tgt/groups/GROUP_NAME/devices deletes device with
host:channel:id:lun from group "GROUP_NAME". The recommended way to find out
H:C:I:L numbers is use of lsscsi utility.
- "add V_NAME lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP/devices adds
device with virtual name "V_NAME" with LUN "lun" in group "GROUP".
- "add V_NAME lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP_NAME/devices adds
device with virtual name "V_NAME" with LUN "lun" in group "GROUP_NAME".
Optionally, the device could be marked as read only.
- "del V_NAME" to /proc/scsi_tgt/groups/GROUP/devices deletes device with
virtual name "V_NAME" from group "GROUP"
- "del V_NAME" to /proc/scsi_tgt/groups/GROUP_NAME/devices deletes device with
virtual name "V_NAME" from group "GROUP_NAME"
- "clear" to /proc/scsi_tgt/groups/GROUP/devices clears the list of devices
for group "GROUP"
- "clear" to /proc/scsi_tgt/groups/GROUP_NAME/devices clears the list of devices
for group "GROUP_NAME"
- "add NAME" to /proc/scsi_tgt/groups/GROUP/names adds name "NAME" to group
"GROUP". For NAME you can use simple DOS-type patterns, containing
- "add NAME" to /proc/scsi_tgt/groups/GROUP_NAME/names adds name "NAME" to group
"GROUP_NAME". For NAME you can use simple DOS-type patterns, containing
'*' and '?' symbols. '*' means match all any symbols, '?' means
match only any single symbol. For instance, "blah.xxx" will match
"bl?h.*".
- "del NAME" to /proc/scsi_tgt/groups/GROUP/names deletes name "NAME" from group
"GROUP"
- "del NAME" to /proc/scsi_tgt/groups/GROUP_NAME/names deletes name "NAME" from group
"GROUP_NAME"
- "clear" to /proc/scsi_tgt/groups/GROUP/names clears the list of names
for group "GROUP"
- "clear" to /proc/scsi_tgt/groups/GROUP_NAME/names clears the list of names
for group "GROUP_NAME"
Examples:
+21 -18
View File
@@ -366,40 +366,43 @@ names of initiators, which allowed to access devices in this group.
To configure access and devices visibility management SCST provides the
following files and directories under /proc/scsi_tgt:
- "add_group GROUP" to /proc/scsi_tgt/scsi_tgt adds group "GROUP"
- "add_group GROUP_NAME" to /proc/scsi_tgt/scsi_tgt adds group "GROUP_NAME"
- "del_group GROUP" to /proc/scsi_tgt/scsi_tgt deletes group "GROUP"
- "del_group GROUP_NAME" to /proc/scsi_tgt/scsi_tgt deletes group "GROUP_NAME"
- "add H:C:I:L lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP/devices adds
device with host:channel:id:lun with LUN "lun" in group "GROUP". Optionally,
- "rename_group OLD_NAME NEW_NAME" to /proc/scsi_tgt/scsi_tgt renames
group "OLD_NAME" to "NEW_NAME".
- "add H:C:I:L lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP_NAME/devices adds
device with host:channel:id:lun with LUN "lun" in group "GROUP_NAME". Optionally,
the device could be marked as read only. The recommended way to find out
H:C:I:L numbers is use of lsscsi utility.
- "del H:C:I:L" to /proc/scsi_tgt/groups/GROUP/devices deletes device with
host:channel:id:lun from group "GROUP". The recommended way to find out
- "del H:C:I:L" to /proc/scsi_tgt/groups/GROUP_NAME/devices deletes device with
host:channel:id:lun from group "GROUP_NAME". The recommended way to find out
H:C:I:L numbers is use of lsscsi utility.
- "add V_NAME lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP/devices adds
device with virtual name "V_NAME" with LUN "lun" in group "GROUP".
- "add V_NAME lun [READ_ONLY]" to /proc/scsi_tgt/groups/GROUP_NAME/devices adds
device with virtual name "V_NAME" with LUN "lun" in group "GROUP_NAME".
Optionally, the device could be marked as read only.
- "del V_NAME" to /proc/scsi_tgt/groups/GROUP/devices deletes device with
virtual name "V_NAME" from group "GROUP"
- "del V_NAME" to /proc/scsi_tgt/groups/GROUP_NAME/devices deletes device with
virtual name "V_NAME" from group "GROUP_NAME"
- "clear" to /proc/scsi_tgt/groups/GROUP/devices clears the list of devices
for group "GROUP"
- "clear" to /proc/scsi_tgt/groups/GROUP_NAME/devices clears the list of devices
for group "GROUP_NAME"
- "add NAME" to /proc/scsi_tgt/groups/GROUP/names adds name "NAME" to group
"GROUP". For NAME you can use simple DOS-type patterns, containing
- "add NAME" to /proc/scsi_tgt/groups/GROUP_NAME/names adds name "NAME" to group
"GROUP_NAME". For NAME you can use simple DOS-type patterns, containing
'*' and '?' symbols. '*' means match all any symbols, '?' means
match only any single symbol. For instance, "blah.xxx" will match
"bl?h.*".
- "del NAME" to /proc/scsi_tgt/groups/GROUP/names deletes name "NAME" from group
"GROUP"
- "del NAME" to /proc/scsi_tgt/groups/GROUP_NAME/names deletes name "NAME" from group
"GROUP_NAME"
- "clear" to /proc/scsi_tgt/groups/GROUP/names clears the list of names
for group "GROUP"
- "clear" to /proc/scsi_tgt/groups/GROUP_NAME/names clears the list of names
for group "GROUP_NAME"
Examples:
+211 -59
View File
@@ -48,6 +48,9 @@ static void scst_free_all_UA(struct scst_tgt_dev *tgt_dev);
static void scst_release_space(struct scst_cmd *cmd);
static void scst_sess_free_tgt_devs(struct scst_session *sess);
static void scst_unblock_cmds(struct scst_device *dev);
static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev);
static struct scst_tgt_dev *scst_alloc_add_tgt_dev(struct scst_session *sess,
struct scst_acg_dev *acg_dev);
#ifdef CONFIG_SCST_DEBUG_TM
static void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev,
@@ -562,6 +565,66 @@ static void scst_queue_report_luns_changed_UA(struct scst_session *sess,
return;
}
/* The activity supposed to be suspended and scst_mutex held */
static void scst_report_luns_changed_sess(struct scst_session *sess)
{
int i;
struct list_head *shead;
struct scst_tgt_dev *tgt_dev;
struct scst_tgt_template *tgtt = sess->tgt->tgtt;
TRACE_ENTRY();
TRACE_DBG("REPORTED LUNS DATA CHANGED (sess %p)", sess);
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
shead = &sess->sess_tgt_dev_list_hash[i];
list_for_each_entry(tgt_dev, shead,
sess_tgt_dev_list_entry) {
if (scst_is_report_luns_changed_type(
tgt_dev->dev->type))
goto found;
}
}
TRACE_MGMT_DBG("Not found a device capable REPORTED "
"LUNS DATA CHANGED UA (sess %p)", sess);
goto out;
found:
if (tgtt->report_aen != NULL) {
struct scst_aen *aen;
int rc;
aen = scst_alloc_aen(tgt_dev);
if (aen == NULL)
goto queue_ua;
aen->event_fn = SCST_AEN_SCSI;
aen->aen_sense_len = SCST_STANDARD_SENSE_LEN;
scst_set_sense(aen->aen_sense, aen->aen_sense_len,
tgt_dev->dev->d_sense,
SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed));
TRACE_DBG("Calling target's %s report_aen(%p)",
tgtt->name, aen);
rc = tgtt->report_aen(aen);
TRACE_DBG("Target's %s report_aen(%p) returned %d",
tgtt->name, aen, rc);
if (rc == SCST_AEN_RES_SUCCESS)
goto out;
scst_free_aen(aen);
}
queue_ua:
scst_queue_report_luns_changed_UA(sess, 0);
out:
TRACE_EXIT();
return;
}
/* The activity supposed to be suspended and scst_mutex held */
void scst_report_luns_changed(struct scst_acg *acg)
{
@@ -572,52 +635,7 @@ void scst_report_luns_changed(struct scst_acg *acg)
TRACE_MGMT_DBG("REPORTED LUNS DATA CHANGED (acg %s)", acg->acg_name);
list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
int i;
struct list_head *shead;
struct scst_tgt_dev *tgt_dev;
struct scst_tgt_template *tgtt = sess->tgt->tgtt;
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
shead = &sess->sess_tgt_dev_list_hash[i];
list_for_each_entry(tgt_dev, shead,
sess_tgt_dev_list_entry) {
if (scst_is_report_luns_changed_type(
tgt_dev->dev->type))
goto found;
}
}
TRACE_MGMT_DBG("Not found a device capable REPORTED "
"LUNS DATA CHANGED UA (sess %p)", sess);
continue;
found:
if (tgtt->report_aen != NULL) {
struct scst_aen *aen;
int rc;
aen = scst_alloc_aen(tgt_dev);
if (aen == NULL)
goto queue_ua;
aen->event_fn = SCST_AEN_SCSI;
aen->aen_sense_len = SCST_STANDARD_SENSE_LEN;
scst_set_sense(aen->aen_sense, aen->aen_sense_len,
tgt_dev->dev->d_sense,
SCST_LOAD_SENSE(scst_sense_reported_luns_data_changed));
TRACE_DBG("Calling target's %s report_aen(%p)",
tgtt->name, aen);
rc = tgtt->report_aen(aen);
TRACE_DBG("Target's %s report_aen(%p) returned %d",
tgtt->name, aen, rc);
if (rc == SCST_AEN_RES_SUCCESS)
continue;
scst_free_aen(aen);
}
queue_ua:
scst_queue_report_luns_changed_UA(sess, 0);
scst_report_luns_changed_sess(sess);
}
TRACE_EXIT();
@@ -684,6 +702,129 @@ out_free:
}
EXPORT_SYMBOL(scst_aen_done);
/* The activity supposed to be suspended and scst_mutex held */
static void scst_check_reassign_sess(struct scst_session *sess)
{
struct scst_acg *acg, *old_acg;
struct scst_acg_dev *acg_dev;
int i;
struct list_head *shead;
struct scst_tgt_dev *tgt_dev;
bool luns_changed = false;
bool add_failed, something_freed;
TRACE_ENTRY();
TRACE_MGMT_DBG("Checking reassignment for sess %p (initiator %s)",
sess, sess->initiator_name);
acg = scst_find_acg(sess);
if (acg == sess->acg) {
TRACE_MGMT_DBG("No reassignment for sess %p", sess);
goto out;
}
TRACE_MGMT_DBG("sess %p will be reassigned from acg %s to acg %s",
sess, sess->acg->acg_name, acg->acg_name);
old_acg = sess->acg;
sess->acg = NULL; /* to catch implicit dependencies earlier */
retry_add:
add_failed = false;
list_for_each_entry(acg_dev, &acg->acg_dev_list, acg_dev_list_entry) {
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
shead = &sess->sess_tgt_dev_list_hash[i];
list_for_each_entry(tgt_dev, shead,
sess_tgt_dev_list_entry) {
if ((tgt_dev->dev == acg_dev->dev) &&
(tgt_dev->lun == acg_dev->lun) &&
(tgt_dev->acg_dev->rd_only == acg_dev->rd_only)) {
TRACE_MGMT_DBG("sess %p: tgt_dev %p for "
"LUN %lld stays the same",
sess, tgt_dev,
(unsigned long long)tgt_dev->lun);
tgt_dev->acg_dev = acg_dev;
goto next;
}
}
}
luns_changed = true;
TRACE_MGMT_DBG("sess %p: Allocing new tgt_dev for LUN %lld",
sess, (unsigned long long)acg_dev->lun);
tgt_dev = scst_alloc_add_tgt_dev(sess, acg_dev);
if (tgt_dev == NULL) {
add_failed = true;
break;
}
next:
continue;
}
something_freed = false;
for (i = 0; i < TGT_DEV_HASH_SIZE; i++) {
struct scst_tgt_dev *t;
shead = &sess->sess_tgt_dev_list_hash[i];
list_for_each_entry_safe(tgt_dev, t, shead,
sess_tgt_dev_list_entry) {
if (tgt_dev->acg_dev->acg != acg) {
TRACE_MGMT_DBG("sess %p: Deleting not used "
"tgt_dev %p for LUN %lld",
sess, tgt_dev,
(unsigned long long)tgt_dev->lun);
luns_changed = true;
something_freed = true;
scst_free_tgt_dev(tgt_dev);
}
}
}
if (add_failed && something_freed) {
TRACE_MGMT_DBG("sess %p: Retrying adding new tgt_devs", sess);
goto retry_add;
}
sess->acg = acg;
TRACE_DBG("Moving sess %p from acg %s to acg %s", sess,
old_acg->acg_name, acg->acg_name);
list_move_tail(&sess->acg_sess_list_entry, &acg->acg_sess_list);
if (luns_changed)
scst_report_luns_changed_sess(sess);
out:
TRACE_EXIT();
return;
}
/* The activity supposed to be suspended and scst_mutex held */
void scst_check_reassign_sessions(void)
{
struct scst_tgt_template *tgtt;
TRACE_ENTRY();
list_for_each_entry(tgtt, &scst_template_list, scst_template_list_entry) {
struct scst_tgt *tgt;
list_for_each_entry(tgt, &tgtt->tgt_list, tgt_list_entry) {
struct scst_session *sess;
list_for_each_entry(sess, &tgt->sess_list,
sess_list_entry) {
scst_check_reassign_sess(sess);
}
}
}
TRACE_EXIT();
return;
}
int scst_get_cmd_abnormal_done_state(const struct scst_cmd *cmd)
{
int res;
@@ -1125,6 +1266,8 @@ struct scst_acg *scst_alloc_add_acg(const char *acg_name)
TRACE_DBG("Adding acg %s to scst_acg_list", acg_name);
list_add_tail(&acg->scst_acg_list_entry, &scst_acg_list);
scst_check_reassign_sessions();
out:
TRACE_EXIT_HRES(acg);
return acg;
@@ -1380,8 +1523,6 @@ out_free:
goto out;
}
static void scst_clear_reservation(struct scst_tgt_dev *tgt_dev);
/* No locks supposed to be held, scst_mutex - held */
void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA)
{
@@ -1628,7 +1769,7 @@ out:
return res;
}
/* scst_mutex supposed to be held */
/* The activity supposed to be suspended and scst_mutex held */
int scst_acg_add_name(struct scst_acg *acg, const char *name)
{
int res = 0;
@@ -1638,8 +1779,7 @@ int scst_acg_add_name(struct scst_acg *acg, const char *name)
TRACE_ENTRY();
list_for_each_entry(n, &acg->acn_list, acn_list_entry)
{
list_for_each_entry(n, &acg->acn_list, acn_list_entry) {
if (strcmp(n->name, name) == 0) {
PRINT_ERROR("Name %s already exists in group %s",
name, acg->acg_name);
@@ -1669,8 +1809,10 @@ int scst_acg_add_name(struct scst_acg *acg, const char *name)
list_add_tail(&n->acn_list_entry, &acg->acn_list);
out:
if (res == 0)
if (res == 0) {
PRINT_INFO("Added name %s to group %s", name, acg->acg_name);
scst_check_reassign_sessions();
}
TRACE_EXIT_RES(res);
return res;
@@ -1681,6 +1823,19 @@ out_free:
}
/* scst_mutex supposed to be held */
void __scst_acg_remove_acn(struct scst_acn *n)
{
TRACE_ENTRY();
list_del(&n->acn_list_entry);
kfree(n->name);
kfree(n);
TRACE_EXIT();
return;
}
/* The activity supposed to be suspended and scst_mutex held */
int scst_acg_remove_name(struct scst_acg *acg, const char *name)
{
int res = -EINVAL;
@@ -1688,12 +1843,9 @@ int scst_acg_remove_name(struct scst_acg *acg, const char *name)
TRACE_ENTRY();
list_for_each_entry(n, &acg->acn_list, acn_list_entry)
{
list_for_each_entry(n, &acg->acn_list, acn_list_entry) {
if (strcmp(n->name, name) == 0) {
list_del(&n->acn_list_entry);
kfree(n->name);
kfree(n);
__scst_acg_remove_acn(n);
res = 0;
break;
}
@@ -1702,10 +1854,10 @@ int scst_acg_remove_name(struct scst_acg *acg, const char *name)
if (res == 0) {
PRINT_INFO("Removed name %s from group %s", name,
acg->acg_name);
} else {
scst_check_reassign_sessions();
} else
PRINT_ERROR("Unable to find name %s in group %s", name,
acg->acg_name);
}
TRACE_EXIT_RES(res);
return res;
+1 -1
View File
@@ -77,7 +77,7 @@
struct mutex scst_mutex;
/* All 3 protected by scst_mutex */
static struct list_head scst_template_list;
struct list_head scst_template_list;
struct list_head scst_dev_list;
struct list_head scst_dev_type_list;
+6
View File
@@ -140,6 +140,7 @@ extern struct scst_sgv_pools scst_sgv;
extern unsigned long scst_flags;
extern struct mutex scst_mutex;
extern atomic_t scst_cmd_count;
extern struct list_head scst_template_list;
extern struct list_head scst_dev_list;
extern struct list_head scst_dev_type_list;
extern wait_queue_head_t scst_dev_cmd_waitQ;
@@ -292,6 +293,10 @@ void scst_free_device(struct scst_device *dev);
struct scst_acg *scst_alloc_add_acg(const char *acg_name);
int scst_destroy_acg(struct scst_acg *acg);
struct scst_acg *scst_find_acg(const struct scst_session *sess);
void scst_check_reassign_sessions(void);
int scst_sess_alloc_tgt_devs(struct scst_session *sess);
void scst_nexus_loss(struct scst_tgt_dev *tgt_dev, bool queue_UA);
@@ -301,6 +306,7 @@ int scst_acg_remove_dev(struct scst_acg *acg, struct scst_device *dev);
int scst_acg_add_name(struct scst_acg *acg, const char *name);
int scst_acg_remove_name(struct scst_acg *acg, const char *name);
void __scst_acg_remove_acn(struct scst_acn *n);
int scst_prepare_request_sense(struct scst_cmd *orig_cmd);
int scst_finish_internal_cmd(struct scst_cmd *cmd);
+116 -23
View File
@@ -83,6 +83,7 @@ static struct scst_proc_data scst_dev_handler_proc_data;
#define SCST_PROC_ACTION_ASSIGN 9
#define SCST_PROC_ACTION_ADD_GROUP 10
#define SCST_PROC_ACTION_DEL_GROUP 11
#define SCST_PROC_ACTION_RENAME_GROUP 12
static struct proc_dir_entry *scst_proc_scsi_tgt;
static struct proc_dir_entry *scst_proc_groups_root;
@@ -125,17 +126,18 @@ static struct scst_proc_log scst_proc_local_trace_tbl[] =
static char *scst_proc_help_string =
" echo \"assign H:C:I:L HANDLER_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
"\n"
" echo \"add_group GROUP\" >/proc/scsi_tgt/scsi_tgt\n"
" echo \"del_group GROUP\" >/proc/scsi_tgt/scsi_tgt\n"
" echo \"add_group GROUP_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
" echo \"del_group GROUP_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
" echo \"rename_group OLD_NAME NEW_NAME\" >/proc/scsi_tgt/scsi_tgt\n"
"\n"
" echo \"add|del H:C:I:L lun [READ_ONLY]\""
" >/proc/scsi_tgt/groups/GROUP/devices\n"
" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
" echo \"add|del V_NAME lun [READ_ONLY]\""
" >/proc/scsi_tgt/groups/GROUP/devices\n"
" echo \"clear\" >/proc/scsi_tgt/groups/GROUP/devices\n"
" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
" echo \"clear\" >/proc/scsi_tgt/groups/GROUP_NAME/devices\n"
"\n"
" echo \"add|del NAME\" >/proc/scsi_tgt/groups/GROUP/names\n"
" echo \"clear\" >/proc/scsi_tgt/groups/GROUP/names\n"
" echo \"add|del NAME\" >/proc/scsi_tgt/groups/GROUP_NAME/names\n"
" echo \"clear\" >/proc/scsi_tgt/groups/GROUP_NAME/names\n"
"\n"
" echo \"DEC|0xHEX|0OCT\" >/proc/scsi_tgt/threads\n"
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
@@ -707,6 +709,45 @@ static int scst_proc_del_free_acg(struct scst_acg *acg, int remove_proc)
return res;
}
/* The activity supposed to be suspended and scst_mutex held */
static int scst_proc_rename_acg(struct scst_acg *acg, const char *new_name)
{
int res = 0, len = strlen(new_name) + 1;
char *name;
struct proc_dir_entry *old_acg_proc_root = acg->acg_proc_root;
TRACE_ENTRY();
name = kmalloc(len, GFP_KERNEL);
if (name == NULL) {
TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of new name failed");
goto out_nomem;
}
strncpy(name, new_name, len);
res = scst_proc_group_add_tree(acg, new_name);
if (res != 0)
goto out_free;
scst_proc_del_acg_tree(old_acg_proc_root, acg->acg_name);
kfree(acg->acg_name);
acg->acg_name = name;
scst_check_reassign_sessions();
out:
TRACE_EXIT_RES(res);
return res;
out_free:
kfree(name);
out_nomem:
res = -ENOMEM;
goto out;
}
static int __init scst_proc_init_groups(void)
{
int res = 0;
@@ -1262,7 +1303,7 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
size_t length, loff_t *off)
{
int res, rc = 0, action;
char *buffer, *p;
char *buffer, *p, *pp;
struct scst_acg *a, *acg = NULL;
TRACE_ENTRY();
@@ -1292,8 +1333,9 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
}
/*
* Usage: echo "add_group GROUP" >/proc/scsi_tgt/scsi_tgt
* or echo "del_group GROUP" >/proc/scsi_tgt/scsi_tgt
* Usage: echo "add_group GROUP_NAME" >/proc/scsi_tgt/scsi_tgt
* or echo "del_group GROUP_NAME" >/proc/scsi_tgt/scsi_tgt
* or echo "rename_group OLD_NAME NEW_NAME" >/proc/scsi_tgt/scsi_tgt"
* or echo "assign H:C:I:L HANDLER_NAME" >/proc/scsi_tgt/scsi_tgt
*/
p = buffer;
@@ -1308,6 +1350,9 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
} else if (!strncasecmp("del_group ", p, 10)) {
p += 10;
action = SCST_PROC_ACTION_DEL_GROUP;
} else if (!strncasecmp("rename_group ", p, 13)) {
p += 13;
action = SCST_PROC_ACTION_RENAME_GROUP;
} else {
PRINT_ERROR("Unknown action \"%s\"", p);
res = -EINVAL;
@@ -1328,12 +1373,33 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
switch (action) {
case SCST_PROC_ACTION_ADD_GROUP:
case SCST_PROC_ACTION_DEL_GROUP:
case SCST_PROC_ACTION_RENAME_GROUP:
if (strcmp(p, SCST_DEFAULT_ACG_NAME) == 0) {
PRINT_ERROR("Attempt to add/delete predefined "
PRINT_ERROR("Attempt to add/delete/rename predefined "
"group \"%s\"", p);
res = -EINVAL;
goto out_up_free;
}
pp = p;
while (!isspace(*pp) && *pp != '\0')
pp++;
if (*pp != '\0') {
switch (action) {
case SCST_PROC_ACTION_ADD_GROUP:
case SCST_PROC_ACTION_DEL_GROUP:
PRINT_ERROR("Wrong acg name %s", p);
res = -EINVAL;
goto out_up_free;
default:
*pp = '\0';
pp++;
while (isspace(*pp) && *pp != '\0')
pp++;
break;
}
}
list_for_each_entry(a, &scst_acg_list, scst_acg_list_entry) {
if (strcmp(a->acg_name, p) == 0) {
TRACE_DBG("group (acg) %p %s found",
@@ -1342,6 +1408,7 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
break;
}
}
switch (action) {
case SCST_PROC_ACTION_ADD_GROUP:
if (acg) {
@@ -1359,6 +1426,22 @@ static ssize_t scst_proc_scsi_tgt_gen_write(struct file *file,
}
rc = scst_proc_del_free_acg(acg, 1);
break;
case SCST_PROC_ACTION_RENAME_GROUP:
if (acg == NULL) {
PRINT_ERROR("acg name %s not found", p);
res = -EINVAL;
goto out_up_free;
}
p = pp;
while (!isspace(*pp) && *pp != '\0')
pp++;
if (*pp != '\0') {
PRINT_ERROR("Wrong acg name %s", p);
res = -EINVAL;
goto out_up_free;
}
rc = scst_proc_rename_acg(acg, p);
break;
}
break;
case SCST_PROC_ACTION_ASSIGN:
@@ -1519,10 +1602,10 @@ static ssize_t scst_proc_groups_devices_write(struct file *file,
/*
* Usage: echo "add|del H:C:I:L lun [READ_ONLY]" \
* >/proc/scsi_tgt/groups/GROUP/devices
* >/proc/scsi_tgt/groups/GROUP_NAME/devices
* or echo "add|del V_NAME lun [READ_ONLY]" \
* >/proc/scsi_tgt/groups/GROUP/devices
* or echo "clear" >/proc/scsi_tgt/groups/GROUP/devices
* >/proc/scsi_tgt/groups/GROUP_NAME/devices
* or echo "clear" >/proc/scsi_tgt/groups/GROUP_NAME/devices
*/
p = buffer;
if (p[strlen(p) - 1] == '\n')
@@ -1687,7 +1770,7 @@ static ssize_t scst_proc_groups_names_write(struct file *file,
const char __user *buf,
size_t length, loff_t *off)
{
int res = length, action;
int res = length, rc = 0, action;
char *buffer, *p, *e;
struct scst_acg *acg =
(struct scst_acg *)PDE(file->f_dentry->d_inode)->data;
@@ -1720,8 +1803,8 @@ static ssize_t scst_proc_groups_names_write(struct file *file,
}
/*
* Usage: echo "add|del NAME" >/proc/scsi_tgt/groups/GROUP/names
* or echo "clear" >/proc/scsi_tgt/groups/GROUP/names
* Usage: echo "add|del NAME" >/proc/scsi_tgt/groups/GROUP_NAME/names
* or echo "clear" >/proc/scsi_tgt/groups/GROUP_NAME/names
*/
p = buffer;
if (p[strlen(p) - 1] == '\n')
@@ -1752,33 +1835,43 @@ static ssize_t scst_proc_groups_names_write(struct file *file,
break;
}
rc = scst_suspend_activity(true);
if (rc != 0)
goto out_free;
if (mutex_lock_interruptible(&scst_mutex) != 0) {
res = -EINTR;
goto out_free;
goto out_free_resume;
}
switch (action) {
case SCST_PROC_ACTION_ADD:
scst_acg_add_name(acg, p);
rc = scst_acg_add_name(acg, p);
break;
case SCST_PROC_ACTION_DEL:
scst_acg_remove_name(acg, p);
rc = scst_acg_remove_name(acg, p);
break;
case SCST_PROC_ACTION_CLEAR:
list_for_each_entry_safe(n, nn, &acg->acn_list,
acn_list_entry) {
list_del(&n->acn_list_entry);
kfree(n->name);
kfree(n);
__scst_acg_remove_acn(n);
}
scst_check_reassign_sessions();
break;
}
mutex_unlock(&scst_mutex);
out_free_resume:
scst_resume_activity();
out_free:
free_page((unsigned long)buffer);
out:
if (rc < 0)
res = rc;
TRACE_EXIT_RES(res);
return res;
}
+23 -13
View File
@@ -5326,7 +5326,7 @@ EXPORT_SYMBOL(scst_rx_mgmt_fn);
* Written by Jack Handy - jakkhandy@hotmail.com
* Taken by Gennadiy Nerubayev <parakie@gmail.com> from
* http://www.codeproject.com/KB/string/wildcmp.aspx. No license attached
* to it, and is posted on a free site; assumed to be free for use.
* to it, and it's posted on a free site; assumed to be free for use.
*/
static bool wildcmp(const char *wild, const char *string)
{
@@ -5363,7 +5363,7 @@ static bool wildcmp(const char *wild, const char *string)
}
/* scst_mutex supposed to be held */
static struct scst_acg *scst_find_acg(const char *initiator_name)
static struct scst_acg *scst_find_acg_by_name_wild(const char *initiator_name)
{
struct scst_acg *acg, *res = NULL;
struct scst_acn *n;
@@ -5407,10 +5407,27 @@ out:
return res;
}
/* Must be called under scst_mitex */
struct scst_acg *scst_find_acg(const struct scst_session *sess)
{
struct scst_acg *acg = NULL;
TRACE_ENTRY();
if (sess->initiator_name)
acg = scst_find_acg_by_name_wild(sess->initiator_name);
if ((acg == NULL) && (sess->tgt->default_group_name != NULL))
acg = scst_find_acg_by_name(sess->tgt->default_group_name);
if (acg == NULL)
acg = scst_default_acg;
TRACE_EXIT_HRES((unsigned long)acg);
return acg;
}
static int scst_init_session(struct scst_session *sess)
{
int res = 0;
struct scst_acg *acg = NULL;
struct scst_cmd *cmd;
struct scst_mgmt_cmd *mcmd, *tm;
int mwake = 0;
@@ -5419,19 +5436,12 @@ static int scst_init_session(struct scst_session *sess)
mutex_lock(&scst_mutex);
if (sess->initiator_name)
acg = scst_find_acg(sess->initiator_name);
if ((acg == NULL) && (sess->tgt->default_group_name != NULL))
acg = scst_find_acg_by_name(sess->tgt->default_group_name);
if (acg == NULL)
acg = scst_default_acg;
sess->acg = scst_find_acg(sess);
PRINT_INFO("Using security group \"%s\" for initiator \"%s\"",
acg->acg_name, sess->initiator_name);
sess->acg->acg_name, sess->initiator_name);
sess->acg = acg;
TRACE_MGMT_DBG("Assigning session %p to acg %s", sess, acg->acg_name);
list_add_tail(&sess->acg_sess_list_entry, &acg->acg_sess_list);
list_add_tail(&sess->acg_sess_list_entry, &sess->acg->acg_sess_list);
TRACE_DBG("Adding sess %p to tgt->sess_list", sess);
list_add_tail(&sess->sess_list_entry, &sess->tgt->sess_list);