#include <errno.h>
#include <fcntl.h>
#include <glob.h>
+#include <mntent.h>
+#include <paths.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#include <linux/limits.h>
#include <libcfs/util/string.h>
+#include <sys/vfs.h>
+#include <linux/magic.h>
/**
* Get parameter path matching the pattern
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 topdir[PATH_MAX] = "{/sys/{fs,kernel/debug}/{lnet,lustre},"
+ "/proc/{fs,sys}/{lnet,lustre}}";
+ static bool test_mounted = false;
+ char path[PATH_MAX];
char buf[PATH_MAX];
+ struct statfs statfsbuf;
va_list args;
int rc;
+
+ if (test_mounted)
+ goto skip_mounting;
+ test_mounted = true;
+
+ rc = statfs("/sys/kernel/debug/", &statfsbuf);
+ if (rc == 0 && statfsbuf.f_type == DEBUGFS_MAGIC)
+ goto skip_mounting;
+
+ if (mount("none", "/sys/kernel/debug", "debugfs", 0, "") == -1) {
+ /* Already mounted or don't have permission to mount is okay */
+ if (errno != EPERM && errno != EBUSY)
+ fprintf(stderr, "Warning: failed to mount debug: %s\n",
+ strerror(errno));
+ } else {
+ struct stat mtab;
+
+ /* This is all for RHEL6 which is old school. Can be removed
+ * later when RHEL6 client support is dropped. */
+ rc = lstat(_PATH_MOUNTED, &mtab);
+ if (!rc && !S_ISLNK(mtab.st_mode)) {
+ FILE *fp = setmntent(_PATH_MOUNTED, "r+");
+
+ if (fp != NULL) {
+ const struct mntent fs = {
+ .mnt_fsname = "debugfs",
+ .mnt_dir = "/sys/kernel/debug",
+ .mnt_type = "debugfs",
+ .mnt_opts = "rw,relatime",
+ };
+
+ rc = addmntent(fp, &fs);
+ if (rc) {
+ fprintf(stderr,
+ "failed to add debugfs to %s: %s\n",
+ _PATH_MOUNTED, strerror(errno));
+ }
+ endmntent(fp);
+ } else {
+ fprintf(stderr, "could not open %s: %s\n",
+ _PATH_MOUNTED, strerror(errno));
+ }
+ }
+ }
+skip_mounting:
va_start(args, pattern);
rc = vsnprintf(buf, sizeof(buf), pattern, args);
va_end(args);
errno = EINVAL;
return -1;
}
- len += rc;
- if (strlcat(path, buf, sizeof(path)) != len) {
+ if (snprintf(path, sizeof(path), "%s/%s", topdir, buf) >=
+ sizeof(path)) {
errno = E2BIG;
return -1;
}