Add "iscsictl -e". Among other things, it makes it possible to perform

discovery without attaching to the targets ("iscsictl -Ad ... -e off"),
and then attach to selected ones ("iscsictl -Mi ... -e on").

PR:		204129
MFC after:	1 month
Relnotes:	yes
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D6633
This commit is contained in:
trasz 2016-05-31 11:32:07 +00:00
parent 9113095212
commit 57b120baca
8 changed files with 119 additions and 16 deletions

View File

@ -406,6 +406,11 @@ iscsi_maintenance_thread_reconnect(struct iscsi_session *is)
KASSERT(STAILQ_EMPTY(&is->is_postponed), KASSERT(STAILQ_EMPTY(&is->is_postponed),
("destroying session with postponed PDUs")); ("destroying session with postponed PDUs"));
if (is->is_conf.isc_enable == 0 && is->is_conf.isc_discovery == 0) {
ISCSI_SESSION_UNLOCK(is);
return;
}
/* /*
* Request immediate reconnection from iscsid(8). * Request immediate reconnection from iscsid(8).
*/ */
@ -549,6 +554,9 @@ iscsi_callout(void *context)
callout_schedule(&is->is_callout, 1 * hz); callout_schedule(&is->is_callout, 1 * hz);
if (is->is_conf.isc_enable == 0)
goto out;
is->is_timeout++; is->is_timeout++;
if (is->is_waiting_for_iscsid) { if (is->is_waiting_for_iscsid) {
@ -1311,6 +1319,11 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
for (;;) { for (;;) {
TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
ISCSI_SESSION_LOCK(is); ISCSI_SESSION_LOCK(is);
if (is->is_conf.isc_enable == 0 &&
is->is_conf.isc_discovery == 0) {
ISCSI_SESSION_UNLOCK(is);
continue;
}
if (is->is_waiting_for_iscsid) if (is->is_waiting_for_iscsid)
break; break;
ISCSI_SESSION_UNLOCK(is); ISCSI_SESSION_UNLOCK(is);
@ -1826,17 +1839,22 @@ iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
callout_reset(&is->is_callout, 1 * hz, iscsi_callout, is); callout_reset(&is->is_callout, 1 * hz, iscsi_callout, is);
TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next); TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next);
/*
* Trigger immediate reconnection.
*/
ISCSI_SESSION_LOCK(is); ISCSI_SESSION_LOCK(is);
/*
* Don't notify iscsid(8) if the session is disabled and it's not
* a discovery session,
*/
if (is->is_conf.isc_enable == 0 && is->is_conf.isc_discovery == 0) {
ISCSI_SESSION_UNLOCK(is);
sx_xunlock(&sc->sc_lock);
return (0);
}
is->is_waiting_for_iscsid = true; is->is_waiting_for_iscsid = true;
strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason)); strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason));
ISCSI_SESSION_UNLOCK(is); ISCSI_SESSION_UNLOCK(is);
cv_signal(&sc->sc_cv); cv_signal(&sc->sc_cv);
sx_xunlock(&sc->sc_lock); sx_xunlock(&sc->sc_lock);
return (0); return (0);
} }

View File

