lib/iscsi: Update redirect portal of public portal group

iscsi_tgt_node_redirect() updates redirect portal of the initial
portal iin a primary portal group for the target node.

Check if the specified portal group is a public portal group and is
mapped to the target node first.

Then if the passed IP address-port pair is NULL, clear the current
redirect setting. Public portal group and private portal group are
clearly separated and redirect portal must be chosen from a private
portal group. Hence this clear method is intuitive and simple.

If the passed IP address-port pair is not NULL, check if they are
valid, and are not in the specified portal group. Then update a
redirect portal of the portal group map.

Finally, send asynchronous logout request to all corresponding
initiators.

Besides, change allocating pg_map from malloc to calloc to initialize
redirect portal.

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I79d826663f4c3d5a117add286f133adeb1ce07f5
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3222
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Shuhei Matsumoto 2020-07-22 15:48:36 +09:00 committed by Tomasz Zawadzki
parent 651f6d6a3a
commit 2c8309e00e
2 changed files with 62 additions and 1 deletions

View File

@ -553,7 +553,7 @@ iscsi_tgt_node_add_pg_map(struct spdk_iscsi_tgt_node *target,
return NULL;
}
pg_map = malloc(sizeof(*pg_map));
pg_map = calloc(1, sizeof(*pg_map));
if (pg_map == NULL) {
return NULL;
}
@ -857,6 +857,63 @@ invalid:
return -1;
}
int
iscsi_tgt_node_redirect(struct spdk_iscsi_tgt_node *target, int pg_tag,
const char *host, const char *port)
{
struct spdk_iscsi_portal_grp *pg;
struct spdk_iscsi_pg_map *pg_map;
struct sockaddr_storage sa;
if (target == NULL) {
return -EINVAL;
}
pg = iscsi_portal_grp_find_by_tag(pg_tag);
if (pg == NULL) {
SPDK_ERRLOG("Portal group %d is not found.\n", pg_tag);
return -EINVAL;
}
if (pg->is_private) {
SPDK_ERRLOG("Portal group %d is not public portal group.\n", pg_tag);
return -EINVAL;
}
pg_map = iscsi_tgt_node_find_pg_map(target, pg);
if (pg_map == NULL) {
SPDK_ERRLOG("Portal group %d is not mapped.\n", pg_tag);
return -EINVAL;
}
if (host == NULL && port == NULL) {
/* Clear redirect setting. */
memset(pg_map->redirect_host, 0, MAX_PORTAL_ADDR + 1);
memset(pg_map->redirect_port, 0, MAX_PORTAL_PORT + 1);
} else {
if (iscsi_parse_redirect_addr(&sa, host, port) != 0) {
SPDK_ERRLOG("IP address-port pair is not valid.\n");
return -EINVAL;
}
if (iscsi_portal_grp_find_portal_by_addr(pg, port, host) != NULL) {
SPDK_ERRLOG("IP address-port pair must be chosen from a "
"different private portal group\n");
return -EINVAL;
}
snprintf(pg_map->redirect_host, MAX_PORTAL_ADDR + 1, "%s", host);
snprintf(pg_map->redirect_port, MAX_PORTAL_PORT + 1, "%s", port);
}
/* Terminate connections to this public portal group by asynchronous
* logout message.
*/
iscsi_conns_request_logout(target, pg_tag);
return 0;
}
static int
check_iscsi_name(const char *name)
{

View File

@ -59,6 +59,8 @@ struct spdk_iscsi_pg_map {
struct spdk_iscsi_portal_grp *pg;
int num_ig_maps;
TAILQ_HEAD(, spdk_iscsi_ig_map) ig_map_head;
char redirect_host[MAX_PORTAL_ADDR + 1];
char redirect_port[MAX_PORTAL_PORT + 1];
TAILQ_ENTRY(spdk_iscsi_pg_map) tailq ;
};
@ -126,6 +128,8 @@ int iscsi_target_node_add_pg_ig_maps(struct spdk_iscsi_tgt_node *target,
int iscsi_target_node_remove_pg_ig_maps(struct spdk_iscsi_tgt_node *target,
int *pg_tag_list, int *ig_tag_list,
uint16_t num_maps);
int iscsi_tgt_node_redirect(struct spdk_iscsi_tgt_node *target, int pg_tag,
const char *host, const char *port);
bool iscsi_tgt_node_access(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_tgt_node *target, const char *iqn,