summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-07-06 17:57:59 +0000
committermav <mav@FreeBSD.org>2014-07-06 17:57:59 +0000
commitac68a20a27159e0ed74698fc31e53c56228aa396 (patch)
treea8be5c88fc1a7a227559ba199b9d78ff13302ffa
parentd74e85dbb9aba51f1ffc63a0ebae250559a8fcd9 (diff)
downloadFreeBSD-src-ac68a20a27159e0ed74698fc31e53c56228aa396.zip
FreeBSD-src-ac68a20a27159e0ed74698fc31e53c56228aa396.tar.gz
Close race in r268291 between port destruction, delayed by sessions
teardown, and new port creation during `service ctld restart`. Close it by returning iSCSI port internal state, that allows to identify dying ports, which should not be counted as existing, from really alive.
-rw-r--r--sys/cam/ctl/ctl.c5
-rw-r--r--sys/cam/ctl/ctl_frontend.h2
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c13
-rw-r--r--usr.sbin/ctld/kernel.c8
4 files changed, 28 insertions, 0 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index ca25c8b..1aeb9e7 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -3252,6 +3252,11 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (retval != 0)
break;
+ if (port->port_info != NULL) {
+ retval = port->port_info(port->onoff_arg, sb);
+ if (retval != 0)
+ break;
+ }
STAILQ_FOREACH(opt, &port->options, links) {
retval = sbuf_printf(sb, "\t<%s>%s</%s>\n",
opt->name, opt->value, opt->name);
diff --git a/sys/cam/ctl/ctl_frontend.h b/sys/cam/ctl/ctl_frontend.h
index cb08962..2582ecc 100644
--- a/sys/cam/ctl/ctl_frontend.h
+++ b/sys/cam/ctl/ctl_frontend.h
@@ -49,6 +49,7 @@ typedef enum {
typedef int (*fe_init_t)(void);
typedef void (*fe_shutdown_t)(void);
typedef void (*port_func_t)(void *onoff_arg);
+typedef int (*port_info_func_t)(void *onoff_arg, struct sbuf *sb);
typedef int (*lun_func_t)(void *arg, struct ctl_id targ_id, int lun_id);
typedef uint32_t (*lun_map_func_t)(void *arg, uint32_t lun_id);
typedef int (*fe_ioctl_t)(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
@@ -214,6 +215,7 @@ struct ctl_port {
int virtual_port; /* passed to CTL */
port_func_t port_online; /* passed to CTL */
port_func_t port_offline; /* passed to CTL */
+ port_info_func_t port_info; /* passed to CTL */
void *onoff_arg; /* passed to CTL */
lun_func_t lun_enable; /* passed to CTL */
lun_func_t lun_disable; /* passed to CTL */
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index fa8bd82..3f39a35 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -145,6 +145,7 @@ SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, maxcmdsn_delta, CTLFLAG_RWTUN,
int cfiscsi_init(void);
static void cfiscsi_online(void *arg);
static void cfiscsi_offline(void *arg);
+static int cfiscsi_info(void *arg, struct sbuf *sb);
static int cfiscsi_lun_enable(void *arg,
struct ctl_id target_id, int lun_id);
static int cfiscsi_lun_disable(void *arg,
@@ -1411,6 +1412,17 @@ cfiscsi_offline(void *arg)
#endif
}
+static int
+cfiscsi_info(void *arg, struct sbuf *sb)
+{
+ struct cfiscsi_target *ct = (struct cfiscsi_target *)arg;
+ int retval;
+
+ retval = sbuf_printf(sb, "\t<cfiscsi_state>%d</cfiscsi_state>\n",
+ ct->ct_state);
+ return (retval);
+}
+
static void
cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
{
@@ -1993,6 +2005,7 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
port->virtual_port = strtoul(tag, NULL, 0);
port->port_online = cfiscsi_online;
port->port_offline = cfiscsi_offline;
+ port->port_info = cfiscsi_info;
port->onoff_arg = ct;
port->lun_enable = cfiscsi_lun_enable;
port->lun_disable = cfiscsi_lun_disable;
diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c
index 74cb27e..a286d35 100644
--- a/usr.sbin/ctld/kernel.c
+++ b/usr.sbin/ctld/kernel.c
@@ -120,6 +120,7 @@ struct cctl_lun {
struct cctl_port {
uint32_t port_id;
+ int cfiscsi_status;
char *cfiscsi_target;
uint16_t cfiscsi_portal_group_tag;
STAILQ_HEAD(,cctl_lun_nv) attr_list;
@@ -332,6 +333,8 @@ cctl_end_pelement(void *user_data, const char *name)
if (strcmp(name, "cfiscsi_target") == 0) {
cur_port->cfiscsi_target = str;
str = NULL;
+ } else if (strcmp(name, "cfiscsi_status") == 0) {
+ cur_port->cfiscsi_status = strtoul(str, NULL, 0);
} else if (strcmp(name, "cfiscsi_portal_group_tag") == 0) {
cur_port->cfiscsi_portal_group_tag = strtoul(str, NULL, 0);
} else if (strcmp(name, "targ_port") == 0) {
@@ -494,6 +497,11 @@ retry_port:
"ignoring", (uintmax_t)port->port_id);
continue;
}
+ if (port->cfiscsi_status != 1) {
+ log_debugx("CTL port %ju is not active (%d); ignoring",
+ (uintmax_t)port->port_id, port->cfiscsi_status);
+ continue;
+ }
targ = target_find(conf, port->cfiscsi_target);
if (targ == NULL) {
OpenPOWER on IntegriCloud