[multipathd] merge a more versatile CLI parser
authorroot <root@xa-s05.(none)>
Wed, 29 Jun 2005 14:18:30 +0000 (16:18 +0200)
committerroot <root@xa-s05.(none)>
Wed, 29 Jun 2005 14:18:30 +0000 (16:18 +0200)
Synthax moved to :

 list paths
 list maps
 add path $path
 remove|del path $path
 add map $map
 remove|del map $map
 switch|switchgroup map $map group $group

multipathd/Makefile
multipathd/cli.c [new file with mode: 0644]
multipathd/cli.h [new file with mode: 0644]
multipathd/cli_handlers.c [new file with mode: 0644]
multipathd/cli_handlers.h [new file with mode: 0644]
multipathd/main.c
multipathd/main.h

index cca8b0f065a077feaa6e66977ff4e2426ceced95..50eddd3476de0aef3b02901ffc94072a3af3e5f7 100644 (file)
@@ -26,7 +26,7 @@ LDFLAGS = -lpthread -ldevmapper -lsysfs -lreadline
 #
 # object files
 #
-OBJS = main.o copy.o log.o log_pthread.o pidfile.o uxlsnr.o uxclnt.o \
+OBJS = main.o copy.o log.o log_pthread.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o \
        $(MULTIPATHLIB)-glibc.a $(CHECKERSLIB)-glibc.a \
 
 
