From 4aed5234f1123efc06c5c7e702085a461a8aae12 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Mon, 28 Dec 2015 11:58:59 -0500 Subject: [PATCH] LU-5030 libcfs: create cfs_get_paths() function With the move of the upstream client to sysfs the lustre and lnet utilites no long should directly access the proc file system. To avoid this a new function is created to support both the traditional procfs lustre/lnet parameters as well as the new sysfs lustre/lnet parameters as well. Besides the creation of these functions the LNet utilites are converted to use these new functions. Change-Id: I78788f41955073e1e48126103ef2aec13d64812b Signed-off-by: Dmitry Eremin Signed-off-by: James Simmons Signed-off-by: Wang Chao Reviewed-on: http://review.whamcloud.com/17459 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Ryan Haasken Reviewed-by: Emoly Liu --- libcfs/include/libcfs/util/Makefile.am | 2 +- libcfs/include/libcfs/util/param.h | 40 +++++++++++++ libcfs/libcfs/autoMakefile.am | 4 +- libcfs/libcfs/util/Makefile.am | 7 ++- libcfs/libcfs/util/param.c | 100 +++++++++++++++++++++++++++++++++ lnet/utils/Makefile.am | 2 +- lnet/utils/debug.c | 46 +++++++++------ lnet/utils/routerstat.c | 64 ++++++++++++--------- 8 files changed, 217 insertions(+), 48 deletions(-) create mode 100644 libcfs/include/libcfs/util/param.h create mode 100644 libcfs/libcfs/util/param.c diff --git a/libcfs/include/libcfs/util/Makefile.am b/libcfs/include/libcfs/util/Makefile.am index 8bde63f..8dc52ce 100644 --- a/libcfs/include/libcfs/util/Makefile.am +++ b/libcfs/include/libcfs/util/Makefile.am @@ -1 +1 @@ -EXTRA_DIST = ioctl.h parser.h string.h +EXTRA_DIST = ioctl.h parser.h param.h string.h diff --git a/libcfs/include/libcfs/util/param.h b/libcfs/include/libcfs/util/param.h new file mode 100644 index 0000000..2fd1e36 --- /dev/null +++ b/libcfs/include/libcfs/util/param.h @@ -0,0 +1,40 @@ +/* + * LGPL 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 Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * LGPL HEADER END + * + * Copyright (c) 2015, James Simmons + * + * Author: + * James Simmons + */ +#ifndef _LIBCFS_UTIL_PARAM_H_ +#define _LIBCFS_UTIL_PARAM_H_ + +#include +#include + +static inline void cfs_free_param_data(glob_t *paths) +{ + globfree(paths); +} + +int cfs_get_param_paths(glob_t *paths, const char *pattern, ...) + __attribute__((__format__(__printf__, 2, 3))); + +#endif /* _LIBCFS_UTIL_PARAM_H_ */ diff --git a/libcfs/libcfs/autoMakefile.am b/libcfs/libcfs/autoMakefile.am index 19638d1..19adcec 100644 --- a/libcfs/libcfs/autoMakefile.am +++ b/libcfs/libcfs/autoMakefile.am @@ -39,8 +39,8 @@ SUBDIRS = linux util DIST_SUBDIRS = linux util -noinst_LIBRARIES= libcfs.a -libcfs_a_SOURCES := util/string.c util/nidstrings.c +noinst_LIBRARIES = libcfs.a +libcfs_a_SOURCES := util/string.c util/nidstrings.c util/param.c libcfs_a_CPPFLAGS := -D_GNU_SOURCE libcfs_a_CPPFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 libcfs_a_CFLAGS := -fPIC diff --git a/libcfs/libcfs/util/Makefile.am b/libcfs/libcfs/util/Makefile.am index 311f4aa..dcbf140 100644 --- a/libcfs/libcfs/util/Makefile.am +++ b/libcfs/libcfs/util/Makefile.am @@ -1 +1,6 @@ -EXTRA_DIST = parser.c l_ioctl.c nidstrings.c string.c +EXTRA_DIST = \ + l_ioctl.c \ + nidstrings.c \ + param.c \ + parser.c \ + string.c diff --git a/libcfs/libcfs/util/param.c b/libcfs/libcfs/util/param.c new file mode 100644 index 0000000..15c7dbe --- /dev/null +++ b/libcfs/libcfs/util/param.c @@ -0,0 +1,100 @@ +/* + * LGPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public License + * (LGPL) version 2.1 or (at your discretion) any later version. + * (LGPL) version 2.1 accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl-2.1.html + * + * This library 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 + * Lesser General Public License for more details. + * + * LGPL HEADER END + */ +/* + * libcfs/libcfs/utils/param.c + * + * This code handles user interaction with the configuration interface + * to the Lustre file system to fine tune it. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Get parameter path matching the pattern + * + * \param[out] paths glob_t structure used to hold the final result + * \param[in] pattern the pattern containing sprintf format specifiers + * which will be used to create the path to match + * + * The \param pattern is appended to the default path glob to complete the + * absolute path to the file the caller is requesting. If the results point + * to one or more files that exist those results are stored in the \param + * paths glob_t structure that is passed by the caller. + * + * Lustre tunables traditionally were in /proc/{sys,fs}/{lnet,lustre} + * but in upstream kernels starting with Linux 4.2 these parameters + * have been moved to /sys/fs/lustre and /sys/kernel/debug/{lnet,lustre} + * so the user tools need to check both locations. + * + * \retval 0 for success, with results stored in \param paths. + * \retval -1 for failure with errno set to report the reason. + */ +int +cfs_get_param_paths(glob_t *paths, const char *pattern, ...) +{ + char path[PATH_MAX] = "{/sys/{fs,kernel/debug}/{lnet,lustre}/," + "/proc/{fs,sys}/{lnet,lustre}/}"; + size_t len = strlen(path); + char buf[PATH_MAX]; + va_list args; + int rc; + + va_start(args, pattern); + rc = vsnprintf(buf, sizeof(buf), pattern, args); + va_end(args); + if (rc < 0) { + return rc; + } else if (rc >= sizeof(buf)) { + errno = EINVAL; + return -1; + } + len += rc; + + if (strlcat(path, buf, sizeof(path)) != len) { + errno = E2BIG; + return -1; + } + + rc = glob(path, GLOB_BRACE, NULL, paths); + if (rc != 0) { + switch (rc) { + case GLOB_NOSPACE: + errno = ENOMEM; + break; + case GLOB_ABORTED: + errno = ENODEV; + break; + case GLOB_NOMATCH: + default: + errno = ENOENT; + break; + } + rc = -1; + } + + return rc; +} diff --git a/lnet/utils/Makefile.am b/lnet/utils/Makefile.am index 015970a..ab9ef92 100644 --- a/lnet/utils/Makefile.am +++ b/lnet/utils/Makefile.am @@ -54,6 +54,7 @@ sbin_PROGRAMS += lnetctl endif # BUILD_DLC routerstat_SOURCES = routerstat.c +routerstat_LDADD = $(LIBCFS) lst_SOURCES = lst.c lst_LDADD = -lptlctl $(LIBCFSUTIL) $(LIBCFS) $(LIBREADLINE) $(LIBEFENCE) @@ -66,7 +67,6 @@ wirecheck_SOURCES = wirecheck.c endif # TESTS lib_LIBRARIES = libptlctl.a - libptlctl_a_SOURCES = portals.c debug.c CYAML := $(top_builddir)/lnet/utils/cyaml/cyaml.c diff --git a/lnet/utils/debug.c b/lnet/utils/debug.c index aae7e46..babadc7 100644 --- a/lnet/utils/debug.c +++ b/lnet/utils/debug.c @@ -59,6 +59,7 @@ #include #include +#include #include #include #include @@ -75,21 +76,34 @@ static int debug_mask = ~0; static const char *libcfs_debug_subsystems[] = LIBCFS_DEBUG_SUBSYS_NAMES; static const char *libcfs_debug_masks[] = LIBCFS_DEBUG_MASKS_NAMES; -#define DAEMON_CTL_NAME "/proc/sys/lnet/daemon_file" -#define SUBSYS_DEBUG_CTL_NAME "/proc/sys/lnet/subsystem_debug" -#define DEBUG_CTL_NAME "/proc/sys/lnet/debug" -#define DUMP_KERNEL_CTL_NAME "/proc/sys/lnet/dump_kernel" +#define DAEMON_CTL_NAME "daemon_file" +#define SUBSYS_DEBUG_CTL_NAME "subsystem_debug" +#define DEBUG_CTL_NAME "debug" +#define DUMP_KERNEL_CTL_NAME "dump_kernel" +/* + * Open the parameter file "debug" which controls the debugging + * flags used to determine what information ends up in the lustre + * logs collected by lctl dk or the debug daemon. + */ static int dbg_open_ctlhandle(const char *str) { - int fd; - fd = open(str, O_WRONLY); - if (fd < 0) { - fprintf(stderr, "open %s failed: %s\n", str, - strerror(errno)); + glob_t path; + int fd, rc; + + rc = cfs_get_param_paths(&path, str); + if (rc != 0) { + fprintf(stderr, "invalid parameter '%s'\n", str); return -1; } + + fd = open(path.gl_pathv[0], O_WRONLY); + if (fd < 0) + fprintf(stderr, "open '%s' failed: %s\n", + path.gl_pathv[0], strerror(errno)); + + cfs_free_param_data(&path); return fd; } @@ -183,22 +197,20 @@ int jt_dbg_show(int argc, char **argv) return 0; } -static int applymask(char* procpath, int value) +static int applymask(char *param, int value) { int rc; char buf[64]; int len = snprintf(buf, 64, "%d", value); - int fd = dbg_open_ctlhandle(procpath); - if (fd == -1) { - fprintf(stderr, "Unable to open %s: %s\n", - procpath, strerror(errno)); + int fd = dbg_open_ctlhandle(param); + if (fd < 0) return fd; - } + rc = dbg_write_cmd(fd, buf, len+1); if (rc != 0) { fprintf(stderr, "Write to %s failed: %s\n", - procpath, strerror(errno)); + param, strerror(errno)); } dbg_close_ctlhandle(fd); @@ -210,7 +222,7 @@ static void applymask_all(unsigned int subs_mask, unsigned int debug_mask) { applymask(SUBSYS_DEBUG_CTL_NAME, subs_mask); applymask(DEBUG_CTL_NAME, debug_mask); - printf("Applied subsystem_debug=%d, debug=%d to /proc/sys/lnet\n", + printf("Applied subsystem_debug=%d, debug=%d to lnet\n", subs_mask, debug_mask); } diff --git a/lnet/utils/routerstat.c b/lnet/utils/routerstat.c index f31f811..edd3464 100644 --- a/lnet/utils/routerstat.c +++ b/lnet/utils/routerstat.c @@ -34,14 +34,18 @@ * Lustre is a trademark of Sun Microsystems, Inc. */ -#include #include -#include #include -#include +#include +#include +#include #include +#include #include #include +#include + +#include double timenow () @@ -168,28 +172,36 @@ do_stat (int fd) last = timenow(); } -int main (int argc, char **argv) +int main(int argc, char **argv) { - int interval = 0; - int fd; - - if (argc > 1) - interval = atoi (argv[1]); - - fd = open ("/proc/sys/lnet/stats", O_RDONLY); - if (fd < 0) - { - fprintf (stderr, "Can't open stat: %s\n", strerror (errno)); - return (1); - } - - do_stat (fd); - if (interval == 0) - return (0); - - for (;;) - { - sleep (interval); - do_stat (fd); - } + int interval = 0; + glob_t path; + int fd; + + if (argc > 1) + interval = atoi(argv[1]); + + if (cfs_get_param_paths(&path, "stats") != 0) { + fprintf(stderr, "LNet stats not available\n"); + return 1; + } + + fd = open(path.gl_pathv[0], O_RDONLY); + if (fd < 0) { + fprintf(stderr, "failed to open '%s': %s\n", path.gl_pathv[0], + strerror(errno)); + cfs_free_param_data(&path); + return 1; + } + cfs_free_param_data(&path); + + do_stat(fd); + if (interval == 0) + return 0; + + while (1) { + sleep(interval); + do_stat(fd); + } + /* Never reached */ } -- 1.8.3.1