Whamcloud - gitweb
LU-8993 utils: Use absolute pathname for debug_daemon log file 85/25485/9
authorSteve Guminski <stephenx.guminski@intel.com>
Mon, 13 Feb 2017 20:24:08 +0000 (15:24 -0500)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 28 Aug 2017 06:25:10 +0000 (06:25 +0000)
The lctl debug_daemon command is changed to always provide an
absolute pathname to the kernel.  The kernel code will return EINVAL
if the pathname does not begin with '/', leading to the confusing
error "Invalid argument". This patch allows the user to provide a
relative pathname to the command without generating this error.

The absolute_path function has been moved to string.c and renamed to
cfs_abs_path, so that it may be used by all utilities.

Signed-off-by: Steve Guminski <stephenx.guminski@intel.com>
Change-Id: I35af242bfcfcb9a56135aeabe0423e28e9634bab
Reviewed-on: https://review.whamcloud.com/25485
Tested-by: Jenkins
Reviewed-by: John L. Hammond <john.hammond@intel.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
libcfs/include/libcfs/util/string.h
libcfs/libcfs/util/string.c
lnet/utils/debug.c
lustre/utils/libmount_utils_ldiskfs.c

index 4dc7abf..bf83fb8 100644 (file)
@@ -91,5 +91,6 @@ void cfs_expr_list_free(struct cfs_expr_list *expr_list);
 void cfs_expr_list_free_list(struct list_head *list);
 int cfs_ip_addr_parse(char *str, int len, struct list_head *list);
 int cfs_ip_addr_match(__u32 addr, struct list_head *list);
+int cfs_abs_path(const char *request_path, char **resolved_path);
 
 #endif
index 9078500..223281d 100644 (file)
@@ -41,6 +41,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
+#include <unistd.h>
 #include <libcfs/util/string.h>
 
 /*
@@ -480,3 +482,83 @@ cfs_expr_list_free_list(struct list_head *list)
                cfs_expr_list_free(el);
        }
 }
+
+/**
+ * cfs_abs_path() - Get the absolute path of a relative path
+ * @request_path:      The relative path to be resolved
+ * @resolved_path:     Set to the resolved absolute path
+ *
+ * Returns the canonicalized absolute pathname.  This function is a wrapper to
+ * realpath, but will work even if the target file does not exist.  All
+ * directories in the path must exist.
+ *
+ * Return: On success, 0 is returned and resolved_path points to an allocated
+ * string containing the absolute pathname.  On error, errno is set
+ * appropriately, -errno is returned, and resolved_path points to NULL.
+ */
+int cfs_abs_path(const char *request_path, char **resolved_path)
+{
+       char  buf[PATH_MAX + 1] = "";
+       char *path;
+       char *ptr;
+       int len;
+       int rc = 0;
+       const char *fmt;
+
+       path = malloc(sizeof(buf));
+       if (path == NULL)
+               return -ENOMEM;
+
+       if (request_path[0] != '/') {
+               if (getcwd(path, sizeof(buf) - 1) == NULL) {
+                       rc = -errno;
+                       goto out;
+               }
+               len = snprintf(buf, sizeof(buf), "%s/%s", path, request_path);
+               if (len >= sizeof(buf)) {
+                       rc = -ENAMETOOLONG;
+                       goto out;
+               }
+       } else {
+               /* skip duplicate leading '/' */
+               len = snprintf(buf, sizeof(buf), "%s",
+                              request_path + strspn(request_path, "/") - 1);
+               if (len >= sizeof(buf)) {
+                       rc = -ENAMETOOLONG;
+                       goto out;
+               }
+       }
+
+       /* if filename not in root directory, call realpath for parent path */
+       ptr = strrchr(buf, '/');
+       if (ptr != buf) {
+               *ptr = '\0';
+               if (path != realpath(buf, path)) {
+                       rc = -errno;
+                       goto out;
+               }
+               /* add the filename back */
+               len = strlen(path);
+               fmt = (path[len - 1] == '/') ? "%s" : "/%s";
+               len = snprintf(path + len, sizeof(buf) - len, fmt, ptr + 1);
+               if (len >= sizeof(buf) - len) {
+                       rc = -ENAMETOOLONG;
+                       goto out;
+               }
+       } else {
+               len = snprintf(path, sizeof(buf), "%s", buf);
+               if (len >= sizeof(buf)) {
+                       rc = -ENAMETOOLONG;
+                       goto out;
+               }
+       }
+
+out:
+       if (rc == 0) {
+               *resolved_path = path;
+       } else {
+               *resolved_path = NULL;
+               free(path);
+       }
+       return rc;
+}
index 8a9f0c2..a0ef7de 100644 (file)
@@ -58,6 +58,7 @@
 #include <libcfs/util/param.h>
 #include <linux/lnet/libcfs_debug.h>
 #include <linux/lnet/lnetctl.h>