diff --git a/multipathd/cli.c b/multipathd/cli.c
new file mode 100644 (file)
index 0000000..9e08ae0
--- /dev/null
@@ -0,0 +1,321 @@
+#include <memory.h>
+#include <vector.h>
+#include <util.h>
+
+#include "cli.h"
+
+static struct key *
+alloc_key (void)
+{
+       return MALLOC(sizeof(struct key));
+}
+
+static struct handler *
+alloc_handler (void)
+{
+       return MALLOC(sizeof(struct handler));
+}
+
+static int
+add_key (vector vec, char * str, int code, int has_param)
+{
+       struct key * kw;
+
+       kw = alloc_key();
+
+       if (!kw)
+               return 1;
+
+       kw->code = code;
+       kw->has_param = has_param;
+       kw->str = strdup(str);
+
+       if (!kw->str)
+               goto out;
+
+       if (!vector_alloc_slot(vec))
+               goto out1;
+
+       vector_set_slot(vec, kw);
+
+       return 0;
+
+out1:
+       FREE(kw->str);
+out:
+       FREE(kw);
+       return 1;
+}
+
+int
+add_handler (int fp, char * (*fn)(void *, void *))
+{
+       struct handler * h;
+
+       h = alloc_handler();
+
+       if (!h)
+               return 1;
+
+       if (!vector_alloc_slot(handlers)) {
+               FREE(h);
+               return 1;
+       }
+
+       vector_set_slot(handlers, h);
+       h->fingerprint = fp;
+       h->fn = fn;
+
+       return 0;
+}
+
+static void
+free_key (struct key * kw)
+{
+               FREE(kw->str);
+
+               if (kw->param)
+                       FREE(kw->param);
+
+               FREE(kw);
+}
+
+static void
+free_keys (vector vec)
+{
+       int i;
+       struct key * kw;
+
+       vector_foreach_slot(vec, kw, i)
+               free_key(kw);
+
+       FREE(vec);
+}
+
+int
+load_keys (void)
+{
+       int r = 0;
+       keys = vector_alloc();
+
+       if (!keys)
+               return 1;
+
+       r += add_key(keys, "list", LIST, 0);
+       r += add_key(keys, "show", LIST, 0);
+       r += add_key(keys, "add", ADD, 0);
+       r += add_key(keys, "remove", DEL, 0);
+       r += add_key(keys, "del", DEL, 0);
+       r += add_key(keys, "switch", SWITCH, 0);
+       r += add_key(keys, "switchgroup", SWITCH, 0);
+       r += add_key(keys, "paths", PATHS, 0);
+       r += add_key(keys, "maps", MAPS, 0);
+       r += add_key(keys, "path", PATH, 1);
+       r += add_key(keys, "map", MAP, 1);
+       r += add_key(keys, "group", GROUP, 1);
+
+       if (r) {
+               free_keys(keys);
+               return 1;
+       }
+
+       return 0;
+}
+
+static struct key *
+find_key (char * str)
+{
+       int i;
+       struct key * kw = NULL;
+
+       vector_foreach_slot (keys, kw, i)
+               if (!strncmp(kw->str, str, strlen(kw->str)))
+                               return kw;
+
+       return NULL;
+}
+               
+static struct handler *
+find_handler (int fp)
+{
+       int i;
+       struct handler *h;
+
+       vector_foreach_slot (handlers, h, i)
+               if (h->fingerprint == fp)
+                       return h;
+
+       return NULL;
+}
+
+static vector
+get_cmdvec (char * cmd)
+{
+       int fwd = 1;
+       char * p = cmd;
+       char * buff;
+       struct key * kw = NULL;
+       struct key * cmdkw = NULL;
+       vector cmdvec;
+
+       cmdvec = vector_alloc();
+
+       if (!cmdvec)
+               return NULL;
+
+       while (fwd) {
+               fwd = get_word(p, &buff);
+
+               if (!buff)
+                       break;
+
+               p += fwd;
+               kw = find_key(buff);
+               FREE(buff);
+
+               if (!kw)
+                       goto out; /* synthax error */
+
+               cmdkw = alloc_key();
+
+               if (!cmdkw)
+                       goto out;
+
+               if (!vector_alloc_slot(cmdvec)) {
+                       FREE(cmdkw);
+                       goto out;
+               }
+
+               vector_set_slot(cmdvec, cmdkw);
+               cmdkw->code = kw->code;
+               cmdkw->has_param = kw->has_param;
+               
+               if (kw->has_param) {
+                       if (*p == '\0')
+                               goto out;
+
+                       fwd = get_word(p, &buff);
+
+                       if (!buff)
+                               goto out;
+
+                       p += fwd;
+                       cmdkw->param = buff;
+               }
+       }
+
+       return cmdvec;
+
+out:
+       free_keys(cmdvec);
+       return NULL;
+}
+
+static int 
+fingerprint(vector vec)
+{
+       int i;
+       int fp = 0;
+       struct key * kw;
+
+       vector_foreach_slot(vec, kw, i)
+               fp += kw->code;
+
+       return fp;
+}
+
+int
+alloc_handlers (void)
+{
+       handlers = vector_alloc();
+
+       if (!handlers)
+               return 1;
+
+       return 0;
+}
+
+static int
+genhelp_sprint_aliases (char * reply, vector keys, struct key * refkw)
+{
+       int i, fwd = 0;
+       struct key * kw;
+
+       vector_foreach_slot (keys, kw, i)
+               if (kw->code == refkw->code && kw != refkw)
+                       fwd += sprintf(reply, "|%s", kw->str);
+
+       return fwd;
+}
+
+static char *
+genhelp_handler (void)
+{
+       int i, j;
+       int fp;
+       struct handler * h;
+       struct key * kw;
+       char * reply;
+       char * p;
+
+       reply = MALLOC(MAX_REPLY_LEN);
+
+       if (!reply)
+               return NULL;
+
+       p = reply;
+
+       vector_foreach_slot (handlers, h, i) {
+               fp = h->fingerprint;
+               vector_foreach_slot (keys, kw, j) {
+                       if ((kw->code & fp)) {
+                               fp -= kw->code;
+                               p += sprintf(p, " %s", kw->str);
+                               p += genhelp_sprint_aliases(p, keys, kw);
+
+                               if (kw->has_param)
+                                       p += sprintf(p, " $%s", kw->str);
+                       }
+               }
+               p += sprintf(p, "\n");
+       }
+
+       return reply;
+}
+
+char *
+parse_cmd (char * cmd, void * data)
+{
+       char * reply;
+       struct handler * h;
+       vector cmdvec = get_cmdvec(cmd);
+
+       if (!cmdvec)
+               return genhelp_handler();
+
+       h = find_handler(fingerprint(cmdvec));
+
+       if (!h)
+               return genhelp_handler();
+
+       /*
+        * execute handler
+        */
+       reply = h->fn(cmdvec, data);
+       free_keys(cmdvec);
+
+       return reply;
+}
+
+char *
+get_keyparam (vector v, int code)
+{
+       struct key * kw;
+       int i;
+
+       vector_foreach_slot(v, kw, i)
+               if (kw->code == code)
+                       return kw->param;
+
+       return NULL;
+}
diff --git a/multipathd/cli.h b/multipathd/cli.h
new file mode 100644 (file)
index 0000000..4b39ada
--- /dev/null
@@ -0,0 +1,32 @@
+#define LIST   1
+#define ADD    (1 << 1)
+#define DEL    (1 << 2)
+#define SWITCH (1 << 3)
+#define PATHS  (1 << 4)
+#define MAPS   (1 << 5)
+#define PATH   (1 << 6)
+#define MAP    (1 << 7)
+#define GROUP  (1 << 8)
+
+#define MAX_REPLY_LEN 1000
+
+struct key {
+       char * str;
+       char * param;
+       int code;
+       int has_param;
+};
+
+struct handler {
+       int fingerprint;
+       char * (*fn)(void *, void *);
+};
+
+vector keys;
+vector handlers;
+
+int alloc_handlers (void);
+int add_handler (int fp, char * (*fn)(void *, void *));
+char * parse_cmd (char * cmd, void *);
+int load_keys (void);
+char * get_keyparam (vector v, int code);
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
new file mode 100644 (file)
index 0000000..d740a47
--- /dev/null
@@ -0,0 +1,82 @@
+#include <memory.h>
+#include <vector.h>
+#include <structs.h>
+#include <devmapper.h>
+
+#include "main.h"
+#include "cli.h"
+
+char *
+list_paths (void * v, void * data)
+{
+       struct paths * allpaths = (struct paths *)data;
+
+       return show_paths(allpaths);
+}
+
+char *
+list_maps (void * v, void * data)
+{
+       struct paths * allpaths = (struct paths *)data;
+
+       return show_maps(allpaths);
+}
+
+char *
+add_path (void * v, void * data)
+{
+       struct paths * allpaths = (struct paths *)data;
+       char * param = get_keyparam(v, PATH);
+
+       if (uev_add_path(param, allpaths))
+               return NULL;
+
+       return strdup("ok");
+}
+
+char *
+del_path (void * v, void * data)
+{
+       struct paths * allpaths = (struct paths *)data;
+       char * param = get_keyparam(v, PATH);
+
+       if (uev_remove_path(param, allpaths))
+               return NULL;
+
+       return strdup("ok");
+}
+
+char *
+add_map (void * v, void * data)
+{
+       struct paths * allpaths = (struct paths *)data;
+       char * param = get_keyparam(v, MAP);
+
+       if (uev_add_map(param, allpaths))
+               return NULL;
+
+       return strdup("ok");
+}
+
+char *
+del_map (void * v, void * data)
+{
+       struct paths * allpaths = (struct paths *)data;
+       char * param = get_keyparam(v, MAP);
+
+       if (uev_remove_map(param, allpaths))
+               return NULL;
+
+       return strdup("ok");
+}
+
+char *
+switch_group(void * v, void * data)
+{
+       char * mapname = get_keyparam(v, MAP);
+       int groupnum = atoi(get_keyparam(v, GROUP));
+       
+       dm_switchgroup(mapname, groupnum);
+
+       return strdup("ok");
+}
diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h
new file mode 100644 (file)
index 0000000..659441a
--- /dev/null
@@ -0,0 +1,7 @@
+char * list_paths (void * v, void * data);
+char * list_maps (void * v, void * data);
+char * add_path (void * v, void * data);
+char * del_path (void * v, void * data);
+char * add_map (void * v, void * data);
+char * del_map (void * v, void * data);
+char * switch_group (void * v, void * data);
index 7b3d1c9ba660f797cee3ef06951faa48f9baf83e..e1c0246b8fd0f5d2ca5299c10b84559041e549dc 100644 (file)
 #include "pidfile.h"
 #include "uxlsnr.h"
 #include "uxclnt.h"
