[stgt] [PATCH] Make the backing-store modules shared objects that are loaded at runtime

Ronnie Sahlberg ronniesahlberg at gmail.com
Sat Aug 10 01:02:05 CEST 2013


Turn most of TGTD into a shared library libtgt.so and install it under
$(PREFIX)/lib/tgtd

Change the six backing stores  bs_aio/null/rdb/rdwr/sg/ssc into shared objects
and install them under $(PREFIX)/lib/tgtd/backing-store

When tgtd is starting, have it traverse the directory for backing stores and
automatically load and initialize all backing stores files that are found.

This allows for example to distribute bs_aio.so as a separate package
since it has additional dependencies (libaio) that tgtd itself does not have
Similarly for bs_rdb.so.
This means that core TGTD can be distributed with minimal dependencies
and backends that add additional dependencies can be distributed separately.

Once we have this basics for a modularized TGTD later patches can build ontop
of this and add features such as :
* list all modules and which luns are using them
* unload module if unused
* re-load module
But that can come in later patches. Lets get the basics in first.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
---
 usr/Makefile  |   42 ++++++---
 usr/bs.c      |   46 +++++++++
 usr/bs_aio.c  |    2 +-
 usr/bs_null.c |    2 +-
 usr/bs_rdwr.c |    2 +-
 usr/bs_sg.c   |    2 +-
 usr/bs_ssc.c  |    2 +-
 usr/target.c  |  285 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 usr/tgtd.c    |  276 +-------------------------------------------------------
 usr/tgtd.h    |    2 +
 10 files changed, 360 insertions(+), 301 deletions(-)

diff --git a/usr/Makefile b/usr/Makefile
index 453eb1a..5c76f43 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -1,4 +1,5 @@
 sbindir ?= $(PREFIX)/sbin
+libdir ?= $(PREFIX)/lib/tgtd
 
 ifneq ($(shell test -e /usr/include/linux/signalfd.h && echo 1),)
 CFLAGS += -DUSE_SIGNALFD
@@ -11,17 +12,14 @@ endif
 TGTD_OBJS += $(addprefix iscsi/, conn.o param.o session.o \
 		iscsid.o target.o chap.o sha1.o md5.o transport.o iscsi_tcp.o \
 		isns.o)
-TGTD_OBJS += bs_rdwr.o
 
 ifneq ($(CEPH_RBD),)
-TGTD_OBJS += bs_rbd.o
-LIBS += -lrados -lrbd
+BS_OBJS += bs_rdb.so
 endif
 
 ifneq ($(shell test -e /usr/include/sys/eventfd.h && test -e /usr/include/libaio.h && echo 1),)
 CFLAGS += -DUSE_EVENTFD
-TGTD_OBJS += bs_aio.o
-LIBS += -laio
+BS_OBJS += bs_aio.so
 endif
 
 ifneq ($(ISCSI_RDMA),)
@@ -40,25 +38,32 @@ CFLAGS += -g -O2 -fno-strict-aliasing
 endif
 CFLAGS += -Wall -Wstrict-prototypes -fPIC
 CFLAGS += -DTGT_VERSION=\"$(VERSION)$(EXTRAVERSION)\"
+CFLAGS += -DBSDIR=\"$(DESTDIR)$(libdir)/backing-store\"
 
 LIBS += -lpthread
 
 PROGRAMS += tgtd tgtadm tgtimg
-TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o log.o driver.o util.o work.o \
-		concat_buf.o parser.o spc.o sbc.o mmc.o osd.o scc.o smc.o \
-		ssc.o bs_ssc.o libssc.o \
-		bs_null.o bs_sg.o bs.o libcrc32c.o
+TGTD_OBJS += tgtd.o 
+LIBTGT_OBJS = bs.o \
+	concat_buf.o driver.o libcrc32c.o libssc.o log.o mgmt.o mmc.o \
+	osd.o parser.o sbc.o scc.o scsi.o smc.o spc.o ssc.o \
+	target.o util.o work.o
+
+BS_OBJS += bs_null.so bs_rdwr.so bs_sg.so bs_ssc.so
 
 TGTD_DEP = $(TGTD_OBJS:.o=.d)
 
 .PHONY:all
