Whamcloud - gitweb
b=17997
authorzhanghc <zhanghc>
Mon, 16 Mar 2009 04:20:39 +0000 (04:20 +0000)
committerzhanghc <zhanghc>
Mon, 16 Mar 2009 04:20:39 +0000 (04:20 +0000)
add a new implementation of lshowmount

i=adilger
i=hongchao.zhang

lustre/utils/Makefile.am
lustre/utils/lshowmount.c [new file with mode: 0644]
lustre/utils/nidlist.c [new file with mode: 0644]
lustre/utils/nidlist.h [new file with mode: 0644]

index 51b9803..6b4f57c 100644 (file)
@@ -21,7 +21,7 @@ EXTRA_PROGRAMS = wirecheck
 rootsbin_PROGRAMS = mount.lustre
 sbin_PROGRAMS = mkfs.lustre tunefs.lustre lctl wiretest \
        l_getidentity llverfs llverdev \
-       llog_reader lr_reader
+       llog_reader lr_reader lshowmount
 if LIBPTHREAD
 sbin_PROGRAMS += loadgen
 endif
@@ -44,6 +44,8 @@ loadgen_SOURCES = loadgen.c lustre_cfg.c obd.c
 loadgen_LDADD := $(LIBREADLINE) liblustreapi.a $(LIBPTLCTL) $(PTHREAD_LIBS)
 loadgen_DEPENDENCIES := $(LIBPTLCTL)
 
+lshowmount_SOURCES = lshowmount.c nidlist.c nidlist.h
+
 if EXT2FS_DEVEL
 EXT2FSLIB = -lext2fs
 E2PLIB = -le2p