+#include "cli.h"
+#include "cli_handlers.h"
 
 #define FILE_NAME_SIZE 256
 #define CMDSIZE 160
-#define MAX_REPLY_LEN 1000
 
 #define CALLOUT_DIR "/var/cache/multipathd"
 
 /*
  * structs
  */
-struct paths {
-       pthread_mutex_t *lock;
-       vector pathvec;
-       vector mpvec;
-};
-
 struct event_thread {
        struct dm_task *dmt;
        pthread_t thread;
@@ -210,37 +205,6 @@ out:
        return 1;
 }
 
-static int
-switch_to_pathgroup (char * str)
-{
-       char * mapname;
-       char * buff = NULL;
-       char * p = NULL;
-       int r = 0;
-       int pg;
-
-       p = str;
-       p += get_word(p, &mapname);
-
-       if (!mapname)
-               return 1;
-
-       p += get_word(p, &buff);
-
-       if (!buff)
-               goto out;
-
-       if (sscanf(buff, "%d", &pg) != 1)
-               goto out1;
-
-       r = !dm_switchgroup(mapname, pg);
-out1:
-       FREE(buff);
-out:
-       FREE(mapname);
-       return r;
-}
-       
 static void
 switch_pathgroup (struct multipath * mpp)
 {
@@ -354,6 +318,7 @@ waiteventloop (struct event_thread * waiter)
        pthread_testcancel();
        dm_task_run(waiter->dmt);
        pthread_testcancel();
+       dm_task_destroy(waiter->dmt);
 
        waiter->event_nr++;
 
@@ -471,8 +436,13 @@ remove_map (struct multipath * mpp, struct paths * allpaths)
        /*
         * stop the DM event waiter thread
         */
-       if (stop_waiter_thread(mpp, allpaths))
+       if (stop_waiter_thread(mpp, allpaths)) {
                condlog(0, "%s: error canceling waiter thread", mpp->alias);
+               /*
+                * warrior mode
+                */
+               free_waiter(mpp->waiter);
+       }
 
        /*
         * clear references to this map
@@ -492,7 +462,7 @@ remove_map (struct multipath * mpp, struct paths * allpaths)
        mpp = NULL;
 }
 
-static int
+int
 uev_add_map (char * devname, struct paths * allpaths)
 {
        int major, minor;
@@ -560,7 +530,7 @@ out:
        return 1;
 }
 
-static int
+int
 uev_remove_map (char * devname, struct paths * allpaths)
 {
        int minor;
@@ -583,7 +553,7 @@ uev_remove_map (char * devname, struct paths * allpaths)
        return 0;
 }
 
-static int
+int
 uev_add_path (char * devname, struct paths * allpaths)
 {
        struct path * pp;
@@ -614,7 +584,7 @@ uev_add_path (char * devname, struct paths * allpaths)
        return 0;
 }
 
-static int
+int
 uev_remove_path (char * devname, struct paths * allpaths)
 {
        int i;
@@ -634,7 +604,7 @@ uev_remove_path (char * devname, struct paths * allpaths)
        return 0;
 }
 
-static char *
+char *
 show_paths (struct paths * allpaths)
 {
        int i, j, k;
@@ -678,7 +648,7 @@ show_paths (struct paths * allpaths)
        return reply;
 }
 
-static char *
+char *
 show_maps (struct paths * allpaths)
 {
        int i, j, k;
@@ -723,7 +693,6 @@ show_maps (struct paths * allpaths)
 char *
 uxsock_trigger (char * str, void * trigger_data)
 {
-       int r;
        struct paths * allpaths;
        char * reply = NULL;
 
@@ -731,47 +700,13 @@ uxsock_trigger (char * str, void * trigger_data)
 
        lock(allpaths->lock);
 
-       if (strlen(str) < 2)
-               r = 1;
-       else if (*str == 'l' && *(str + 1) == 'p')
-               reply = show_paths(allpaths);
-
-       else if (*str == 'l' && *(str + 1) == 'm')
-               reply = show_maps(allpaths);
-
-       else if (strlen(str) < 4)
-               r = 1;
+       reply = parse_cmd(str, allpaths);
 
-       else if (*str == 'r' && *(str + 1) == 'p')
-               r = uev_remove_path(str + 3, allpaths);
-
-       else if (*str == 'a' && *(str + 1) == 'p')
-               r = uev_add_path(str + 3, allpaths);
-
-       else if (*str == 'r' && *(str + 1) == 'm') {
-               if (!strncmp(str +3, "dm-", 3)) {
-                       r = uev_remove_map(str + 3, allpaths);
-               }
-       }
-
-       else if (*str == 'a' && *(str + 1) == 'm') {
-               if (!strncmp(str +3, "dm-", 3)) {
-                       r = uev_add_map(str + 3, allpaths);
-               }
-       }
-
-       else if (*str == 's' && *(str + 1) == 'g')
-               r = switch_to_pathgroup(str + 3);
+       if (!reply)
+               reply = strdup("fail\n");
 
-       else
-               r = 1;
-
-       if (!reply) {
-               if (r)
-                       reply = strdup("fail\n");
-               else
-                       reply = strdup("ok\n");
-       }
+       else if (strlen(reply) == 0)
+               reply = strdup("ok\n");
 
        unlock(allpaths->lock);
 
@@ -840,6 +775,20 @@ ueventloop (void * ap)
 static void *
 uxlsnrloop (void * ap)
 {
+       if (load_keys())
+               return NULL;
+       
+       if (alloc_handlers())
+               return NULL;
+
+       add_handler(LIST+PATHS, list_paths);
+       add_handler(LIST+MAPS, list_maps);
+       add_handler(ADD+PATH, add_path);
+       add_handler(DEL+PATH, del_path);
+       add_handler(ADD+MAP, add_map);
+       add_handler(DEL+MAP, del_map);
+       add_handler(SWITCH+MAP+GROUP, switch_group);
+
        uxsock_listen(&uxsock_trigger, ap);
 
        return NULL;
@@ -1347,10 +1296,7 @@ child (void * param)
                conf->binvec = vector_alloc();
                push_callout("/sbin/scsi_id");
        }
-       if (!conf->multipath) {
-               conf->multipath = MULTIPATH;
-               push_callout(conf->multipath);
-       }
+
        if (!conf->checkint) {
                conf->checkint = CHECKINT;
                conf->max_checkint = MAX_CHECKINT;
index 748be61116bdc0367231d7e28a47b1a7d374c9ef..6a56bdda348503fb0a9e1a28188decdf438bae32 100644 (file)
@@ -1,10 +1,22 @@
-#ifndef HWTABLE_H
-#define HWTABLE_H
+#ifndef MAIN_H
+#define MAIN_H
 
 #define DAEMON 1
 #define CHECKINT 5
 #define MAPGCINT 5
 #define MAX_CHECKINT CHECKINT << 2
-#define MULTIPATH "/sbin/multipath -v0"
 
-#endif
+struct paths {
+       pthread_mutex_t *lock;
+       vector pathvec;
+       vector mpvec;
+};
+
+char * show_paths (struct paths *);
+char * show_maps (struct paths *);
+int uev_add_path (char *, struct paths *);
+int uev_remove_path (char *, struct paths *);
+int uev_add_map (char *, struct paths *);
+int uev_remove_map (char *, struct paths *);
+
+#endif /* MAIN_H */