4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the GNU Lesser General Public License
8 * (LGPL) version 2.1 or (at your discretion) any later version.
9 * (LGPL) version 2.1 accompanies this distribution, and is available at
10 * http://www.gnu.org/licenses/lgpl-2.1.html
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
20 * libcfs/libcfs/utils/param.c
22 * This code handles user interaction with the configuration interface
23 * to the Lustre file system to fine tune it.
35 #include <sys/mount.h>
37 #include <sys/types.h>
39 #include <linux/limits.h>
40 #include <libcfs/util/string.h>
41 #include <libcfs/util/param.h>
43 #include <linux/magic.h>
46 * Get parameter path matching the pattern
48 * \param[out] paths glob_t structure used to hold the final result
49 * \param[in] pattern the pattern containing sprintf format specifiers
50 * which will be used to create the path to match
52 * The \param pattern is appended to the default path glob to complete the
53 * absolute path to the file the caller is requesting. If the results point
54 * to one or more files that exist those results are stored in the \param
55 * paths glob_t structure that is passed by the caller.
57 * Lustre tunables traditionally were in /proc/{sys,fs}/{lnet,lustre}
58 * but in upstream kernels starting with Linux 4.2 these parameters
59 * have been moved to /sys/fs/lustre and /sys/kernel/debug/{lnet,lustre}
60 * so the user tools need to check both locations.
62 * \retval 0 for success, with results stored in \param paths.
63 * \retval -1 for failure with errno set to report the reason.
66 cfs_get_param_paths(glob_t *paths, const char *pattern, ...)
68 char topdir[PATH_MAX] = "{/sys/{fs,kernel/debug}/{lnet,lustre},"
69 "/proc/{fs,sys}/{lnet,lustre}}";
70 static bool test_mounted = false;
73 struct statfs statfsbuf;
82 rc = statfs("/sys/kernel/debug/", &statfsbuf);
83 if (rc == 0 && statfsbuf.f_type == DEBUGFS_MAGIC)
86 if (mount("none", "/sys/kernel/debug", "debugfs", 0, "") == -1) {
87 /* Already mounted or don't have permission to mount is okay */
88 if (errno != EPERM && errno != EBUSY)
89 fprintf(stderr, "Warning: failed to mount debug: %s\n",
94 /* This is all for RHEL6 which is old school. Can be removed
95 * later when RHEL6 client support is dropped. */
96 rc = lstat(_PATH_MOUNTED, &mtab);
97 if (!rc && !S_ISLNK(mtab.st_mode)) {
98 FILE *fp = setmntent(_PATH_MOUNTED, "r+");
101 const struct mntent fs = {
102 .mnt_fsname = "debugfs",
103 .mnt_dir = "/sys/kernel/debug",
104 .mnt_type = "debugfs",
105 .mnt_opts = "rw,relatime",
108 rc = addmntent(fp, &fs);
111 "failed to add debugfs to %s: %s\n",
112 _PATH_MOUNTED, strerror(errno));
116 fprintf(stderr, "could not open %s: %s\n",
117 _PATH_MOUNTED, strerror(errno));
122 va_start(args, pattern);
123 rc = vsnprintf(buf, sizeof(buf), pattern, args);
127 } else if (rc >= sizeof(buf)) {
132 if (snprintf(path, sizeof(path), "%s/%s", topdir, buf) >=
138 rc = glob(path, GLOB_BRACE, NULL, paths);