Merge remote-tracking branch 'cgroup/for-next'
[deliverable/linux.git] / fs / kernfs / dir.c
index 390390212b4324855331862d0110515bc5c618e5..498e2a6f401eee7d1a0c881177a467f1022058ae 100644 (file)
@@ -110,8 +110,9 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a,
  * kn_to:   /n1/n2/n3         [depth=3]
  * result:  /../..
  *
- * return value: length of the string.  If greater than buflen,
- * then contents of buf are undefined.  On error, -1 is returned.
+ * Returns the length of the full path.  If the full length is equal to or
+ * greater than @buflen, @buf contains the truncated path with the trailing
+ * '\0'.  On error, -errno is returned.
  */
 static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
                                        struct kernfs_node *kn_from,
@@ -119,9 +120,8 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
 {
        struct kernfs_node *kn, *common;
        const char parent_str[] = "/..";
-       size_t depth_from, depth_to, len = 0, nlen = 0;
-       char *p;
-       int i;
+       size_t depth_from, depth_to, len = 0;
+       int i, j;
 
        if (!kn_from)
                kn_from = kernfs_root(kn_to)->kn;
@@ -131,7 +131,7 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
 
        common = kernfs_common_ancestor(kn_from, kn_to);
        if (WARN_ON(!common))
-               return -1;
+               return -EINVAL;
 
        depth_to = kernfs_depth(common, kn_to);
        depth_from = kernfs_depth(common, kn_from);
@@ -144,22 +144,16 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
                               len < buflen ? buflen - len : 0);
 
        /* Calculate how many bytes we need for the rest */
-       for (kn = kn_to; kn != common; kn = kn->parent)
-               nlen += strlen(kn->name) + 1;
-
-       if (len + nlen >= buflen)
-               return len + nlen;
-
-       p = buf + len + nlen;
-       *p = '\0';
-       for (kn = kn_to; kn != common; kn = kn->parent) {
-               size_t tmp = strlen(kn->name);
-               p -= tmp;
-               memcpy(p, kn->name, tmp);
-               *(--p) = '/';
+       for (i = depth_to - 1; i >= 0; i--) {
+               for (kn = kn_to, j = 0; j < i; j++)
+                       kn = kn->parent;
+               len += strlcpy(buf + len, "/",
+                              len < buflen ? buflen - len : 0);
+               len += strlcpy(buf + len, kn->name,
+                              len < buflen ? buflen - len : 0);
        }
 
-       return len + nlen;
+       return len;
 }
 
 /**
@@ -185,29 +179,6 @@ int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
        return ret;
 }
 
-/**
- * kernfs_path_len - determine the length of the full path of a given node
- * @kn: kernfs_node of interest
- *
- * The returned length doesn't include the space for the terminating '\0'.
- */
-size_t kernfs_path_len(struct kernfs_node *kn)
-{
-       size_t len = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&kernfs_rename_lock, flags);
-
-       do {
-               len += strlen(kn->name) + 1;
-               kn = kn->parent;
-       } while (kn && kn->parent);
-
-       spin_unlock_irqrestore(&kernfs_rename_lock, flags);
-
-       return len;
-}
-
 /**
  * kernfs_path_from_node - build path of node @to relative to @from.
  * @from: parent kernfs_node relative to which we need to build the path
@@ -220,8 +191,9 @@ size_t kernfs_path_len(struct kernfs_node *kn)
  * path (which includes '..'s) as needed to reach from @from to @to is
  * returned.
  *
- * If @buf isn't long enough, the return value will be greater than @buflen
- * and @buf contents are undefined.
+ * Returns the length of the full path.  If the full length is equal to or
+ * greater than @buflen, @buf contains the truncated path with the trailing
+ * '\0'.  On error, -errno is returned.
  */
 int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
                          char *buf, size_t buflen)
@@ -236,28 +208,6 @@ int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
 }
 EXPORT_SYMBOL_GPL(kernfs_path_from_node);
 
-/**
- * kernfs_path - build full path of a given node
- * @kn: kernfs_node of interest
- * @buf: buffer to copy @kn's name into
- * @buflen: size of @buf
- *
- * Builds and returns the full path of @kn in @buf of @buflen bytes.  The
- * path is built from the end of @buf so the returned pointer usually
- * doesn't match @buf.  If @buf isn't long enough, @buf is nul terminated
- * and %NULL is returned.
- */
-char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
-{
-       int ret;
-
-       ret = kernfs_path_from_node(kn, NULL, buf, buflen);
-       if (ret < 0 || ret >= buflen)
-               return NULL;
-       return buf;
-}
-EXPORT_SYMBOL_GPL(kernfs_path);
-
 /**
  * pr_cont_kernfs_name - pr_cont name of a kernfs_node
  * @kn: kernfs_node of interest
This page took 0.027169 seconds and 5 git commands to generate.