Please could the attached patch be considered for inclusion in the open-iscsi
source.
Regards,
Alex Zeffertt
Changelog:
---------
iSCSI Boot Firmware Tables are able to specify up to two iSCSI targets, but
until now open-iscsi has only been able to display/attach one of these.
This change enables open-iscsi to display/attach both targets when the iBFT
contains two valid entries. The following commands are affected:
iscsiadm -m fw [-l]
iscsistart -b
iscsistart -f
The primary benefit of this change is that it makes possible for initrds to
mount a multipath device, where the slave devices are iSCSI LUNs specified by
the iBFT.
Signed-off-by: [email protected]
--
You received this message because you are subscribed to the Google Groups
"open-iscsi" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/open-iscsi?hl=en.
diff -urN a/include/fw_context.h b/include/fw_context.h
--- a/include/fw_context.h 2008-07-01 02:14:03.000000000 +0100
+++ b/include/fw_context.h 2009-12-16 15:33:15.000000000 +0000
@@ -40,7 +40,17 @@
char isid[10];
};
-extern int fw_get_entry(struct boot_context *context, const char *filepath);
+/*
+ * Parse the firmware into context[] and return the number of entries written.
+ */
+extern int fw_get_entry(struct boot_context context[], int max_entries, const char *filepath);
+
+/*
+ * Print the contents of context.
+ */
extern void fw_print_entry(struct boot_context *context);
+/* PPC may have 1 entry, iBFT on x86 may have 1 or 2 entries */
+#define FWPARAM_MAX_ENTRIES 2
+
#endif /* FWPARAM_CONTEXT_H_ */
diff -urN a/usr/iscsiadm.c b/usr/iscsiadm.c
--- a/usr/iscsiadm.c 2008-07-01 02:14:03.000000000 +0100
+++ b/usr/iscsiadm.c 2009-12-16 15:33:15.000000000 +0000
@@ -1960,32 +1960,40 @@
static int exec_fw_op(discovery_rec_t *drec, int do_login, int info_level)
{
- struct boot_context context;
- struct node_rec *rec;
+ struct boot_context context[FWPARAM_MAX_ENTRIES];
+ struct boot_context *pcontext = context;
+ int entries = 0;
int ret = 0;
- memset(&context, 0, sizeof(struct boot_context));
- ret = fw_get_entry(&context, NULL);
- if (ret) {
- log_error("Could not read fw values.");
- return ret;
+ memset(context, 0, sizeof(context));
+ entries = fw_get_entry(context, FWPARAM_MAX_ENTRIES, NULL);
+ if (entries == 0) {
+ log_error("Could not find fw values.");
+ return -1;
}
+ while (entries-- && ret == 0) {
+ struct node_rec *rec;
+ rec = fw_create_rec_by_entry(pcontext);
+ if (!rec)
+ return ENODEV;
+
+ /* if discovery, print nodes that were found. */
+ if (drec)
+ /* this looks wrong... aren't we supposed to do something
+ * with drec - like fill it out for example?
+ */
+ print_fw_nodes(rec, info_level);
+
+ if (do_login)
+ ret = login_portal(NULL, NULL, rec);
+ free(rec);
- rec = fw_create_rec_by_entry(&context);
- if (!rec)
- return ENODEV;
-
- /* if discovery, print nodes that were found. */
- if (drec)
- print_fw_nodes(rec, info_level);
-
- if (do_login)
- ret = login_portal(NULL, NULL, rec);
- free(rec);
-
- /* print the fw node info if called in fw mode with no params */
- if (!do_login && !drec)
- fw_print_entry(&context);
+ /* print the fw node info if called in fw mode with no params */
+ if (!do_login && !drec)
+ fw_print_entry(pcontext);
+
+ pcontext++;
+ }
return ret;
}
diff -urN a/usr/iscsistart.c b/usr/iscsistart.c
--- a/usr/iscsistart.c 2008-07-01 02:14:03.000000000 +0100
+++ b/usr/iscsistart.c 2009-12-16 15:35:20.000000000 +0000
@@ -49,8 +49,6 @@
struct iscsi_daemon_config daemon_config;
struct iscsi_daemon_config *dconfig = &daemon_config;
-static node_rec_t config_rec;
-
static char program_name[] = "iscsistart";
static int mgmt_ipc_fd;
@@ -120,7 +118,7 @@
return rc;
}
-static int setup_session(void)
+static int setup_session(node_rec_t *config_rec)
{
iscsiadm_req_t req;
iscsiadm_rsp_t rsp;
@@ -130,18 +128,18 @@
* For root boot we cannot change this so increase to account
* for boot using static setup.
*/
- config_rec.session.initial_login_retry_max = 120;
+ config_rec->session.initial_login_retry_max = 120;
/* we cannot answer so turn off */
- config_rec.conn[0].timeo.noop_out_interval = 0;
- config_rec.conn[0].timeo.noop_out_timeout = 0;
+ config_rec->conn[0].timeo.noop_out_interval = 0;
+ config_rec->conn[0].timeo.noop_out_timeout = 0;
- printf("%s: Logging into %s %s:%d,%d\n", program_name, config_rec.name,
- config_rec.conn[0].address, config_rec.conn[0].port,
- config_rec.tpgt);
+ printf("%s: Logging into %s %s:%d,%d\n", program_name, config_rec->name,
+ config_rec->conn[0].address, config_rec->conn[0].port,
+ config_rec->tpgt);
memset(&req, 0, sizeof(req));
req.command = MGMT_IPC_SESSION_LOGIN;
- memcpy(&req.u.session.rec, &config_rec, sizeof(node_rec_t));
+ memcpy(&req.u.session.rec, config_rec, sizeof(node_rec_t));
rc = do_iscsid(&req, &rsp);
if (rc)
iscsid_handle_error(rc);
@@ -154,24 +152,24 @@
log_warning("pid %d caught signal -%d", getpid(), signo);
}
-static int check_params(char *initiatorname)
+static int check_params(char *initiatorname, node_rec_t *config_rec)
{
if (!initiatorname) {
log_error("InitiatorName not set. Exiting %s\n", program_name);
return EINVAL;
}
- if (config_rec.tpgt == PORTAL_GROUP_TAG_UNKNOWN) {
+ if (config_rec->tpgt == PORTAL_GROUP_TAG_UNKNOWN) {
log_error("Portal Group not set. Exiting %s\n", program_name);
return EINVAL;
}
- if (!strlen(config_rec.name)) {
+ if (!strlen(config_rec->name)) {
log_error("TargetName not set. Exiting %s\n", program_name);
return EINVAL;
}
- if (!strlen(config_rec.conn[0].address)) {
+ if (!strlen(config_rec->conn[0].address)) {
log_error("IP Address not set. Exiting %s\n", program_name);
return EINVAL;
}
@@ -188,21 +186,36 @@
} \
} while (0);
+static LIST_HEAD(node_list);
+
+static node_rec_t *alloc_node(void)
+{
+ node_rec_t *config_rec = malloc(sizeof(node_rec_t));
+ if (config_rec == NULL) {
+ printf("malloc failed\n");
+ exit(-1);
+ }
+ idbm_node_setup_defaults(config_rec);
+ config_rec->name[0] = '\0';
+ config_rec->conn[0].address[0] = '\0';
+ return config_rec;
+}
+
int main(int argc, char *argv[])
{
struct utsname host_info; /* will use to compound initiator alias */
struct iscsi_auth_config *auth;
char *initiatorname = NULL;
- int ch, longindex, ret;
+ int ch, longindex, entries;
struct sigaction sa_old;
struct sigaction sa_new;
- struct boot_context context;
+ struct boot_context context[FWPARAM_MAX_ENTRIES];
+ struct boot_context *pcontext;
+ node_rec_t *config_rec;
pid_t pid;
- idbm_node_setup_defaults(&config_rec);
- config_rec.name[0] = '\0';
- config_rec.conn[0].address[0] = '\0';
- auth = &config_rec.session.auth;
+ config_rec = alloc_node();
+ list_add_tail(&config_rec->list, &node_list);
/* do not allow ctrl-c for now... */
sa_new.sa_handler = catch_signal;
@@ -219,19 +232,20 @@
case 't':
check_str_param_len(optarg, TARGET_NAME_MAXLEN,
"targetname");
- strncpy(config_rec.name, optarg, TARGET_NAME_MAXLEN);
+ strncpy(config_rec->name, optarg, TARGET_NAME_MAXLEN);
break;
case 'g':
- config_rec.tpgt = atoi(optarg);
+ config_rec->tpgt = atoi(optarg);
break;
case 'a':
check_str_param_len(optarg, NI_MAXHOST, "address");
- strncpy(config_rec.conn[0].address, optarg, NI_MAXHOST);
+ strncpy(config_rec->conn[0].address, optarg, NI_MAXHOST);
break;
case 'p':
- config_rec.conn[0].port = atoi(optarg);
+ config_rec->conn[0].port = atoi(optarg);
break;
case 'w':
+ auth = &config_rec->session.auth;
check_str_param_len(optarg, AUTH_STR_MAX_LEN,
"password");
strncpy((char *)auth->password, optarg,
@@ -239,6 +253,7 @@
auth->password_length = strlen((char *)auth->password);
break;
case 'W':
+ auth = &config_rec->session.auth;
check_str_param_len(optarg, AUTH_STR_MAX_LEN,
"password_in");
strncpy((char *)auth->password_in, optarg,
@@ -247,11 +262,13 @@
strlen((char *)auth->password_in);
break;
case 'u':
+ auth = &config_rec->session.auth;
check_str_param_len(optarg, AUTH_STR_MAX_LEN,
"username");
strncpy(auth->username, optarg, AUTH_STR_MAX_LEN);
break;
case 'U':
+ auth = &config_rec->session.auth;
check_str_param_len(optarg, AUTH_STR_MAX_LEN,
"username_in");
strncpy(auth->username_in, optarg, AUTH_STR_MAX_LEN);
@@ -260,42 +277,54 @@
log_level = atoi(optarg);
break;
case 'b':
- ret = fw_get_entry(&context, NULL);
- if (ret) {
- printf("Could not setup fw entries.");
+ entries = fw_get_entry(context, FWPARAM_MAX_ENTRIES, NULL);
+ if (entries == 0) {
+ printf("Could not find fw entries.");
exit(-1);
}
-
- initiatorname = context.initiatorname;
- strncpy(config_rec.name, context.targetname,
- sizeof(context.targetname));
- strncpy(config_rec.conn[0].address,
- context.target_ipaddr,
- sizeof(context.target_ipaddr));
- config_rec.conn[0].port = context.target_port;
- /* this seems broken ??? */
- config_rec.tpgt = 1;
- strncpy(auth->username, context.chap_name,
- sizeof(context.chap_name));
- strncpy((char *)auth->password, context.chap_password,
- sizeof(context.chap_password));
- auth->password_length = strlen((char *)auth->password);
- strncpy(auth->username_in, context.chap_name_in,
- sizeof(context.chap_name_in));
- strncpy((char *)auth->password_in,
- context.chap_password_in,
- sizeof(context.chap_password_in));
- auth->password_in_length =
- strlen((char *)auth->password_in);
+ pcontext = context;
+ while (entries--) {
+ auth = &config_rec->session.auth;
+ initiatorname = pcontext->initiatorname;
+ strncpy(config_rec->name, pcontext->targetname,
+ sizeof(pcontext->targetname));
+ strncpy(config_rec->conn[0].address,
+ pcontext->target_ipaddr,
+ sizeof(pcontext->target_ipaddr));
+ config_rec->conn[0].port = pcontext->target_port;
+ /* this seems broken ??? */
+ config_rec->tpgt = 1;
+ strncpy(auth->username, pcontext->chap_name,
+ sizeof(pcontext->chap_name));
+ strncpy((char *)auth->password, pcontext->chap_password,
+ sizeof(pcontext->chap_password));
+ auth->password_length = strlen((char *)auth->password);
+ strncpy(auth->username_in, pcontext->chap_name_in,
+ sizeof(pcontext->chap_name_in));
+ strncpy((char *)auth->password_in,
+ pcontext->chap_password_in,
+ sizeof(pcontext->chap_password_in));
+ auth->password_in_length =
+ strlen((char *)auth->password_in);
+ if (entries) {
+ /* more firmware to go */
+ config_rec = alloc_node();
+ list_add_tail(&config_rec->list, &node_list);
+ pcontext++;
+ }
+ }
break;
case 'f':
- ret = fw_get_entry(&context, NULL);
- if (ret) {
- printf("Could not read fw values.\n");
+ entries = fw_get_entry(context, FWPARAM_MAX_ENTRIES, NULL);
+ if (entries == 0) {
+ printf("Could not find fw values.\n");
exit(-1);
}
-
- fw_print_entry(&context);
+ pcontext = context;
+ while (entries--) {
+ fw_print_entry(pcontext);
+ pcontext++;
+ }
exit(0);
case 'v':
printf("%s version %s\n", program_name,
@@ -317,18 +346,27 @@
sysfs_init();
if (iscsi_sysfs_check_class_version())
exit(1);
-
- if (check_params(initiatorname))
- exit(1);
+
+ list_for_each_entry(config_rec, &node_list, list) {
+ if (check_params(initiatorname, config_rec))
+ exit(1);
+ }
pid = fork();
if (pid < 0) {
log_error("iscsiboot fork failed");
exit(1);
} else if (pid) {
- int status, rc, rc2;
+ int status, rc = 0, rc2;
- rc = setup_session();
+ list_for_each_entry(config_rec, &node_list, list) {
+ log_debug(1, "TargetName=%s", config_rec->name);
+ log_debug(1, "TPGT=%d", config_rec->tpgt);
+ log_debug(1, "IP Address=%s", config_rec->conn[0].address);
+ rc = setup_session(config_rec);
+ if (rc)
+ break;
+ }
rc2 = stop_event_loop();
/*
* something horrible happened. kill child and get
@@ -364,9 +402,6 @@
log_debug(1, "InitiatorName=%s", daemon_config.initiator_name);
log_debug(1, "InitiatorAlias=%s", daemon_config.initiator_alias);
- log_debug(1, "TargetName=%s", config_rec.name);
- log_debug(1, "TPGT=%d", config_rec.tpgt);
- log_debug(1, "IP Address=%s", config_rec.conn[0].address);
/* log the version, so that we can tell if the daemon and kernel module
* match based on what shows up in the syslog. Tarballs releases
diff -urN a/utils/fwparam_ibft/fw_entry.c b/utils/fwparam_ibft/fw_entry.c
--- a/utils/fwparam_ibft/fw_entry.c 2008-07-01 02:14:03.000000000 +0100
+++ b/utils/fwparam_ibft/fw_entry.c 2009-12-16 15:39:28.000000000 +0000
@@ -23,14 +23,20 @@
#include "fw_context.h"
#include "fwparam_ibft.h"
-int fw_get_entry(struct boot_context *context, const char *filepath)
+/*
+ * Parse the firmware into context[] and return the number of entries written.
+ */
+int fw_get_entry(struct boot_context context[], int max_entries, const char *filepath)
{
int ret;
+ int entries = 1;
ret = fwparam_ppc(context, filepath);
if (ret)
- ret = fwparam_ibft(context, filepath);
- return ret;
+ entries = fwparam_ibft(context, max_entries, filepath);
+ else
+ entries = 1; /* PPC only supports 1 entry */
+ return entries;
}
/*
diff -urN a/utils/fwparam_ibft/fwparam_ibft.c b/utils/fwparam_ibft/fwparam_ibft.c
--- a/utils/fwparam_ibft/fwparam_ibft.c 2008-07-01 02:14:03.000000000 +0100
+++ b/utils/fwparam_ibft/fwparam_ibft.c 2009-12-16 15:33:15.000000000 +0000
@@ -306,8 +306,8 @@
/*
* Read in and dump ASCII output for ibft starting at ibft_loc.
*/
-int
-dump_ibft(void *ibft_loc, struct boot_context *context)
+static int
+dump_ibft(void *ibft_loc, struct boot_context context[], int max_entries)
{
struct ibft_table_hdr *ibft_hdr = ibft_loc;
struct ibft_control *control;
@@ -315,6 +315,7 @@
struct ibft_nic *nic0 = NULL, *nic1 = NULL;
struct ibft_tgt *tgt0 = NULL, *tgt1 = NULL;
char ipbuf[32];
+ struct boot_context *pcontext = context;
control = ibft_loc + sizeof(*ibft_hdr);
CHECK_HDR(control, control);
@@ -353,57 +354,65 @@
tgt1 = ibft_loc + control->tgt1_off;
CHECK_HDR(tgt1, target);
}
-
- strncpy(context->initiatorname,
- (char *)ibft_loc+initiator->initiator_name_off,
- initiator->initiator_name_len + 1);
-
- if (tgt0 && (tgt0->hdr.flags & INIT_FLAG_FW_SEL_BOOT)) {
- strncpy((char *)context->targetname,
+
+ /* TODO: how should we treat the boot failover flag?
+ */
+ if (pcontext < &context[max_entries] &&
+ tgt0 && (tgt0->hdr.flags & INIT_FLAG_FW_SEL_BOOT)) {
+ strncpy(pcontext->initiatorname,
+ (char *)ibft_loc+initiator->initiator_name_off,
+ initiator->initiator_name_len + 1);
+ strncpy((char *)pcontext->targetname,
(char *)(ibft_loc+tgt0->tgt_name_off),
tgt0->tgt_name_len);
format_ipaddr(ipbuf, sizeof(ipbuf),
tgt0->ip_addr);
- strncpy((char *)context->target_ipaddr, ipbuf,
+ strncpy((char *)pcontext->target_ipaddr, ipbuf,
sizeof(ipbuf));
- context->target_port = tgt0->port;
- strncpy(context->chap_name,
+ pcontext->target_port = tgt0->port;
+ strncpy(pcontext->chap_name,
(char *)(ibft_loc + tgt0->chap_name_off),
tgt0->chap_name_len);
- strncpy(context->chap_password,
+ strncpy(pcontext->chap_password,
(char*)(ibft_loc + tgt0->chap_secret_off),
tgt0->chap_secret_len);
- strncpy(context->chap_name_in,
+ strncpy(pcontext->chap_name_in,
(char *)(ibft_loc + tgt0->rev_chap_name_off),
tgt0->rev_chap_name_len);
- strncpy(context->chap_password_in,
+ strncpy(pcontext->chap_password_in,
(char *)(ibft_loc + tgt0->rev_chap_secret_off),
tgt0->rev_chap_secret_len);
- } else if (tgt1 &&
- (tgt1->hdr.flags & INIT_FLAG_FW_SEL_BOOT)) {
- strncpy((char *)context->targetname,
+ pcontext++;
+ }
+ if (pcontext < &context[max_entries] &&
+ tgt1 && (tgt1->hdr.flags & INIT_FLAG_FW_SEL_BOOT)) {
+ strncpy(pcontext->initiatorname,
+ (char *)ibft_loc+initiator->initiator_name_off,
+ initiator->initiator_name_len + 1);
+ strncpy((char *)pcontext->targetname,
(char *)(ibft_loc+tgt1->tgt_name_off),
tgt1->tgt_name_len);
format_ipaddr(ipbuf, sizeof(ipbuf),
tgt1->ip_addr);
- strncpy((char *)context->target_ipaddr,ipbuf,
+ strncpy((char *)pcontext->target_ipaddr,ipbuf,
sizeof(ipbuf));
- context->target_port = tgt1->port;
- strncpy(context->chap_name,
+ pcontext->target_port = tgt1->port;
+ strncpy(pcontext->chap_name,
(char *)(ibft_loc + tgt1->chap_name_off),
tgt1->chap_name_len);
- strncpy(context->chap_password,
+ strncpy(pcontext->chap_password,
(char*)(ibft_loc + tgt1->chap_secret_off),
tgt1->chap_secret_len);
- strncpy(context->chap_name_in,
+ strncpy(pcontext->chap_name_in,
(char *)(ibft_loc + tgt1->rev_chap_name_off),
tgt1->rev_chap_name_len);
- strncpy(context->chap_password_in,
+ strncpy(pcontext->chap_password_in,
(char *)(ibft_loc + tgt1->rev_chap_secret_off),
tgt1->rev_chap_secret_len);
+ pcontext++;
}
- return 0;
+ return pcontext - context;
}
char *search_ibft(unsigned char *start, int length)
@@ -438,8 +447,11 @@
return NULL;
}
+/*
+ * Parse the iBFT into context[] and return the number of entries written.
+ */
int
-fwparam_ibft(struct boot_context *context, const char *filepath)
+fwparam_ibft(struct boot_context context[], int max_entries, const char *filepath)
{
int fd, ret;
char *filebuf, *ibft_loc;
@@ -486,7 +498,7 @@
ibft_loc = search_ibft((unsigned char *)filebuf, end_search);
if (ibft_loc)
- ret = dump_ibft(ibft_loc, context);
+ ret = dump_ibft(ibft_loc, context, max_entries);
else {
printf("Could not find iBFT.\n");
ret = -1;
diff -urN a/utils/fwparam_ibft/fwparam_ibft.h b/utils/fwparam_ibft/fwparam_ibft.h
--- a/utils/fwparam_ibft/fwparam_ibft.h 2008-07-01 02:14:03.000000000 +0100
+++ b/utils/fwparam_ibft/fwparam_ibft.h 2009-12-16 15:33:15.000000000 +0000
@@ -152,7 +152,7 @@
#define INITIATOR "iscsi-initiator"
#define TARGET "target"
-extern int fwparam_ibft(struct boot_context *context, const char *filepath);
+extern int fwparam_ibft(struct boot_context context[], int max_entries, const char *filepath);
extern int fwparam_ppc(struct boot_context *context, const char *filepath);
#endif /* FWPARAM_IBFT_H_ */