Whamcloud - gitweb
LU-17402 kernel: update dotdot patch path for RHEL 8.10
[fs/lustre-release.git] / libcfs / libcfs / util / param.c
1 /*
2  * LGPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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
11  *
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.
16  *
17  * LGPL HEADER END
18  */
19 /*
20  * libcfs/libcfs/utils/param.c
21  *
22  * This code handles user interaction with the configuration interface
23  * to the Lustre file system to fine tune it.
24  */
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <glob.h>
28 #include <mntent.h>
29 #include <paths.h>
30 #include <stdarg.h>
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/mount.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39 #include <linux/limits.h>
40 #include <libcfs/util/string.h>
41 #include <libcfs/util/param.h>
42 #include <sys/vfs.h>
43 #include <linux/magic.h>
44
45 /**
46  * Get parameter path matching the pattern
47  *
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
51  *
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.
56  *
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.
61  *
62  * \retval       0 for success, with results stored in \param paths.
63  * \retval      -1 for failure with errno set to report the reason.
64  */
65 int
66 cfs_get_param_paths(glob_t *paths, const char *pattern, ...)
67 {
68         char topdir[PATH_MAX] = "{/sys/{fs,kernel/debug}/{lnet,lustre},"
69                                 "/proc/{fs,sys}/{lnet,lustre}}";
70         static bool test_mounted = false;
71         char path[PATH_MAX];
72         char buf[PATH_MAX];
73         struct statfs statfsbuf;
74         va_list args;
75         int rc;
76
77
78         if (test_mounted)
79                 goto skip_mounting;
80         test_mounted = true;
81
82         rc = statfs("/sys/kernel/debug/", &statfsbuf);
83         if (rc == 0 && statfsbuf.f_type == DEBUGFS_MAGIC)
84                 goto skip_mounting;
85
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",
90                                 strerror(errno));
91         } else {
92                 struct stat mtab;
93
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+");
99
100                         if (fp != NULL) {
101                                 const struct mntent fs = {
102                                         .mnt_fsname     = "debugfs",
103                                         .mnt_dir        = "/sys/kernel/debug",
104                                         .mnt_type       = "debugfs",
105                                         .mnt_opts       = "rw,relatime",
106                                 };
107
108                                 rc = addmntent(fp, &fs);
109                                 if (rc) {
110                                         fprintf(stderr,
111                                                 "failed to add debugfs to %s: %s\n",
112                                                 _PATH_MOUNTED, strerror(errno));
113                                 }
114                                 endmntent(fp);
115                         } else {
116                                 fprintf(stderr, "could not open %s: %s\n",
117                                         _PATH_MOUNTED, strerror(errno));
118                         }
119                 }
120         }
121 skip_mounting:
122         va_start(args, pattern);
123         rc = vsnprintf(buf, sizeof(buf), pattern, args);
124         va_end(args);
125         if (rc < 0) {
126                 return rc;
127         } else if (rc >= sizeof(buf)) {
128                 errno = EINVAL;
129                 return -1;
130         }
131
132         if (snprintf(path, sizeof(path), "%s/%s", topdir, buf) >=
133             sizeof(path)) {
134                 errno = E2BIG;
135                 return -1;
136         }
137
138         rc = glob(path, GLOB_BRACE, NULL, paths);
139         if (rc != 0) {
140                 switch (rc) {
141                 case GLOB_NOSPACE:
142                         errno = ENOMEM;
143                         break;
144                 case GLOB_ABORTED:
145                         errno = ENODEV;
146                         break;
147                 case GLOB_NOMATCH:
148                 default:
149                         errno = ENOENT;
150                         break;
151                 }
152                 rc = -1;
153         }
154
155         return rc;
156 }