mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 01:01:27 +00:00
Add support for iSCSI TargetAlias
This includes both support during iSCSI LOGIN and iSNS.
This commit is contained in:
committed by
Gleb Chesnokov
parent
c00af8aab9
commit
3c8f66e2b8
@@ -283,6 +283,10 @@ Each target subdirectory contains the following entries:
|
||||
|
||||
- tid - TID of this target.
|
||||
|
||||
- alias - TargetAlias of this target. If not set, it will default to the
|
||||
empty string and no TargetAlias will be reported in LOGIN RESPONSE or iSNS
|
||||
for this target.
|
||||
|
||||
The "sessions" subdirectory contains the following attribute:
|
||||
|
||||
- thread_pid - the process identifiers (PIDs) of the iscsird and iscsiwr
|
||||
@@ -559,6 +563,7 @@ both iSCSI-SCST targets will look like:
|
||||
| | |-- NopInInterval
|
||||
| | |-- QueuedCommands
|
||||
| | |-- RspTimeout
|
||||
| | |-- alias
|
||||
| | |-- enabled
|
||||
| | |-- ini_groups
|
||||
| | | `-- mgmt
|
||||
|
||||
@@ -265,6 +265,32 @@ char *config_sep_string(char **pp)
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip leading and trailing whitespace.
|
||||
*
|
||||
* Modifies the contents of the parameter string.
|
||||
*/
|
||||
char *config_strip_string(char *s)
|
||||
{
|
||||
size_t size;
|
||||
char *end;
|
||||
|
||||
size = strlen(s);
|
||||
|
||||
if (!size)
|
||||
return s;
|
||||
|
||||
end = s + size - 1;
|
||||
while (end >= s && isspace(*end))
|
||||
end--;
|
||||
*(end + 1) = '\0';
|
||||
|
||||
while (*s && isspace(*s))
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static char *config_gets(char *buf, int size, const char *data, int *offset)
|
||||
{
|
||||
int offs = *offset, i = 0;
|
||||
|
||||
@@ -78,7 +78,12 @@ int kernel_target_create(struct target *target, u32 *tid, u32 cookie)
|
||||
info.tid = (tid != NULL) ? *tid : 0;
|
||||
info.cookie = cookie;
|
||||
|
||||
info.attrs_num = 2;
|
||||
/*
|
||||
* ISCSI_PER_PORTAL_ACL_ATTR_NAME
|
||||
* ISCSI_TARGET_REDIRECTION_ATTR_NAME
|
||||
* ISCSI_TARGET_ALIAS_ATTR_NAME
|
||||
*/
|
||||
info.attrs_num = 3;
|
||||
|
||||
for (j = 0; j < session_key_last; j++) {
|
||||
if (session_keys[j].show_in_sysfs)
|
||||
@@ -117,6 +122,11 @@ int kernel_target_create(struct target *target, u32 *tid, u32 cookie)
|
||||
sizeof(ISCSI_TARGET_REDIRECTION_ATTR_NAME));
|
||||
i++;
|
||||
|
||||
kern_attrs[i].mode = 0644;
|
||||
strlcpy(kern_attrs[i].name, ISCSI_TARGET_ALIAS_ATTR_NAME,
|
||||
sizeof(ISCSI_TARGET_ALIAS_ATTR_NAME));
|
||||
i++;
|
||||
|
||||
for (j = 0; j < session_key_last; j++) {
|
||||
if (!session_keys[j].show_in_sysfs)
|
||||
continue;
|
||||
|
||||
@@ -611,6 +611,17 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event)
|
||||
add_key_mark(res_str, sizeof(res_str), 0);
|
||||
} else
|
||||
*res_str = '\0';
|
||||
} else if (strcasecmp(ISCSI_TARGET_ALIAS_ATTR_NAME, pp) == 0) {
|
||||
if (target == NULL) {
|
||||
log_error("Target expected for attr %s", pp);
|
||||
res = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
if (target->alias) {
|
||||
snprintf(res_str, sizeof(res_str), "%s\n", target->alias);
|
||||
add_key_mark(res_str, sizeof(res_str), 0);
|
||||
} else
|
||||
*res_str = '\0';
|
||||
} else if (strcasecmp(ISCSI_ISNS_SERVER_ATTR_NAME, pp) == 0) {
|
||||
if (target != NULL) {
|
||||
log_error("Not NULL target %s for global attribute %s",
|
||||
@@ -955,6 +966,48 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event)
|
||||
res = handle_target_redirect(target, p);
|
||||
if (res != 0)
|
||||
goto out_free;
|
||||
} else if (strcasecmp(ISCSI_TARGET_ALIAS_ATTR_NAME, pp) == 0) {
|
||||
bool alias_changed = false;
|
||||
|
||||
if (target == NULL) {
|
||||
log_error("Target expected for attr %s", pp);
|
||||
res = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
p = config_strip_string(p);
|
||||
if (*p == '\0') {
|
||||
if (target->alias) {
|
||||
free(target->alias);
|
||||
target->alias = NULL;
|
||||
alias_changed = true;
|
||||
}
|
||||
} else {
|
||||
char *newval = strdup(p);
|
||||
|
||||
if (newval == NULL) {
|
||||
log_error("Unable to duplicate alias name %s", p);
|
||||
res = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
if (target->alias)
|
||||
free(target->alias);
|
||||
target->alias = newval;
|
||||
alias_changed = true;
|
||||
}
|
||||
/* If we previously registered an alias and we need to update it */
|
||||
if (alias_changed && target->isns_registered) {
|
||||
if (target->alias) {
|
||||
isns_target_register(target->name);
|
||||
} else {
|
||||
/*
|
||||
* We have cleared a previously set alias.
|
||||
* Work-around to make change visible in
|
||||
* open-isns server.
|
||||
*/
|
||||
isns_target_deregister(target->name);
|
||||
isns_target_register(target->name);
|
||||
}
|
||||
}
|
||||
} else if (strcasecmp(ISCSI_ISNS_SERVER_ATTR_NAME, pp) == 0) {
|
||||
if (target != NULL) {
|
||||
log_error("Not NULL target %s for global attribute %s",
|
||||
|
||||
@@ -921,6 +921,8 @@ static void login_start(struct connection *conn)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (target->alias)
|
||||
text_key_add(conn, "TargetAlias", target->alias);
|
||||
log_debug(1, "target %s, sessions_count %d", target_name,
|
||||
target->sessions_count);
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ struct target {
|
||||
|
||||
unsigned int tgt_enabled:1;
|
||||
unsigned int per_portal_acl:1;
|
||||
unsigned int isns_registered:1;
|
||||
|
||||
unsigned int target_params[target_key_last];
|
||||
unsigned int session_params[session_key_last];
|
||||
@@ -353,6 +354,7 @@ extern int nl_open(void);
|
||||
|
||||
/* config.c */
|
||||
extern char *config_sep_string(char **pp);
|
||||
extern char *config_strip_string(char *s);
|
||||
extern int config_parse_main(const char *data, u32 cookie);
|
||||
extern int config_load(const char *config_name);
|
||||
extern int config_target_create(u32 *tid, char *name);
|
||||
|
||||
@@ -482,7 +482,7 @@ int isns_target_register(char *name)
|
||||
uint32_t port = htonl(server_port);
|
||||
uint32_t node = htonl(ISNS_NODE_TARGET);
|
||||
uint32_t type = htonl(2);
|
||||
struct target *target;
|
||||
struct target *target, *alias_target;
|
||||
int err, initial = list_length_is_one(&targets_list);
|
||||
int max_buf;
|
||||
|
||||
@@ -499,6 +499,7 @@ int isns_target_register(char *name)
|
||||
tlv = (struct isns_tlv *)hdr->pdu;
|
||||
max_buf = sizeof(buf) - offsetof(struct isns_hdr, pdu);
|
||||
|
||||
alias_target = target_find_by_name(name);
|
||||
if (strlen(isns_entity_target_name) < 1) {
|
||||
target = list_entry(targets_list.q_forw, struct target, tlist);
|
||||
err = isns_tlv_set(&tlv, max_buf - length, ISNS_ATTR_ISCSI_NAME,
|
||||
@@ -566,6 +567,14 @@ int isns_target_register(char *name)
|
||||
goto out;
|
||||
length += err;
|
||||
|
||||
if (alias_target && alias_target->alias) {
|
||||
err = isns_tlv_set(&tlv, max_buf - length, ISNS_ATTR_ISCSI_ALIAS,
|
||||
strlen(alias_target->alias) + 1, alias_target->alias);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
length += err;
|
||||
}
|
||||
|
||||
err = isns_tlv_set(&tlv, max_buf - length, ISNS_ATTR_ISCSI_NODE_TYPE,
|
||||
sizeof(node), &node);
|
||||
if (err < 0)
|
||||
@@ -579,6 +588,8 @@ int isns_target_register(char *name)
|
||||
err = write(isns_fd, buf, length + sizeof(struct isns_hdr));
|
||||
if (err < 0)
|
||||
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
|
||||
else if (alias_target)
|
||||
alias_target->isns_registered = 1;
|
||||
|
||||
if (scn_listen_port)
|
||||
isns_scn_register();
|
||||
@@ -662,6 +673,9 @@ int isns_target_deregister(char *name)
|
||||
if (err < 0)
|
||||
log_error("%s %d: %s", __func__, __LINE__, strerror(errno));
|
||||
|
||||
if (target)
|
||||
target->isns_registered = 0;
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define ISCSI_TARGET_REDIRECTION_ATTR_NAME "redirect"
|
||||
#define ISCSI_TARGET_REDIRECTION_VALUE_TEMP "temp"
|
||||
#define ISCSI_TARGET_REDIRECTION_VALUE_PERM "perm"
|
||||
#define ISCSI_TARGET_ALIAS_ATTR_NAME "alias"
|
||||
|
||||
struct iscsi_key;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user