+#include <libcfs/util/string.h>
 
 static char rawbuf[8192];
 static char *buf = rawbuf;
@@ -646,6 +647,7 @@ int jt_dbg_debug_daemon(int argc, char **argv)
 {
        int rc;
        int fd;
+       char *resolved_path = NULL;
 
        if (argc <= 1) {
                fprintf(stderr, debug_daemon_usage, argv[0]);
@@ -689,7 +691,15 @@ int jt_dbg_debug_daemon(int argc, char **argv)
                        }
                }
 
-               rc = dbg_write_cmd(fd, argv[2], strlen(argv[2]));
+               rc = cfs_abs_path(argv[2], &resolved_path);
+               if (rc != 0) {
+                       fprintf(stderr,
+                               "%s debug_daemon: cannot resolve path '%s': %s\n",
+                               program_invocation_short_name, argv[2],
+                               strerror(-rc));
+                       goto out;
+               }
+               rc = dbg_write_cmd(fd, resolved_path, strlen(resolved_path));
                if (rc != 0) {
                        fprintf(stderr, "start debug_daemon on %s failed: %s\n",
                                argv[2], strerror(errno));
@@ -714,6 +724,8 @@ int jt_dbg_debug_daemon(int argc, char **argv)
        rc = -1;
 out:
        dbg_close_ctlhandle(fd);
+       if (resolved_path != NULL)
+               free(resolved_path);
        return rc;
 }
 
index c6ece22..ec7b556 100644 (file)
@@ -70,6 +70,7 @@
 #include <linux/version.h>
 #include <linux/lnet/lnetctl.h>
 #include <linux/lustre/lustre_ver.h>
+#include <libcfs/util/string.h>
 
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
@@ -120,57 +121,6 @@ static void append_context_for_mount(char *mntpt, struct mkfs_opts *mop)
 }
 #endif
 
-/* return canonicalized absolute pathname, even if the target file does not
- * exist, unlike realpath */
-static char *absolute_path(char *devname)
-{
-       char  buf[PATH_MAX + 1] = "";
-       char *path;
-       char *ptr;
-       int len;
-
-       path = malloc(sizeof(buf));
-       if (path == NULL)
-               return NULL;
-
-       if (devname[0] != '/') {
-               if (getcwd(buf, sizeof(buf) - 1) == NULL) {
-                       free(path);
-                       return NULL;
-               }
-               len = snprintf(path, sizeof(buf), "%s/%s", buf, devname);
-               if (len >= sizeof(buf)) {
-                       free(path);
-                       return NULL;
-               }
-       } else {
-               len = snprintf(path, sizeof(buf), "%s", devname);
-               if (len >= sizeof(buf)) {
-                       free(path);
-                       return NULL;
-               }
-       }
-
-       /* truncate filename before calling realpath */
-       ptr = strrchr(path, '/');
-       if (ptr == NULL) {
-               free(path);
-               return NULL;
-       }
-       *ptr = '\0';
-       if (buf != realpath(path, buf)) {
-               free(path);
-               return NULL;
-       }
-       /* add the filename back */
-       len = snprintf(path, PATH_MAX, "%s/%s", buf, ptr+1);
-       if (len >= PATH_MAX) {
-               free(path);
-               return NULL;
-       }
-       return path;
-}
-
 /* Determine if a device is a block device (as opposed to a file) */
 static int is_block(char *devname)
 {
@@ -178,10 +128,10 @@ static int is_block(char *devname)
        int     ret = 0;
        char    *devpath;
 
-       devpath = absolute_path(devname);
-       if (devpath == NULL) {
-               fprintf(stderr, "%s: failed to resolve path to %s\n",
-                       progname, devname);
+       ret = cfs_abs_path(devname, &devpath);
+       if (ret != 0) {
+               fprintf(stderr, "%s: failed to resolve path '%s': %s\n",
+                       progname, devname, strerror(-ret));
                return -1;
        }