-all: $(PROGRAMS)
+all: libtgt.so $(PROGRAMS) $(BS_OBJS) 
 
 tgtd: $(TGTD_OBJS)
-	$(CC) $^ -o $@ $(LIBS)
+	$(CC) $^ -o $@ $(LIBS) libtgt.so
 
 -include $(TGTD_DEP)
 
+libtgt.so: $(LIBTGT_OBJS)
+	$(CC) -shared -fPIC -DPIC $^ -o $@  -ldl
+
 TGTADM_OBJS = tgtadm.o concat_buf.o
 TGTADM_DEP = $(TGTADM_OBJS:.o=.d)
 
@@ -79,11 +84,24 @@ tgtimg: $(TGTIMG_OBJS)
 	$(CC) -c $(CFLAGS) $*.c -o $*.o
 	@$(CC) -MM $(CFLAGS) -MF $*.d -MT $*.o $*.c
 
+%.so: %.c
+	$(CC) -shared $(CFLAGS) $*.c -o $*.so
+
+bs_aio.so: bs_aio.c
+	$(CC) -shared $(CFLAGS) bs_aio.c -o bs_aio.so -laio
+
+bs_rdb.so: bs_rdb.c
+	$(CC) -shared $(CFLAGS) bs_rdb.c -o bs_rdb.so -lrados -lrbd
+
 .PHONY: install
 install: $(PROGRAMS)
 	install -d -m 755 $(DESTDIR)$(sbindir)
 	install -m 755 $(PROGRAMS) $(DESTDIR)$(sbindir)
+	install -d -m 755 $(DESTDIR)$(libdir)/backing-store
+	install -m 755 $(BS_OBJS) $(DESTDIR)$(libdir)/backing-store
+	install -m 755 libtgt.so $(DESTDIR)$(libdir)
+	ldconfig $(DESTDIR)$(libdir)
 
 .PHONY: clean
 clean:
-	rm -f *.[od] $(PROGRAMS) iscsi/*.[od] ibmvio/*.[od] fc/*.[od]
+	rm -f *.[od] *.so $(PROGRAMS) iscsi/*.[od] ibmvio/*.[od] fc/*.[od]
diff --git a/usr/bs.c b/usr/bs.c
index 65c332e..7974e3a 100644
--- a/usr/bs.c
+++ b/usr/bs.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA
  */
+#include <dirent.h>
+#include <dlfcn.h>
 #include <errno.h>
 #include <string.h>
 #include <inttypes.h>
@@ -307,10 +309,54 @@ destroy_cond_mutex:
 	return 1;
 }
 
