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
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
--- /dev/null
+/* -*- 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);
+ }
+}
--- /dev/null
+/* -*- 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;
+}
--- /dev/null
+/* -*- 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