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

Dan Mick dan.mick at inktank.com
Sat Aug 10 07:47:38 CEST 2013


This would be super-cool, as it would allow building and distributing 
rbd support without requiring users of the package to install Ceph just 
to use stgt without Ceph.

Some initial comments below:

On 08/09/2013 04:02 PM, Ronnie Sahlberg wrote:
> 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 +-

No 2-line change to bs_rbd.c?

>   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

bs_rbd.so, not rdb

It may seem weird to compile, but it *should* be enough to add package 
'librbd1' (which will also pull in librados2) to allow the build with 
CEPH_RBD enabled.  If Tomo agrees this patch is worthwhile, I'd sure 
like to see it go in with all bsdrvs supported.

>   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);
>
>
--
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