+void update_lbppbe(struct scsi_lu *lu, int blksize)
+{
+	lu->attrs.lbppbe = 0;
+	while (blksize > (1U << lu->blk_shift)) {
+		lu->attrs.lbppbe++;
+		blksize >>= 1;
+	}
+}
+
 int bs_init(void)
 {
+	DIR *dir;
 	int ret;
 
+	dir = opendir(BSDIR);
+	if (dir == NULL) {
+		eprintf("could not open backing-store module directory %s\n",
+			BSDIR); 
+	} else {
+		struct dirent *dirent;
+		void *handle;
+		while ((dirent = readdir(dir))) {
+			char *soname;
+			void (*register_bs_module)(void);
+
+			if (dirent->d_name[0] == '.') {
+				continue;
+			}
+
+			asprintf(&soname, "%s/%s", BSDIR, dirent->d_name);
+			handle = dlopen(soname, RTLD_NOW|RTLD_LOCAL);
+			if (handle == NULL) {
+				eprintf("failed to dlopen backing-store "
+					"module %s error %s \n",
+					soname, dlerror());
+				continue;
+			}
+			register_bs_module = dlsym(handle, "register_bs_module");
+			if (register_bs_module == NULL) {
+				eprintf("could not find register_bs_module "
+					"symbol in module %s\n",
+					soname);
+				continue;
+			}
+			register_bs_module();
+		}
+		closedir(dir);
+	}
 	ret = bs_init_signalfd();
 	if (!ret) {
 		eprintf("use signalfd notification\n");
diff --git a/usr/bs_aio.c b/usr/bs_aio.c
index c0cbadd..cc59cf6 100644
--- a/usr/bs_aio.c
+++ b/usr/bs_aio.c
@@ -414,7 +414,7 @@ static struct backingstore_template aio_bst = {
 	.bs_cmd_submit  	= bs_aio_cmd_submit,
 };
 
-__attribute__((constructor)) static void bs_rdwr_constructor(void)
+void register_bs_module(void)
 {
 	register_backingstore_template(&aio_bst);
 }
diff --git a/usr/bs_null.c b/usr/bs_null.c
index d463f18..4dbe144 100644
--- a/usr/bs_null.c
+++ b/usr/bs_null.c
@@ -56,7 +56,7 @@ static struct backingstore_template null_bst = {
 	.bs_cmd_submit		= bs_null_cmd_submit,
 };
 
-__attribute__((constructor)) static void bs_null_constructor(void)
+void register_bs_module(void)
 {
 	register_backingstore_template(&null_bst);
 }
diff --git a/usr/bs_rdwr.c b/usr/bs_rdwr.c
index 47d2d99..82807d1 100644
--- a/usr/bs_rdwr.c
+++ b/usr/bs_rdwr.c
@@ -423,7 +423,7 @@ static struct backingstore_template rdwr_bst = {
 	.bs_oflags_supported    = O_SYNC | O_DIRECT,
 };
 
-__attribute__((constructor)) static void bs_rdwr_constructor(void)
+void register_bs_module(void)
 {
 	register_backingstore_template(&rdwr_bst);
 }
diff --git a/usr/bs_sg.c b/usr/bs_sg.c
index 5f1e687..43dc5f3 100644
--- a/usr/bs_sg.c
+++ b/usr/bs_sg.c
@@ -517,7 +517,7 @@ static struct device_type_template sg_template = {
 	.cmd_passthrough	= bs_sg_rw,
 };
 
-__attribute__((constructor)) static void bs_sg_constructor(void)
+void register_bs_module(void)
 {
 	register_backingstore_template(&sg_bst);
 	register_backingstore_template(&bsg_bst);
diff --git a/usr/bs_ssc.c b/usr/bs_ssc.c
index 117e274..98b84b5 100644
--- a/usr/bs_ssc.c
+++ b/usr/bs_ssc.c
@@ -702,7 +702,7 @@ static struct backingstore_template ssc_bst = {
 	.bs_cmd_submit		= bs_thread_cmd_submit,
 };
 
-__attribute__((constructor)) static void bs_ssc_constructor(void)
+void register_bs_module(void)
 {
 	register_backingstore_template(&ssc_bst);
 }
diff --git a/usr/target.c b/usr/target.c
index b1729b3..b7872fb 100644
--- a/usr/target.c
+++ b/usr/target.c
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA
  */
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -27,8 +28,10 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <sys/epoll.h>
 #include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/wait.h>
 
 #include "list.h"
 #include "util.h"
@@ -42,8 +45,11 @@
 #include "spc.h"
 
 static LIST_HEAD(device_type_list);
+static LIST_HEAD(tgt_events_list);
+static LIST_HEAD(tgt_sched_events_list);
 
 static struct target global_target;
+int ep_fd;
 
 int device_type_register(struct device_type_template *t)
 {
@@ -2411,15 +2417,6 @@ tgtadm_err lld_show(struct concat_buf *b)
 	return TGTADM_SUCCESS;
 }
 
-void update_lbppbe(struct scsi_lu *lu, int blksize)
-{
-	lu->attrs.lbppbe = 0;
-	while (blksize > (1U << lu->blk_shift)) {
-		lu->attrs.lbppbe++;
-		blksize >>= 1;
-	}
-}
-
 int is_system_available(void)
 {
 	return (sys_state == TGT_SYSTEM_READY);
@@ -2430,6 +2427,276 @@ int is_system_inactive(void)
 	return list_empty(&target_list);
 }
 
+int tgt_event_add(int fd, int events, event_handler_t handler, void *data)
+{
+	struct epoll_event ev;
+	struct event_data *tev;
+	int err;
+
+	tev = zalloc(sizeof(*tev));
+	if (!tev)
+		return -ENOMEM;
+
+	tev->data = data;
+	tev->handler = handler;
+	tev->fd = fd;
+
+	memset(&ev, 0, sizeof(ev));
+	ev.events = events;
+	ev.data.ptr = tev;
+	err = epoll_ctl(ep_fd, EPOLL_CTL_ADD, fd, &ev);
+	if (err) {
+		eprintf("Cannot add fd, %m\n");
+		free(tev);
+	} else
+		list_add(&tev->e_list, &tgt_events_list);
+
+	return err;
+}
+
+static struct event_data *tgt_event_lookup(int fd)
+{
+	struct event_data *tev;
+
+	list_for_each_entry(tev, &tgt_events_list, e_list) {
+		if (tev->fd == fd)
+			return tev;
+	}
+	return NULL;
+}
+
+void tgt_event_del(int fd)
+{
+	struct event_data *tev;
+	int ret;
+
+	tev = tgt_event_lookup(fd);
+	if (!tev) {
+		eprintf("Cannot find event %d\n", fd);
+		return;
+	}
+
+	ret = epoll_ctl(ep_fd, EPOLL_CTL_DEL, fd, NULL);
+	if (ret < 0)
+		eprintf("fail to remove epoll event, %s\n", strerror(errno));
+
+	list_del(&tev->e_list);
+	free(tev);
+}
+
+int tgt_event_modify(int fd, int events)
+{
+	struct epoll_event ev;
+	struct event_data *tev;
+
+	tev = tgt_event_lookup(fd);
+	if (!tev) {
+		eprintf("Cannot find event %d\n", fd);
+		return -EINVAL;
+	}
+
+	memset(&ev, 0, sizeof(ev));
+	ev.events = events;
+	ev.data.ptr = tev;
+
+	return epoll_ctl(ep_fd, EPOLL_CTL_MOD, fd, &ev);
+}
+
+void tgt_init_sched_event(struct event_data *evt,
+			  sched_event_handler_t sched_handler, void *data)
+{
+	evt->sched_handler = sched_handler;
+	evt->scheduled = 0;
+	evt->data = data;
+	INIT_LIST_HEAD(&evt->e_list);
+}
+
+void tgt_add_sched_event(struct event_data *evt)
+{
+	if (!evt->scheduled) {
+		evt->scheduled = 1;
+		list_add_tail(&evt->e_list, &tgt_sched_events_list);
+	}
+}
+
+void tgt_remove_sched_event(struct event_data *evt)
+{
+	if (evt->scheduled) {
+		evt->scheduled = 0;
+		list_del_init(&evt->e_list);
+	}
+}
+
+int tgt_exec_scheduled(void)
+{
+	struct list_head *last_sched;
+	struct event_data *tev, *tevn;
+	int work_remains = 0;
+
+	if (!list_empty(&tgt_sched_events_list)) {
+		/* execute only work scheduled till now */
+		last_sched = tgt_sched_events_list.prev;
+		list_for_each_entry_safe(tev, tevn, &tgt_sched_events_list,
+					 e_list) {
+			tgt_remove_sched_event(tev);
+			tev->sched_handler(tev);
+			if (&tev->e_list == last_sched)
+				break;
+		}
+		if (!list_empty(&tgt_sched_events_list))
+			work_remains = 1;
+	}
+	return work_remains;
+}
+
+/* strcpy, while eating multiple white spaces */
+static void str_spacecpy(char **dest, const char *src)
+{
+	const char *s = src;
+	char *d = *dest;
+
+	while (*s) {
+		if (isspace(*s)) {
+			if (!*(s+1))
+				break;
+			if (isspace(*(s+1))) {
+				s++;
+				continue;
+			}
+		}
+		*d++ = *s++;
+	}
+	*d = '\0';
+}
+
+int call_program(const char *cmd, void (*callback)(void *data, int result),
+		void *data, char *output, int op_len, int flags)
+{
+	pid_t pid;
+	int fds[2], ret, i;
+	char *pos, arg[256];
+	char *argv[sizeof(arg) / 2];
+
+	i = 0;
+	pos = arg;
+	str_spacecpy(&pos, cmd);
+	if (strchr(cmd, ' ')) {
+		while (pos != '\0')
+			argv[i++] = strsep(&pos, " ");
+	} else
+		argv[i++] = arg;
+	argv[i] =  NULL;
+
+	ret = pipe(fds);
+	if (ret < 0) {
+		eprintf("pipe create failed for %s, %m\n", cmd);
+		return ret;
+	}
+
+	dprintf("%s, pipe: %d %d\n", cmd, fds[0], fds[1]);
+
+	pid = fork();
+	if (pid < 0) {
+		eprintf("fork failed for: %s, %m\n", cmd);
+		close(fds[0]);
+		close(fds[1]);
+		return pid;
+	}
+
+	if (!pid) {
+		close(1);
+		ret = dup(fds[1]);
+		if (ret < 0) {
+			eprintf("dup failed for: %s, %m\n", cmd);
+			exit(-1);
+		}
+		close(fds[0]);
+		execv(argv[0], argv);
+
+		eprintf("execv failed for: %s, %m\n", cmd);
+		exit(-1);
+	} else {
+		struct timeval tv;
+		fd_set rfds;
+		int ret_sel;
+
+		close(fds[1]);
+		/* 0.1 second is okay, as the initiator will retry anyway */
+		do {
+			FD_ZERO(&rfds);
+			FD_SET(fds[0], &rfds);
+			tv.tv_sec = 0;
+			tv.tv_usec = 100000;
+			ret_sel = select(fds[0]+1, &rfds, NULL, NULL, &tv);
+		} while (ret_sel < 0 && errno == EINTR);
+		if (ret_sel <= 0) { /* error or timeout */
+			eprintf("timeout on redirect callback, terminating "
+				"child pid %d\n", pid);
+			kill(pid, SIGTERM);
+		}
+		do {
+			ret = waitpid(pid, &i, 0);
+		} while (ret < 0 && errno == EINTR);
+		if (ret < 0) {
+			eprintf("waitpid failed for: %s, %m\n", cmd);
+			close(fds[0]);
+			return ret;
+		}
+		if (ret_sel > 0) {
+			ret = read(fds[0], output, op_len);
+			if (ret < 0) {
+				eprintf("failed to get output from: %s\n", cmd);
+				close(fds[0]);
+				return ret;
+			}
+		}
+
+		if (callback)
+			callback(data, WEXITSTATUS(i));
+		close(fds[0]);
+	}
+
+	return 0;
+}
+
+struct tgt_param {
+	int (*parse_func)(char *);
+	char *name;
+};
+
+static struct tgt_param params[64];
+
+int setup_param(char *name, int (*parser)(char *))
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(params); i++)
+		if (!params[i].name)
+			break;
+
+	if (i < ARRAY_SIZE(params)) {
+		params[i].name = name;
+		params[i].parse_func = parser;
+
+		return 0;
+	} else
+		return -1;
+}
+
+int parse_params(char *name, char *p)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(params) && params[i].name; i++) {
+		if (!strcmp(name, params[i].name))
+			return params[i].parse_func(p);
+	}
+
+	fprintf(stderr, "'%s' is an unknown option\n", name);
+
+	return -1;
+}
+
 static void __attribute__((constructor)) target_constructor(void)
 {
 	static int global_target_aids[DEFAULT_NR_ACCOUNT];
diff --git a/usr/tgtd.c b/usr/tgtd.c
index f985510..3ef7220 100644
--- a/usr/tgtd.c
+++ b/usr/tgtd.c
@@ -30,11 +30,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <ctype.h>
 #include <sys/resource.h>
 #include <sys/epoll.h>
 #include <sys/types.h>
-#include <sys/wait.h>
 #include <sys/stat.h>
 
 #include "list.h"
@@ -44,12 +42,10 @@
 #include "util.h"
 
 unsigned long pagesize, pageshift;
+extern int ep_fd;
 
 int system_active = 1;
-static int ep_fd;
 static char program_name[] = "tgtd";
-static LIST_HEAD(tgt_events_list);
-static LIST_HEAD(tgt_sched_events_list);
 
 static struct option const long_options[] = {
 	{"foreground", no_argument, 0, 'f'},
@@ -174,238 +170,6 @@ set_rlimit:
 	return 0;
 }
 
-int tgt_event_add(int fd, int events, event_handler_t handler, void *data)
-{
-	struct epoll_event ev;
-	struct event_data *tev;
-	int err;
-
-	tev = zalloc(sizeof(*tev));
-	if (!tev)
-		return -ENOMEM;
-
-	tev->data = data;
-	tev->handler = handler;
-	tev->fd = fd;
-
-	memset(&ev, 0, sizeof(ev));
-	ev.events = events;
-	ev.data.ptr = tev;
-	err = epoll_ctl(ep_fd, EPOLL_CTL_ADD, fd, &ev);
-	if (err) {
-		eprintf("Cannot add fd, %m\n");
-		free(tev);
-	} else
-		list_add(&tev->e_list, &tgt_events_list);
-
-	return err;
-}
-
-static struct event_data *tgt_event_lookup(int fd)
-{
-	struct event_data *tev;
-
-	list_for_each_entry(tev, &tgt_events_list, e_list) {
-		if (tev->fd == fd)
-			return tev;
-	}
-	return NULL;
-}
-
-void tgt_event_del(int fd)
-{
-	struct event_data *tev;
-	int ret;
-
-	tev = tgt_event_lookup(fd);
-	if (!tev) {
-		eprintf("Cannot find event %d\n", fd);
-		return;
-	}
-
-	ret = epoll_ctl(ep_fd, EPOLL_CTL_DEL, fd, NULL);
-	if (ret < 0)
-		eprintf("fail to remove epoll event, %s\n", strerror(errno));
-
-	list_del(&tev->e_list);
-	free(tev);
-}
-
-int tgt_event_modify(int fd, int events)
-{
-	struct epoll_event ev;
-	struct event_data *tev;
-
-	tev = tgt_event_lookup(fd);
-	if (!tev) {
-		eprintf("Cannot find event %d\n", fd);
-		return -EINVAL;
-	}
-
-	memset(&ev, 0, sizeof(ev));
-	ev.events = events;
-	ev.data.ptr = tev;
-
-	return epoll_ctl(ep_fd, EPOLL_CTL_MOD, fd, &ev);
-}
-
-void tgt_init_sched_event(struct event_data *evt,
-			  sched_event_handler_t sched_handler, void *data)
-{
-	evt->sched_handler = sched_handler;
-	evt->scheduled = 0;
-	evt->data = data;
-	INIT_LIST_HEAD(&evt->e_list);
-}
-
-void tgt_add_sched_event(struct event_data *evt)
-{
-	if (!evt->scheduled) {
-		evt->scheduled = 1;
-		list_add_tail(&evt->e_list, &tgt_sched_events_list);
-	}
-}
-
-void tgt_remove_sched_event(struct event_data *evt)
-{
-	if (evt->scheduled) {
-		evt->scheduled = 0;
-		list_del_init(&evt->e_list);
-	}
-}
-
-/* strcpy, while eating multiple white spaces */
-void str_spacecpy(char **dest, const char *src)
-{
-	const char *s = src;
-	char *d = *dest;
-
-	while (*s) {
-		if (isspace(*s)) {
-			if (!*(s+1))
-				break;
-			if (isspace(*(s+1))) {
-				s++;
-				continue;
-			}
-		}
-		*d++ = *s++;
-	}
-	*d = '\0';
-}
-
-int call_program(const char *cmd, void (*callback)(void *data, int result),
-		void *data, char *output, int op_len, int flags)
-{
-	pid_t pid;
-	int fds[2], ret, i;
-	char *pos, arg[256];
-	char *argv[sizeof(arg) / 2];
-
-	i = 0;
-	pos = arg;
-	str_spacecpy(&pos, cmd);
-	if (strchr(cmd, ' ')) {
-		while (pos != '\0')
-			argv[i++] = strsep(&pos, " ");
-	} else
-		argv[i++] = arg;
-	argv[i] =  NULL;
-
-	ret = pipe(fds);
-	if (ret < 0) {
-		eprintf("pipe create failed for %s, %m\n", cmd);
-		return ret;
-	}
-
-	dprintf("%s, pipe: %d %d\n", cmd, fds[0], fds[1]);
-
-	pid = fork();
-	if (pid < 0) {
-		eprintf("fork failed for: %s, %m\n", cmd);
-		close(fds[0]);
-		close(fds[1]);
-		return pid;
-	}
-
-	if (!pid) {
-		close(1);
-		ret = dup(fds[1]);
-		if (ret < 0) {
-			eprintf("dup failed for: %s, %m\n", cmd);
-			exit(-1);
-		}
-		close(fds[0]);
-		execv(argv[0], argv);
-
-		eprintf("execv failed for: %s, %m\n", cmd);
-		exit(-1);
-	} else {
-		struct timeval tv;
-		fd_set rfds;
-		int ret_sel;
-
-		close(fds[1]);
-		/* 0.1 second is okay, as the initiator will retry anyway */
-		do {
-			FD_ZERO(&rfds);
-			FD_SET(fds[0], &rfds);
-			tv.tv_sec = 0;
-			tv.tv_usec = 100000;
-			ret_sel = select(fds[0]+1, &rfds, NULL, NULL, &tv);
-		} while (ret_sel < 0 && errno == EINTR);
-		if (ret_sel <= 0) { /* error or timeout */
-			eprintf("timeout on redirect callback, terminating "
-				"child pid %d\n", pid);
-			kill(pid, SIGTERM);
-		}
-		do {
-			ret = waitpid(pid, &i, 0);
-		} while (ret < 0 && errno == EINTR);
-		if (ret < 0) {
-			eprintf("waitpid failed for: %s, %m\n", cmd);
-			close(fds[0]);
-			return ret;
-		}
-		if (ret_sel > 0) {
-			ret = read(fds[0], output, op_len);
-			if (ret < 0) {
-				eprintf("failed to get output from: %s\n", cmd);
-				close(fds[0]);
-				return ret;
-			}
-		}
-
-		if (callback)
-			callback(data, WEXITSTATUS(i));
-		close(fds[0]);
-	}
-
-	return 0;
-}
-
-static int tgt_exec_scheduled(void)
-{
-	struct list_head *last_sched;
-	struct event_data *tev, *tevn;
-	int work_remains = 0;
-
-	if (!list_empty(&tgt_sched_events_list)) {
-		/* execute only work scheduled till now */
-		last_sched = tgt_sched_events_list.prev;
-		list_for_each_entry_safe(tev, tevn, &tgt_sched_events_list,
-					 e_list) {
-			tgt_remove_sched_event(tev);
-			tev->sched_handler(tev);
-			if (&tev->e_list == last_sched)
-				break;
-		}
-		if (!list_empty(&tgt_sched_events_list))
-			work_remains = 1;
-	}
-	return work_remains;
-}
-
 static void event_loop(void)
 {
 	int nevent, i, sched_remains, timeout;
@@ -471,44 +235,6 @@ static void lld_exit(void)
 	}
 }
 
