Whamcloud - gitweb
LU-12352 libcfs: crashes with certain cpu part numbers
[fs/lustre-release.git] / libcfs / libcfs / util / param.c
index 15c7dbe..18fe84d 100644 (file)
 #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);
@@ -72,9 +127,9 @@ cfs_get_param_paths(glob_t *paths, const char *pattern, ...)
                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;
        }