@ -67,7 +67,8 @@ struct iscsi_session_conf {
int isc_data_digest; int isc_data_digest;
int isc_iser; int isc_iser;
char isc_offload[ISCSI_OFFLOAD_LEN]; char isc_offload[ISCSI_OFFLOAD_LEN];
int isc_spare[2]; int isc_enable;
int isc_spare[1];
}; };
/* /*

View File

@ -125,6 +125,14 @@ must be defined.
Discovery sessions result in the initiator connecting to all the targets Discovery sessions result in the initiator connecting to all the targets
returned by SendTargets iSCSI discovery with the defined returned by SendTargets iSCSI discovery with the defined
.Sy TargetAddress . .Sy TargetAddress .
.It Cm Enable
Enable or disable the session.
State can be either
.Qq Ar On ,
or
.Qq Ar Off .
Default is
.Qq Ar On .
.It Cm Offload .It Cm Offload
Name of selected iSCSI hardware offload driver. Name of selected iSCSI hardware offload driver.
Default is Default is

View File

@ -40,11 +40,13 @@
.Op Fl u Ar user Fl s Ar secret .Op Fl u Ar user Fl s Ar secret
.Op Fl w Ar timeout .Op Fl w Ar timeout
.Op Fl r .Op Fl r
.Op Fl e Cm on | off
.Nm .Nm
.Fl A .Fl A
.Fl d Ar discovery-host .Fl d Ar discovery-host
.Op Fl u Ar user Fl s Ar secret .Op Fl u Ar user Fl s Ar secret
.Op Fl r .Op Fl r
.Op Fl e Cm on | off
.Nm .Nm
.Fl A .Fl A
.Fl a Op Fl c Ar path .Fl a Op Fl c Ar path
@ -58,6 +60,7 @@
.Op Fl t Ar target .Op Fl t Ar target
.Op Fl u Ar user .Op Fl u Ar user
.Op Fl s Ar secret .Op Fl s Ar secret
.Op Fl e Cm on | off
.Nm .Nm
.Fl M .Fl M
.Fl i Ar session-id .Fl i Ar session-id
@ -110,6 +113,10 @@ Target host name or address used for SendTargets discovery.
When used, it will add a temporary discovery session. When used, it will add a temporary discovery session.
After discovery is done, sessions will be added for each discovered target, After discovery is done, sessions will be added for each discovered target,
and the temporary discovery session will be removed. and the temporary discovery session will be removed.
.It Fl e
Enable or disable the session.
This is ignored for discovery sessions, but gets passed down to normal
sessions they add.
.It Fl i .It Fl i
Session ID, as displayed by Session ID, as displayed by
.Nm .Nm
@ -189,6 +196,12 @@ utility exits 0 on success, and >0 if an error occurs.
Attach to target iqn.2012-06.com.example:target0, served by 192.168.1.1: Attach to target iqn.2012-06.com.example:target0, served by 192.168.1.1:
.Dl Nm Fl A Fl t Ar iqn.2012-06.com.example:target0 Fl p Ar 192.168.1.1 .Dl Nm Fl A Fl t Ar iqn.2012-06.com.example:target0 Fl p Ar 192.168.1.1
.Pp .Pp
Perform discovery on 192.168.1.1, and add disabled sessions for each
discovered target; use
.Nm -M -e on
to connect them:
.Dl Nm Fl A Fl d Ar 192.168.1.1 Fl e Ar off
.Pp
Disconnect all iSCSI sessions: Disconnect all iSCSI sessions:
.Dl Nm Fl Ra .Dl Nm Fl Ra
.Sh SEE ALSO .Sh SEE ALSO

View File

@ -98,7 +98,6 @@ target_delete(struct target *targ)
free(targ); free(targ);
} }
static char * static char *
default_initiator_name(void) default_initiator_name(void)
{ {
@ -152,6 +151,23 @@ valid_hex(const char ch)
} }
} }
int
parse_enable(const char *enable)
{
if (enable == NULL)
return (ENABLE_UNSPECIFIED);
if (strcasecmp(enable, "on") == 0 ||
strcasecmp(enable, "yes") == 0)
return (ENABLE_ON);
if (strcasecmp(enable, "off") == 0 ||
strcasecmp(enable, "no") == 0)
return (ENABLE_OFF);
return (ENABLE_UNSPECIFIED);
}
bool bool
valid_iscsi_name(const char *name) valid_iscsi_name(const char *name)
{ {
@ -325,6 +341,8 @@ conf_from_target(struct iscsi_session_conf *conf,
sizeof(conf->isc_mutual_secret)); sizeof(conf->isc_mutual_secret));
if (targ->t_session_type == SESSION_TYPE_DISCOVERY) if (targ->t_session_type == SESSION_TYPE_DISCOVERY)
conf->isc_discovery = 1; conf->isc_discovery = 1;
if (targ->t_enable != ENABLE_OFF)
conf->isc_enable = 1;
if (targ->t_protocol == PROTOCOL_ISER) if (targ->t_protocol == PROTOCOL_ISER)
conf->isc_iser = 1; conf->isc_iser = 1;
if (targ->t_offload != NULL) if (targ->t_offload != NULL)
@ -371,7 +389,7 @@ kernel_modify(int iscsi_fd, unsigned int session_id, const struct target *targ)
static void static void
kernel_modify_some(int iscsi_fd, unsigned int session_id, const char *target, kernel_modify_some(int iscsi_fd, unsigned int session_id, const char *target,
const char *target_addr, const char *user, const char *secret) const char *target_addr, const char *user, const char *secret, int enable)
{ {
struct iscsi_session_state *states = NULL; struct iscsi_session_state *states = NULL;
struct iscsi_session_state *state; struct iscsi_session_state *state;
@ -421,6 +439,10 @@ kernel_modify_some(int iscsi_fd, unsigned int session_id, const char *target,
strlcpy(conf->isc_user, user, sizeof(conf->isc_user)); strlcpy(conf->isc_user, user, sizeof(conf->isc_user));
if (secret != NULL) if (secret != NULL)
strlcpy(conf->isc_secret, secret, sizeof(conf->isc_secret)); strlcpy(conf->isc_secret, secret, sizeof(conf->isc_secret));
if (enable == ENABLE_ON)
conf->isc_enable = 1;
else if (enable == ENABLE_OFF)
conf->isc_enable = 0;
memset(&ism, 0, sizeof(ism)); memset(&ism, 0, sizeof(ism));
ism.ism_session_id = session_id; ism.ism_session_id = session_id;
@ -527,6 +549,9 @@ kernel_list(int iscsi_fd, const struct target *targ __unused,
xo_emit("{L:/%-18s}{V:type/%s}\n", xo_emit("{L:/%-18s}{V:type/%s}\n",
"Session type:", "Session type:",
conf->isc_discovery ? "Discovery" : "Normal"); conf->isc_discovery ? "Discovery" : "Normal");
xo_emit("{L:/%-18s}{V:enable/%s}\n",
"Enable:",
conf->isc_enable ? "Yes" : "No");
xo_emit("{L:/%-18s}{V:state/%s}\n", xo_emit("{L:/%-18s}{V:state/%s}\n",
"Session state:", "Session state:",
state->iss_connected ? "Connected" : "Disconnected"); state->iss_connected ? "Connected" : "Disconnected");
@ -575,6 +600,8 @@ kernel_list(int iscsi_fd, const struct target *targ __unused,
} else { } else {
if (conf->isc_discovery) { if (conf->isc_discovery) {
xo_emit("{V:state}\n", "Discovery"); xo_emit("{V:state}\n", "Discovery");
} else if (conf->isc_enable == 0) {
xo_emit("{V:state}\n", "Disabled");
} else if (state->iss_connected) { } else if (state->iss_connected) {
xo_emit("{V:state}: ", "Connected"); xo_emit("{V:state}: ", "Connected");
print_periphs(state->iss_id); print_periphs(state->iss_id);
@ -653,13 +680,13 @@ usage(void)
{ {
fprintf(stderr, "usage: iscsictl -A -p portal -t target " fprintf(stderr, "usage: iscsictl -A -p portal -t target "
"[-u user -s secret] [-w timeout]\n"); "[-u user -s secret] [-w timeout] [-e on | off]\n");
fprintf(stderr, " iscsictl -A -d discovery-host " fprintf(stderr, " iscsictl -A -d discovery-host "
"[-u user -s secret]\n"); "[-u user -s secret] [-e on | off]\n");
fprintf(stderr, " iscsictl -A -a [-c path]\n"); fprintf(stderr, " iscsictl -A -a [-c path]\n");
fprintf(stderr, " iscsictl -A -n nickname [-c path]\n"); fprintf(stderr, " iscsictl -A -n nickname [-c path]\n");
fprintf(stderr, " iscsictl -M -i session-id [-p portal] " fprintf(stderr, " iscsictl -M -i session-id [-p portal] "
"[-t target] [-u user] [-s secret]\n"); "[-t target] [-u user] [-s secret] [-e on | off]\n");
fprintf(stderr, " iscsictl -M -i session-id -n nickname " fprintf(stderr, " iscsictl -M -i session-id -n nickname "
"[-c path]\n"); "[-c path]\n");
fprintf(stderr, " iscsictl -R [-p portal] [-t target]\n"); fprintf(stderr, " iscsictl -R [-p portal] [-t target]\n");
@ -687,8 +714,8 @@ main(int argc, char **argv)
rflag = 0, vflag = 0; rflag = 0, vflag = 0;
const char *conf_path = DEFAULT_CONFIG_PATH; const char *conf_path = DEFAULT_CONFIG_PATH;
char *nickname = NULL, *discovery_host = NULL, *portal = NULL, char *nickname = NULL, *discovery_host = NULL, *portal = NULL,
*target = NULL, *user = NULL, *secret = NULL; *target = NULL, *user = NULL, *secret = NULL;
int timeout = -1; int timeout = -1, enable = ENABLE_UNSPECIFIED;
long long session_id = -1; long long session_id = -1;
char *end; char *end;
int ch, error, iscsi_fd, retval, saved_errno; int ch, error, iscsi_fd, retval, saved_errno;
@ -699,7 +726,7 @@ main(int argc, char **argv)
argc = xo_parse_args(argc, argv); argc = xo_parse_args(argc, argv);
xo_open_container("iscsictl"); xo_open_container("iscsictl");
while ((ch = getopt(argc, argv, "AMRLac:d:i:n:p:rt:u:s:vw:")) != -1) { while ((ch = getopt(argc, argv, "AMRLac:d:e:i:n:p:rt:u:s:vw:")) != -1) {
switch (ch) { switch (ch) {
case 'A': case 'A':
Aflag = 1; Aflag = 1;
@ -722,6 +749,13 @@ main(int argc, char **argv)
case 'd': case 'd':
discovery_host = optarg; discovery_host = optarg;
break; break;
case 'e':
enable = parse_enable(optarg);
if (enable == ENABLE_UNSPECIFIED) {
xo_errx(1, "invalid argument to -e, "
"must be either \"on\" or \"off\"");
}
break;
case 'i': case 'i':
session_id = strtol(optarg, &end, 10); session_id = strtol(optarg, &end, 10);
if ((size_t)(end - optarg) != strlen(optarg)) if ((size_t)(end - optarg) != strlen(optarg))
@ -781,6 +815,8 @@ main(int argc, char **argv)
*/ */
if (Aflag != 0) { if (Aflag != 0) {
if (aflag != 0) { if (aflag != 0) {
if (enable != ENABLE_UNSPECIFIED)
xo_errx(1, "-a and -e and mutually exclusive");
if (portal != NULL) if (portal != NULL)
xo_errx(1, "-a and -p and mutually exclusive"); xo_errx(1, "-a and -p and mutually exclusive");
if (target != NULL) if (target != NULL)
@ -796,6 +832,8 @@ main(int argc, char **argv)
if (rflag != 0) if (rflag != 0)
xo_errx(1, "-a and -r and mutually exclusive"); xo_errx(1, "-a and -r and mutually exclusive");
} else if (nickname != NULL) { } else if (nickname != NULL) {
if (enable != ENABLE_UNSPECIFIED)
xo_errx(1, "-n and -e and mutually exclusive");
if (portal != NULL) if (portal != NULL)
xo_errx(1, "-n and -p and mutually exclusive"); xo_errx(1, "-n and -p and mutually exclusive");
if (target != NULL) if (target != NULL)
@ -838,6 +876,8 @@ main(int argc, char **argv)
xo_errx(1, "-M requires -i"); xo_errx(1, "-M requires -i");
if (nickname != NULL) { if (nickname != NULL) {
if (enable != ENABLE_UNSPECIFIED)
xo_errx(1, "-n and -e and mutually exclusive");
if (portal != NULL) if (portal != NULL)
xo_errx(1, "-n and -p and mutually exclusive"); xo_errx(1, "-n and -p and mutually exclusive");
if (target != NULL) if (target != NULL)
@ -878,6 +918,8 @@ main(int argc, char **argv)
if (discovery_host != NULL) if (discovery_host != NULL)
xo_errx(1, "-d cannot be used with -R"); xo_errx(1, "-d cannot be used with -R");
if (enable != ENABLE_UNSPECIFIED)
xo_errx(1, "-e cannot be used with -R");
if (session_id != -1) if (session_id != -1)
xo_errx(1, "-i cannot be used with -R"); xo_errx(1, "-i cannot be used with -R");
if (rflag != 0) if (rflag != 0)
@ -946,7 +988,7 @@ main(int argc, char **argv)
failed += kernel_list(iscsi_fd, targ, vflag); failed += kernel_list(iscsi_fd, targ, vflag);
} else if (Mflag != 0) { } else if (Mflag != 0) {
kernel_modify_some(iscsi_fd, session_id, target, portal, kernel_modify_some(iscsi_fd, session_id, target, portal,
user, secret); user, secret, enable);
} else { } else {
if (Aflag != 0 && target != NULL) { if (Aflag != 0 && target != NULL) {
if (valid_iscsi_name(target) == false) if (valid_iscsi_name(target) == false)
@ -965,6 +1007,7 @@ main(int argc, char **argv)
targ->t_session_type = SESSION_TYPE_NORMAL; targ->t_session_type = SESSION_TYPE_NORMAL;
targ->t_address = portal; targ->t_address = portal;
} }
targ->t_enable = enable;
if (rflag != 0) if (rflag != 0)
targ->t_protocol = PROTOCOL_ISER; targ->t_protocol = PROTOCOL_ISER;
targ->t_user = user; targ->t_user = user;

View File

@ -58,6 +58,10 @@
#define PROTOCOL_ISCSI 1 #define PROTOCOL_ISCSI 1
#define PROTOCOL_ISER 2 #define PROTOCOL_ISER 2
#define ENABLE_UNSPECIFIED 0
#define ENABLE_ON 1
#define ENABLE_OFF 2
struct target { struct target {
TAILQ_ENTRY(target) t_next; TAILQ_ENTRY(target) t_next;
struct conf *t_conf; struct conf *t_conf;
@ -71,6 +75,7 @@ struct target {
int t_data_digest; int t_data_digest;
int t_auth_method; int t_auth_method;
int t_session_type; int t_session_type;
int t_enable;
int t_protocol; int t_protocol;
char *t_offload; char *t_offload;
char *t_user; char *t_user;
@ -113,5 +118,6 @@ void print_periphs(int session_id);
char *checked_strdup(const char *); char *checked_strdup(const char *);
bool valid_iscsi_name(const char *name); bool valid_iscsi_name(const char *name);
int parse_enable(const char *enable);
#endif /* !ISCSICTL_H */ #endif /* !ISCSICTL_H */

View File

@ -56,7 +56,7 @@ extern void yyrestart(FILE *);
%} %}
%token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS %token AUTH_METHOD ENABLE HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD %token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
%token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET %token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET
@ -118,6 +118,8 @@ target_entry:
| |
session_type session_type
| |
enable
|
offload offload
| |
protocol protocol
@ -253,6 +255,17 @@ session_type: SESSION_TYPE EQUALS STR
} }
; ;
enable: ENABLE EQUALS STR
{
if (target->t_enable != ENABLE_UNSPECIFIED)
xo_errx(1, "duplicated enable at line %d", lineno);
target->t_enable = parse_enable($3);
if (target->t_enable == ENABLE_UNSPECIFIED)
xo_errx(1, "invalid enable at line %d; "
"must be either \"on\" or \"off\"", lineno);
}
;
offload: OFFLOAD EQUALS STR offload: OFFLOAD EQUALS STR
{ {
if (target->t_offload != NULL) if (target->t_offload != NULL)

View File

@ -62,6 +62,7 @@ tgtChapName { return MUTUAL_USER; }
tgtChapSecret { return MUTUAL_SECRET; } tgtChapSecret { return MUTUAL_SECRET; }
AuthMethod { return AUTH_METHOD; } AuthMethod { return AUTH_METHOD; }
SessionType { return SESSION_TYPE; } SessionType { return SESSION_TYPE; }
enable { return ENABLE; }
protocol { return PROTOCOL; } protocol { return PROTOCOL; }
offload { return OFFLOAD; } offload { return OFFLOAD; }
port { return IGNORED; } port { return IGNORED; }