-struct tgt_param {
-	int (*parse_func)(char *);
-	char *name;
-};
-
-static struct tgt_param params[64];
-
-int setup_param(char *name, int (*parser)(char *))
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(params); i++)
-		if (!params[i].name)
-			break;
-
-	if (i < ARRAY_SIZE(params)) {
-		params[i].name = name;
-		params[i].parse_func = parser;
-
-		return 0;
-	} else
-		return -1;
-}
-
-static int parse_params(char *name, char *p)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(params) && params[i].name; i++) {
-		if (!strcmp(name, params[i].name))
-			return params[i].parse_func(p);
-	}
-
-	fprintf(stderr, "'%s' is an unknown option\n", name);
-
-	return -1;
-}
-
 int main(int argc, char **argv)
 {
 	struct sigaction sa_old;
diff --git a/usr/tgtd.h b/usr/tgtd.h
index 484e6e9..0d4c6ae 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -295,6 +295,7 @@ extern void tgt_event_del(int fd);
 
 extern void tgt_add_sched_event(struct event_data *evt);
 extern void tgt_remove_sched_event(struct event_data *evt);
+extern int tgt_exec_scheduled(void);
 
 extern int tgt_event_modify(int fd, int events);
 extern int target_cmd_queue(int tid, struct scsi_cmd *cmd);
@@ -373,6 +374,7 @@ extern struct backingstore_template *get_backingstore_template(const char *name)
 extern int lld_init_one(int lld_index);
 
 extern int setup_param(char *name, int (*parser)(char *));
+extern int parse_params(char *name, char *p);
 
 extern int bs_init(void);
 
-- 
1.7.3.1

--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list