diff --git a/lustre/utils/lshowmount.c b/lustre/utils/lshowmount.c
new file mode 100644 (file)
index 0000000..920bebb
--- /dev/null
@@ -0,0 +1,225 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * 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 version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/utils/lshowmount.h
+ *
+ * Author: Herb Wartens <wartens2@llnl.gov>
+ * Author: Jim Garlick <garlick@llnl.gov>
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+#include <libgen.h>
+
+#include "nidlist.h"
+
+#define PROC_DIRS {                     \
+        "/proc/fs/lustre/mgs",          \
+        "/proc/fs/lustre/mdt",          \
+        "/proc/fs/lustre/obdfilter",    \
+        NULL,                           \
+}
+#define PROC_EXPORTS_TMPL       "%s/%s/exports"
+#define PROC_UUID_TMPL          "%s/%s/uuid"
+
+static void print_nids(NIDList nidlist, int lookup, int enumerate, int indent);
+static int lshowmount(int lookup, int enumerate, int verbose);
+static void read_exports(char *exports, NIDList nidlist);
+
+char *prog;
+
+#define OPTIONS "ehlv"
+static struct option long_options[] = {
+        {"enumerate", no_argument, 0, 'e'},
+        {"help",      no_argument, 0, 'h'},
+        {"lookup",    no_argument, 0, 'l'},
+        {"verbose",   no_argument, 0, 'v'},
+        {0, 0, 0, 0},
+};
+
+static void usage(void)
+{
+        fprintf(stderr, "usage: %s [-e] [-h] [-l] [-v]\n", prog);
+        exit(1);
+}
+
+int main(int argc, char **argv)
+{
+        int opt, optidx = 0;
+        int lopt = 0;
+        int vopt = 0;
+        int eopt = 0;
+
+        prog = basename(argv[0]);
+
+        while ((opt = getopt_long(argc, argv, OPTIONS, long_options, &optidx)) != -1) {
+                switch (opt) {
+                        case 'e':       /* --enumerate */
+                                eopt = 1;
+                                break;
+                        case 'l':       /* --lookup */
+                                lopt = 1;
+                                break;
+                        case 'v':       /* --verbose */
+                                vopt = 1;
+                                break;
+                        case 'h':       /* --help */
+                        default:
+                                usage();
+                }
+        }
+
+        if (lshowmount(lopt, eopt, vopt) == 0) {
+                fprintf(stderr, "%s: lustre server modules not loaded\n", prog);
+                exit(1);
+        }
+        exit(0);
+}
+
+static void print_nids(NIDList nidlist, int lookup, int enumerate, int indent)
+{
+        char *s, *sep = "\n", *pfx = "";
+
+        if (lookup)
+                nl_lookup_ip(nidlist);
+        nl_sort(nidlist);
+        nl_uniq(nidlist);
+        if (nl_count(nidlist) > 0) {
+                if (indent) {
+                        sep = "\n    ";
+                        pfx = "    ";
+                }
+                if (enumerate)
+                        s = nl_string(nidlist, sep);
+                else
+                        s = nl_xstring(nidlist, sep);
+                printf("%s%s\n", pfx, s);
+                free(s);
+        }
+}
+
+static int lshowmount(int lookup, int enumerate, int verbose)
+{
+        char *dirs[] = PROC_DIRS;
+        char exp[PATH_MAX + 1];
+        NIDList nidlist = NULL;
+        DIR *topdirp;
+        struct dirent *dp;
+        int i;
+        int opens = 0;
+
+        if (!verbose)
+                nidlist = nl_create();
+        for (i = 0; dirs[i] != NULL; i++) {
+                if ((topdirp = opendir(dirs[i])) == NULL)
+                        continue;
+                while ((dp = readdir(topdirp))) {
+                        if (dp->d_type != DT_DIR)
+                                continue;
+                        if (!strcmp(dp->d_name, "."))
+                                continue;
+                        if (!strcmp(dp->d_name, ".."))
+                                continue;
+                        sprintf(exp, PROC_EXPORTS_TMPL, dirs[i], dp->d_name);
+                        if (verbose) {
+                                nidlist = nl_create();
+                                read_exports(exp, nidlist);
+                                printf("%s:\n", dp->d_name);
+                                print_nids(nidlist, lookup, enumerate, 1);
+                                nl_destroy(nidlist);
+                        } else
+                                read_exports(exp, nidlist);
+                }
+                closedir(topdirp);
+                opens++;
+        }
+        if (!verbose) {
+                print_nids(nidlist, lookup, enumerate, 0);
+                nl_destroy(nidlist);
+        }
+        return opens;
+}
+
+static int empty_proc_file(char *path)
+{
+        int empty = 0;
+        char buf[36];
+        int fd;
+
+        if ((fd = open(path, O_RDONLY)) < 0 || read(fd, buf, sizeof(buf)) <= 0)
+                empty = 1;
+        if (fd >= 0)
+                close(fd);
+        return empty;
+}
+
+static void read_exports(char *exports, NIDList nidlist)
+{
+        DIR *dirp;
+        struct dirent *dp;
+        char path[PATH_MAX + 1];
+
+        if ((dirp = opendir(exports))) {
+                while ((dp = readdir(dirp))) {
+                        if (dp->d_type != DT_DIR)
+                                continue;
+                        if (!strcmp(dp->d_name, "."))
+                                continue;
+                        if (!strcmp(dp->d_name, ".."))
+                                continue;
+                        if (strchr(dp->d_name, '@') == NULL)
+                                continue;
+                        sprintf(path, PROC_UUID_TMPL, exports, dp->d_name);
+                        if (empty_proc_file(path))
+                                continue;
+
+                        nl_add(nidlist, dp->d_name);
+                }
+                closedir(dirp);
+        }
+}
diff --git a/lustre/utils/nidlist.c b/lustre/utils/nidlist.c
new file mode 100644 (file)
index 0000000..fb0cbec
--- /dev/null
@@ -0,0 +1,334 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * 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 version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/utils/nidlist.c
+ *
+ * Author: Jim Garlick <garlick@llnl.gov>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include "nidlist.h"
+
+struct nl_struct {
+       char **nids;
+       int len;
+       int count;
+};
+#define NL_CHUNK       64
+
+extern char *prog;
+
+static void nl_oom(void)
+{
+       fprintf(stderr, "%s: out of memory\n", prog);
+       exit(1);
+}
+
+NIDList nl_create(void)
+{
+       struct nl_struct *nl;
+
+       if (!(nl = malloc(sizeof(struct nl_struct))))
+               nl_oom();
+       nl->len = NL_CHUNK;
+       if (!(nl->nids = malloc(nl->len * sizeof(char *))))
+               nl_oom();
+       nl->count = 0;
+
+       return nl;
+}
+
+void nl_destroy(NIDList nl)
+{
+       int i;
+
+       for (i = 0; i < nl->count; i++)
+               free(nl->nids[i]);
+       free(nl->nids);
+       free(nl);
+}
+
+static void nl_grow(NIDList nl, int n)
+{
+       nl->len += n;
+       if (!(nl->nids = realloc(nl->nids, nl->len * sizeof(char *))))
+               nl_oom();
+}
+
+void nl_add(NIDList nl, char *nid)
+{
+       char *cp;
+
+       if (!(cp = strdup(nid)))
+               nl_oom();
+       if (nl->count == nl->len)
+               nl_grow(nl, NL_CHUNK);
+       nl->nids[nl->count++] = cp;
+}
+
+int nl_count(NIDList nl)
+{
+        return nl->count;
+}
+
+static char *nl_nid_addr(char *nid)
+{
+       char *addr, *p;
+
+       if (!(addr = strdup(nid)))
+               nl_oom();
+       if ((p = strchr(addr, '@')))
+               *p = '\0';
+
+       return addr;
+}
+
+static int nl_nid_parse_addr(char *addr)
+{
+       int o;
+
+       for (o = strlen(addr); o > 0; o--)
+                if (!isdigit(addr[o - 1]))
+                       break;
+
+       return o;
+}
+
+static int nl_cmp_addr(char *nid1, char *nid2, int *cflagp)
+{
+       char *p1 = nl_nid_addr(nid1);
+       char *p2 = nl_nid_addr(nid2);
+       int res, o1, o2, cflag = 0;
+
+       o1 = nl_nid_parse_addr(p1);
+       o2 = nl_nid_parse_addr(p2);
+
+       if (o1 == o2 && (res = strncmp(p1, p2, o1)) == 0) {
+               res = strtoul(&p1[o1], NULL, 10) - strtoul(&p2[o2], NULL, 10);
+                if (cflagp && strlen(&p1[o1]) > 0 && strlen(&p2[o2]) > 0)
+                        cflag = 1;
+       } else
+                res = strcmp(p1, p2);
+       free(p1);
+       free(p2);
+       if (cflagp)
+               *cflagp = cflag;
+       return res;
+}
+
+static int nl_cmp_lnet(char *nid1, char *nid2)
+{
+       char *s1 = strchr(nid1, '@');
+       char *s2 = strchr(nid2, '@');
+
+       return strcmp(s1 ? s1 + 1 : "", s2 ? s2 + 1 : "");
+}
+
+static int nl_cmp(const void *p1, const void *p2)
+{
+       int res;
+
+       if ((res = nl_cmp_lnet(*(char **)p1, *(char **)p2)) == 0)
+               res = nl_cmp_addr(*(char **)p1, *(char **)p2, NULL);
+       return res;
+}
+
+void nl_sort(NIDList nl)
+{
+       qsort(nl->nids, nl->count, sizeof(char *), nl_cmp);
+}
+
+void nl_uniq(NIDList nl)
+{
+       int i, j;
+
+       for (i = 1; i < nl->count; i++) {
+               if (!strcmp(nl->nids[i], nl->nids[i - 1])) {
+                       free(nl->nids[i]);
+                       for (j = i; j < nl->count - 1; j++)
+                               nl->nids[j] = nl->nids[j + 1];
+                       nl->count--;
+                       i--;
+               }
+       }
+}
+
+static char *nl_nid_lookup_ipaddr(char *nid)
+{
+        struct addrinfo *ai, *aip;
+        char name[NI_MAXHOST] = "";
+        char *p, *addr, *lnet = NULL, *res = NULL;
+        int len, x;
+
+        addr = nl_nid_addr(nid);
+        if (sscanf(addr, "%d.%d.%d.%d", &x, &x, &x, &x) == 4) {
+                if ((p = strchr(nid, '@')))
+                        lnet = p + 1;
+                if (getaddrinfo(addr, NULL, NULL, &ai) == 0) {
+                        for (aip = ai; aip != NULL; aip = aip->ai_next) {
+                                if (getnameinfo(aip->ai_addr, aip->ai_addrlen,
+                                    name, sizeof(name), NULL, 0,
+                                    NI_NAMEREQD | NI_NOFQDN) == 0) {
+                                        if ((p = strchr(name, '.')))
+                                                *p = '\0';
+                                        len = strlen(name) + strlen(lnet) + 2;
+                                        if (!(res = malloc(len)))
+                                                nl_oom();
+                                        snprintf(res, len, "%s@%s", name, lnet);
+                                        break;
+                                }
+                        }
+                        freeaddrinfo(ai);
+                }
+        }
+        free(addr);
+
+        return res;
+}
+
+void nl_lookup_ip(NIDList nl)
+{
+       int i;
+        char *new;
+
+       for (i = 0; i < nl->count; i++) {
+                if ((new = nl_nid_lookup_ipaddr(nl->nids[i]))) {
+                        free(nl->nids[i]);
+                        nl->nids[i] = new;
+                }
+        }
+}
+
+char *nl_string(NIDList nl, char *sep)
+{
+       int seplen = strlen(sep);
+       int i, len = 1;
+       char *s;
+
+       for (i = 0; i < nl->count; i++)
+               len += strlen(nl->nids[i]) + seplen;
+       if (!(s = malloc(len)))
+               nl_oom();
+       s[0] = '\0';
+       for (i = 0; i < nl->count; i++) {
+               if (i > 0)
+                       strcat(s, sep);
+               strcat(s, nl->nids[i]);
+       }
+       return s;
+}
+
+static void nl_strxcat(char *s, char **nids, int len)
+{
+       int i, o, lastn = 0;
+       char *base, *p, *lnet = NULL, *savedn = NULL;
+
+       if ((p = strchr(nids[0], '@')))
+               lnet = p + 1;
+        base = nl_nid_addr(nids[0]);
+        o = nl_nid_parse_addr(base);
+       base[o] = '\0';
+       for (i = 0; i < len; i++) {
+               char *addr = nl_nid_addr(nids[i]);
+               int n = strtoul(&addr[o], NULL, 10);
+
+               if (i == 0)
+                       sprintf(s + strlen(s), "%s[%s", base, &addr[o]);
+               else if (i < len) {
+                       if (n == lastn + 1) {
+                               if (savedn)
+                                       free(savedn);
+                               if (!(savedn = strdup(&addr[o])))
+                                       nl_oom();
+                       } else {
+                               if (savedn) {
+                                       sprintf(s + strlen(s), "-%s", savedn);
+                                       free(savedn);
+                                       savedn = NULL;
+                               }
+                               sprintf(s + strlen(s), ",%s", &addr[o]);
+                       }
+               }
+               if (i == len - 1) {
+                       if (savedn) {
+                               sprintf(s + strlen(s), "-%s", savedn);
+                               free(savedn);
+                       }
+                       strcat(s, "]");
+                       if (lnet)
+                               sprintf(s + strlen(s), "@%s", lnet);
+               }
+               free(addr);
+               lastn = n;
+       }
+       free(base);
+}
+
+char *nl_xstring(NIDList nl, char *sep)
+{
+       int seplen = strlen(sep);
+       int cflag, i, j, len = 1;
+       char *s;
+
+       for (i = 0; i < nl->count; i++)
+               len += strlen(nl->nids[i]) + seplen;
+       if (!(s = malloc(len)))
+               nl_oom();
+       s[0] = '\0';
+       for (i = 0; i < nl->count; i++) {
+               if (i > 0)
+                       strcat(s, sep);
+               for (j = i + 1; j < nl->count; j++) {
+                       if (nl_cmp_lnet(nl->nids[i], nl->nids[j]) != 0)
+                               break;
+                       (void)nl_cmp_addr(nl->nids[i], nl->nids[j], &cflag);
+                       if (!cflag)
+                               break;
+               }
+               if (j - i > 1)
+                       nl_strxcat(s, &nl->nids[i], j - i);
+               else
+                       strcat(s, nl->nids[i]);
+               i += j - i - 1;
+       }
+       return s;
+}
diff --git a/lustre/utils/nidlist.h b/lustre/utils/nidlist.h
new file mode 100644 (file)
index 0000000..1978736
--- /dev/null
@@ -0,0 +1,56 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * 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 version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/utils/nidlist.h
+ *
+ * Author: Jim Garlick <garlick@llnl.gov>
+ */
+
+#ifndef NIDLIST_H
+#define NIDLIST_H
+
+typedef struct nl_struct *NIDList;
+
+NIDList nl_create(void);
+void nl_destroy(NIDList nl);
+void nl_add(NIDList nl, char *nid);
+int nl_count(NIDList nl);
+void nl_lookup_ip(NIDList nl);
+void nl_sort(NIDList nl);
+void nl_uniq(NIDList nl);
+char *nl_string(NIDList nl, char *sep);
+char *nl_xstring(NIDList nl, char *sep);
+
+#endif