Blob Blame History Raw
From 4d3d30ea5bcb917fed58f1cb57154de5e6ce2349 Mon Sep 17 00:00:00 2001
From: Chris Leech <cleech@redhat.com>
Date: Fri, 24 Jul 2015 14:18:30 -0700
Subject: [PATCH] share session use checks with iscsiadm, apply for flashnode
 session

---
 usr/Makefile           |   8 +-
 usr/initiator.c        | 196 +----------------------------------------
 usr/initiator.h        |   1 +
 usr/initiator_common.c |   3 +
 usr/iscsiadm.c         |  23 +++++
 usr/iscsistart.c       |   2 +
 usr/mntcheck.c         | 234 +++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 268 insertions(+), 199 deletions(-)
 create mode 100644 usr/mntcheck.c

diff --git a/usr/Makefile b/usr/Makefile
index b2c1504..93b03d5 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -54,15 +54,15 @@ DISCOVERY_SRCS = $(FW_BOOT_SRCS) strings.o discovery.o
 all: $(PROGRAMS)
 
 iscsid: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(DISCOVERY_SRCS) \
-	iscsid.o session_mgmt.o discoveryd.o
+	iscsid.o session_mgmt.o discoveryd.o mntcheck.o
 	$(CC) $(CFLAGS) $^ -o $@  -L../utils/open-isns -lisns -lmount
 
-iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o
-	$(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns
+iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o mntcheck.o
+	$(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns -lmount
 
 iscsistart: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(FW_BOOT_SRCS) \
 		iscsistart.o statics.o
-	$(CC) $(CFLAGS) -static $^ -o $@ -lmount
+	$(CC) $(CFLAGS) -static $^ -o $@
 clean:
 	rm -f *.o $(PROGRAMS) .depend $(LIBSYS)
 
diff --git a/usr/initiator.c b/usr/initiator.c
index 1b4c90a..701b9a5 100644
--- a/usr/initiator.c
+++ b/usr/initiator.c
@@ -30,7 +30,6 @@
 #include <errno.h>
 #include <dirent.h>
 #include <fcntl.h>
-#include <libmount/libmount.h>
 
 #include "initiator.h"
 #include "transport.h"
@@ -2141,199 +2140,6 @@ static int session_unbind(struct iscsi_session *session)
 	return err;
 }
 
-static struct libmnt_table *mtab, *swaps;
-static struct libmnt_cache *mntcache;
-
-static void libmount_cleanup(void)
-{
-	mnt_free_table(mtab);
-	mnt_free_table(swaps);
-	mnt_free_cache(mntcache);
-	mtab = swaps = mntcache = NULL;
-}
-
-static int libmount_init(void)
-{
-	mnt_init_debug(0);
-	mtab = mnt_new_table();
-	swaps = mnt_new_table();
-	mntcache = mnt_new_cache();
-	if (!mtab || !swaps || !mntcache) {
-		libmount_cleanup();
-		return -ENOMEM;
-	}
-	mnt_table_set_cache(mtab, mntcache);
-	mnt_table_set_cache(swaps, mntcache);
-	mnt_table_parse_mtab(mtab, NULL);
-	mnt_table_parse_swaps(swaps, NULL);
-	return 0;
-}
-
-static int trans_filter(const struct dirent *d)
-{
-	if (!strcmp(".", d->d_name) || !strcmp("..", d->d_name))
-		return 0;
-	return 1;
-}
-
-static int subdir_filter(const struct dirent *d)
-{
-	if (!(d->d_type & DT_DIR))
-		return 0;
-	return trans_filter(d);
-}
-
-static int is_partition(const char *path)
-{
-	char *devtype;
-	int rc = 0;
-
-	devtype = sysfs_get_uevent_devtype(path);
-	if (!devtype)
-		return 0;
-	if (strcmp(devtype, "partition") == 0)
-		rc = 1;
-	free(devtype);
-	return rc;
-}
-
-static int blockdev_check_mnts(char *syspath)
-{
-	struct libmnt_fs *fs;
-	char *devname = NULL;
-	char *_devname = NULL;
-	int rc = 0;
-
-	devname = sysfs_get_uevent_devname(syspath);
-	if (!devname)
-		goto out;
-
-	_devname = calloc(1, PATH_MAX);
-	if (!_devname)
-		goto out;
-	snprintf(_devname, PATH_MAX, "/dev/%s", devname);
-
-	fs = mnt_table_find_source(mtab, _devname, MNT_ITER_FORWARD);
-	if (fs) {
-		rc = 1;
-		goto out;
-	}
-	fs = mnt_table_find_source(swaps, _devname, MNT_ITER_FORWARD);
-	if (fs)
-		rc = 1;
-out:
-	free(devname);
-	free(_devname);
-	return rc;
-}
-
-static int count_device_users(char *syspath);
-
-static int blockdev_get_partitions(char *syspath)
-{
-	struct dirent **parts = NULL;
-	int n, i;
-	int count = 0;
-
-	n = scandir(syspath, &parts, subdir_filter, alphasort);
-	for (i = 0; i < n; i++) {
-		char *newpath;
-
-		newpath = calloc(1, PATH_MAX);
-		if (!newpath)
-			continue;
-		snprintf(newpath, PATH_MAX, "%s/%s", syspath, parts[i]->d_name);
-		free(parts[i]);
-		if (is_partition(newpath)) {
-			count += count_device_users(newpath);
-		}
-		free(newpath);
-	}
-	free(parts);
-	return count;
-}
-
-static int blockdev_get_holders(char *syspath)
-{
-	char *path = NULL;
-	struct dirent **holds = NULL;
-	int n, i;
-	int count = 0;
-
-	path = calloc(1, PATH_MAX);
-	if (!path)
-		return 0;
-	snprintf(path, PATH_MAX, "%s/holders", syspath);
-
-	n = scandir(path, &holds, trans_filter, alphasort);
-	for (i = 0; i < n; i++) {
-		char *newpath;
-		char *rp;
-
-		newpath = calloc(1, PATH_MAX);
-		if (!newpath)
-			continue;
-		snprintf(newpath, PATH_MAX, "%s/%s", path, holds[i]->d_name);
-
-		free(holds[i]);
-		rp = realpath(newpath, NULL);
-		if (rp)
-			count += count_device_users(rp);
-		free(newpath);
-		free(rp);
-	}
-	free(path);
-	free(holds);
-	return count;
-}
-
-static int count_device_users(char *syspath)
-{
-	int count = 0;
-	count += blockdev_check_mnts(syspath);
-	count += blockdev_get_partitions(syspath);
-	count += blockdev_get_holders(syspath);
-	return count;
-};
-
-static void device_in_use(void *data, int host_no, int target, int lun)
-{
-	char *syspath = NULL;
-	char *devname = NULL;
-	int *count = data;
-
-	devname = iscsi_sysfs_get_blockdev_from_lun(host_no, target, lun);
-	if (!devname)
-		goto out;
-	syspath = calloc(1, PATH_MAX);
-	if (!syspath)
-		goto out;
-	snprintf(syspath, PATH_MAX, "/sys/class/block/%s", devname);
-	*count += count_device_users(syspath);
-out:
-	free(syspath);
-	free(devname);
-}
-
-static int session_in_use(int sid)
-{
-	int host_no = -1, err = 0;
-	int count = 0;
-
-	if (libmount_init()) {
-		log_error("Failed to initialize libmount, "
-			  "not checking for active mounts on session [%d].\n", sid);
-		return 0;
-	}
-
-	host_no = iscsi_sysfs_get_host_no_from_sid(sid, &err);
-	if (!err)
-		iscsi_sysfs_for_each_device(&count, host_no, sid, device_in_use);
-
-	libmount_cleanup();
-	return count;
-}
-
 int session_logout_task(int sid, queue_task_t *qtask)
 {
 	iscsi_session_t *session;
@@ -2363,7 +2169,7 @@ invalid_state:
 
 	if (dconfig->safe_logout && session_in_use(sid)) {
 		log_error("Session is actively in use for mounted storage, "
-			  "and iscsid.safe_logout is configured.\n");
+			  "and iscsid.safe_logout is configured.");
 		return ISCSI_ERR_BUSY;
 	}
 
diff --git a/usr/initiator.h b/usr/initiator.h
index c34625b..e8bce45 100644
--- a/usr/initiator.h
+++ b/usr/initiator.h
@@ -360,4 +360,5 @@ extern int iscsi_set_net_config(struct iscsi_transport *t,
 				struct iface_rec *iface);
 extern void iscsi_session_init_params(struct iscsi_session *session);
 
+extern int session_in_use(int sid);
 #endif /* INITIATOR_H */
diff --git a/usr/initiator_common.c b/usr/initiator_common.c
index 8ff993d..4e574b4 100644
--- a/usr/initiator_common.c
+++ b/usr/initiator_common.c
@@ -23,6 +23,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <dirent.h>
+#include <libmount/libmount.h>
 
 #include "initiator.h"
 #include "transport.h"
@@ -741,3 +743,4 @@ int iscsi_host_set_net_params(struct iface_rec *iface,
 	}
 	return 0;
 }
