From: zhanghc Date: Mon, 16 Mar 2009 04:20:39 +0000 (+0000) Subject: b=17997 X-Git-Tag: v1_9_166~29 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=2177e48c99e9f63c8d64cdc032de78284ac85381;p=fs%2Flustre-release.git b=17997 add a new implementation of lshowmount i=adilger i=hongchao.zhang --- diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index 51b9803..6b4f57c 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -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 index 0000000..920bebb --- /dev/null +++ b/lustre/utils/lshowmount.c @@ -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 + * Author: Jim Garlick + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..fb0cbec --- /dev/null +++ b/lustre/utils/nidlist.c @@ -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 + */ + +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..1978736 --- /dev/null +++ b/lustre/utils/nidlist.h @@ -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 + */ + +#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