+
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index f886d39..d5d38b1 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -1898,11 +1898,34 @@ exit_logout:
 	return rc;
 }
 
+static int iscsi_check_session_use_count(uint32_t sid) {
+	char *config_file;
+	char *safe_logout;
+
+	config_file = get_config_file();
+	if (!config_file) {
+		log_error("Could not get config file from iscsid");
+		return 0;
+	}
+
+	safe_logout = cfg_get_string_param(config_file, "iscsid.safe_logout");
+	if (!safe_logout || strcmp(safe_logout, "Yes"))
+		return 0;
+
+	return session_in_use(sid);
+}
+
 int iscsi_logout_flashnode_sid(struct iscsi_transport *t, uint32_t host_no,
 			       uint32_t sid)
 {
 	int fd, rc = 0;
 
+	if (iscsi_check_session_use_count(sid)) {
+		log_error("Session is actively in use for mounted storage, "
+			  "and iscsid.safe_logout is configured.");
+		return ISCSI_ERR_BUSY;
+	}
+
 	fd = ipc->ctldev_open();
 	if (fd < 0) {
 		log_error("Netlink open failed.");
diff --git a/usr/iscsistart.c b/usr/iscsistart.c
index 6924d49..26ba014 100644
--- a/usr/iscsistart.c
+++ b/usr/iscsistart.c
@@ -279,6 +279,8 @@ static int setup_session(void)
 	return rc;
 }
 
+int session_in_use(int sid) { return 0; }
+
 static void catch_signal(int signo)
 {
 	log_warning("pid %d caught signal -%d", getpid(), signo);
diff --git a/usr/mntcheck.c b/usr/mntcheck.c
new file mode 100644
index 0000000..57bf007
--- /dev/null
+++ b/usr/mntcheck.c
@@ -0,0 +1,234 @@
+/*
+ * Common code for checking sessions for mnt use
+ *
+ * Copyright (C) 2014 - 2015 Chris Leech
+ * Copyright (C) 2014 - 2015 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <dirent.h>
+#include <libmount/libmount.h>
+
+#include "initiator.h"
+#include "transport.h"
+#include "iscsid.h"
+#include "iscsi_ipc.h"
+#include "log.h"
+#include "iscsi_sysfs.h"
+#include "iscsi_settings.h"
+#include "iface.h"
+#include "host.h"
+#include "sysdeps.h"
+#include "iscsi_err.h"
+#include "iscsi_net_util.h"
+
+static struct libmnt_table *mtab, *swaps;
+static struct libmnt_cache *mntcache;
+
+static void libmount_cleanup(void)
+{
+	mnt_free_table(mtab);
+	mnt_free_table(swaps);
+	mnt_free_cache(mntcache);
+	mtab = NULL;
+	swaps = NULL;
+	mntcache = NULL;
+}
+
+static int libmount_init(void)
+{
+	mnt_init_debug(0);
+	mtab = mnt_new_table();
+	swaps = mnt_new_table();
+	mntcache = mnt_new_cache();
+	if (!mtab || !swaps || !mntcache) {
+		libmount_cleanup();
+		return -ENOMEM;
+	}
+	mnt_table_set_cache(mtab, mntcache);
+	mnt_table_set_cache(swaps, mntcache);
+	mnt_table_parse_mtab(mtab, NULL);
+	mnt_table_parse_swaps(swaps, NULL);
+	return 0;
+}
+
+static int trans_filter(const struct dirent *d)
+{
+	if (!strcmp(".", d->d_name) || !strcmp("..", d->d_name))
+		return 0;
+	return 1;
+}
+
+static int subdir_filter(const struct dirent *d)
+{
+	if (!(d->d_type & DT_DIR))
+		return 0;
+	return trans_filter(d);
+}
+
+static int is_partition(const char *path)
+{
+	char *devtype;
+	int rc = 0;
+
+	devtype = sysfs_get_uevent_devtype(path);
+	if (!devtype)
+		return 0;
+	if (strcmp(devtype, "partition") == 0)
+		rc = 1;
+	free(devtype);
+	return rc;
+}
+
+static int blockdev_check_mnts(char *syspath)
+{
+	struct libmnt_fs *fs;
+	char *devname = NULL;
+	char *_devname = NULL;
+	int rc = 0;
+
+	devname = sysfs_get_uevent_devname(syspath);
+	if (!devname)
+		goto out;
+
+	_devname = calloc(1, PATH_MAX);
+	if (!_devname)
+		goto out;
+	snprintf(_devname, PATH_MAX, "/dev/%s", devname);
+
+	fs = mnt_table_find_source(mtab, _devname, MNT_ITER_FORWARD);
+	if (fs) {
+		rc = 1;
+		goto out;
+	}
+	fs = mnt_table_find_source(swaps, _devname, MNT_ITER_FORWARD);
+	if (fs)
+		rc = 1;
+out:
+	free(devname);
+	free(_devname);
+	return rc;
+}
+
+static int count_device_users(char *syspath);
+
+static int blockdev_get_partitions(char *syspath)
+{
+	struct dirent **parts = NULL;
+	int n, i;
+	int count = 0;
+
+	n = scandir(syspath, &parts, subdir_filter, alphasort);
+	for (i = 0; i < n; i++) {
+		char *newpath;
+
+		newpath = calloc(1, PATH_MAX);
+		if (!newpath)
+			continue;
+		snprintf(newpath, PATH_MAX, "%s/%s", syspath, parts[i]->d_name);
+		free(parts[i]);
+		if (is_partition(newpath)) {
+			count += count_device_users(newpath);
+		}
+		free(newpath);
+	}
+	free(parts);
+	return count;
+}
+
+static int blockdev_get_holders(char *syspath)
+{
+	char *path = NULL;
+	struct dirent **holds = NULL;
+	int n, i;
+	int count = 0;
+
+	path = calloc(1, PATH_MAX);
+	if (!path)
+		return 0;
+	snprintf(path, PATH_MAX, "%s/holders", syspath);
+
+	n = scandir(path, &holds, trans_filter, alphasort);
+	for (i = 0; i < n; i++) {
+		char *newpath;
+		char *rp;
+
+		newpath = calloc(1, PATH_MAX);
+		if (!newpath)
+			continue;
+		snprintf(newpath, PATH_MAX, "%s/%s", path, holds[i]->d_name);
+
+		free(holds[i]);
+		rp = realpath(newpath, NULL);
+		if (rp)
+			count += count_device_users(rp);
+		free(newpath);
+		free(rp);
+	}
+	free(path);
+	free(holds);
+	return count;
+}
+
+static int count_device_users(char *syspath)
+{
+	int count = 0;
+	count += blockdev_check_mnts(syspath);
+	count += blockdev_get_partitions(syspath);
+	count += blockdev_get_holders(syspath);
+	return count;
+};
+
+static void device_in_use(void *data, int host_no, int target, int lun)
+{
+	char *syspath = NULL;
+	char *devname = NULL;
+	int *count = data;
+
+	devname = iscsi_sysfs_get_blockdev_from_lun(host_no, target, lun);
+	if (!devname)
+		goto out;
+	syspath = calloc(1, PATH_MAX);
+	if (!syspath)
+		goto out;
+	snprintf(syspath, PATH_MAX, "/sys/class/block/%s", devname);
+	*count += count_device_users(syspath);
+out:
+	free(syspath);
+	free(devname);
+}
+
+int session_in_use(int sid)
+{
+	int host_no = -1, err = 0;
+	int count = 0;
+
+	if (libmount_init()) {
+		log_error("Failed to initialize libmount, "
+			  "not checking for active mounts on session [%d].\n", sid);
+		return 0;
+	}
+
+	host_no = iscsi_sysfs_get_host_no_from_sid(sid, &err);
+	if (!err)
+		iscsi_sysfs_for_each_device(&count, host_no, sid, device_in_use);
+
+	libmount_cleanup();
+	return count;
+}
+
-- 
2.1.0