21ab4e
From 4b1fdb2a6c56f7dbfdab4f12fe8320d29260d7f4 Mon Sep 17 00:00:00 2001
21ab4e
From: Jiffin Tony Thottan <jthottan@redhat.com>
21ab4e
Date: Sun, 11 Jun 2017 07:33:52 +0530
21ab4e
Subject: [PATCH 522/525] gfapi : Resolve "." and ".." only for named lookups
21ab4e
21ab4e
The patch https://review.gluster.org/#/c/17177 resolves "." and ".."
21ab4e
to corrosponding inodes and names before sending the request to the
21ab4e
backend server. But this will only work if inode and its parent is
21ab4e
linked properly. Incase of nameless lookup(applications like ganesha)
21ab4e
the inode of parent can be NULL(only gfid is send). So this patch will
21ab4e
resolve "." and ".." only if proper parent is available
21ab4e
21ab4e
Upstream reference :
21ab4e
>Change-Id: I4c50258b0d896dabf000a547ab180b57df308a0b
21ab4e
>BUG: 1460514
21ab4e
>Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
21ab4e
>Reviewed-on: https://review.gluster.org/17502
21ab4e
>Smoke: Gluster Build System <jenkins@build.gluster.org>
21ab4e
>NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
21ab4e
>Reviewed-by: Poornima G <pgurusid@redhat.com>
21ab4e
>CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
21ab4e
>Reviewed-by: soumya k <skoduri@redhat.com>
21ab4e
>Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
21ab4e
>Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
21ab4e
21ab4e
Change-Id: I4c50258b0d896dabf000a547ab180b57df308a0b
21ab4e
BUG: 1457183
21ab4e
Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
21ab4e
Reviewed-on: https://code.engineering.redhat.com/gerrit/109520
21ab4e
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
21ab4e
---
21ab4e
 api/src/glfs-resolve.c   |  72 +++++++++++++++++++++++++----
21ab4e
 libglusterfs/src/inode.c | 118 ++++++++---------------------------------------
21ab4e
 libglusterfs/src/inode.h |  17 +------
21ab4e
 3 files changed, 83 insertions(+), 124 deletions(-)
21ab4e
21ab4e
diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c
21ab4e
index 44d013c..8e91cd7 100644
21ab4e
--- a/api/src/glfs-resolve.c
21ab4e
+++ b/api/src/glfs-resolve.c
21ab4e
@@ -268,6 +268,7 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
21ab4e
 {
21ab4e
 	loc_t        loc = {0, };
21ab4e
 	inode_t     *inode = NULL;
21ab4e
+        inode_t     *temp_parent = NULL;
21ab4e
 	int          reval = 0;
21ab4e
 	int          ret = -1;
21ab4e
 	int          glret = -1;
21ab4e
@@ -276,14 +277,12 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
21ab4e
 	dict_t      *xattr_req = NULL;
21ab4e
         uint64_t     ctx_value = LOOKUP_NOT_NEEDED;
21ab4e
 
21ab4e
-	loc.name = component;
21ab4e
-
21ab4e
 	loc.parent = inode_ref (parent);
21ab4e
 	gf_uuid_copy (loc.pargfid, parent->gfid);
21ab4e
 
21ab4e
-        /* At this point we should never have '.' or ".." in path */
21ab4e
         if (__is_root_gfid (parent->gfid) &&
21ab4e
-            (strcmp (component, "/") == 0)) {
21ab4e
+            ((strcmp (component, ".") == 0) ||
21ab4e
+             (strcmp (component, "..") == 0))) {
21ab4e
                 if (!force_lookup) {
21ab4e
                         inode = inode_ref (parent);
21ab4e
                 } else {
21ab4e
@@ -293,8 +292,68 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
21ab4e
                 }
21ab4e
                 goto found;
21ab4e
         }
21ab4e
+        /* *
21ab4e
+        * if the component name is either "." or "..", it will try to
21ab4e
+        * resolve that if inode has a proper parent (named lookup).
21ab4e
+        *
21ab4e
+        * Below condition works like this
21ab4e
+        *
21ab4e
+        * Example 1 :
21ab4e
+        * Path /out_dir/dir/in_dir/.
21ab4e
+        *     In put values :
21ab4e
+        *         parent = in_dir
21ab4e
+        *         component : "."
21ab4e
+        *
21ab4e
+        *      Out put values:
21ab4e
+        *         parent : dir
21ab4e
+        *         component : "in_dir"
21ab4e
+        *
21ab4e
+        * Example 2 :
21ab4e
+        * Path /out_dir/dir/in_dir/..
21ab4e
+        *     In put values :
21ab4e
+        *         parent = in_dir
21ab4e
+        *         component : ".."
21ab4e
+        *
21ab4e
+        *     Out put values:
21ab4e
+        *         parent : output_dir
21ab4e
+        *         component : "dir"
21ab4e
+        *
21ab4e
+        * Incase of nameless lookup, both "." and ".." retained
21ab4e
+        */
21ab4e
+
21ab4e
+        if (strcmp (component, ".") == 0) {
21ab4e
+                loc.inode = inode_ref (parent);
21ab4e
+                temp_parent = inode_parent (loc.inode, 0, 0);
21ab4e
+                if (temp_parent) {
21ab4e
+                        inode_unref (loc.parent);
21ab4e
+                        loc.parent = temp_parent;
21ab4e
+                        inode_find_directory_name (loc.inode, &loc.name);
21ab4e
+                }
21ab4e
+
21ab4e
+        } else if (strcmp (component, "..") == 0) {
21ab4e
+                loc.inode = inode_parent (parent, 0, 0);
21ab4e
+                if (loc.inode) {
21ab4e
+                        temp_parent = inode_parent (loc.inode, 0, 0);
21ab4e
+                        if (temp_parent) {
21ab4e
+                                inode_unref (loc.parent);
21ab4e
+                                loc.parent = temp_parent;
21ab4e
+                                inode_find_directory_name (loc.inode, &loc.name);
21ab4e
+                        } else if (__is_root_gfid (loc.inode->gfid)) {
21ab4e
+                                inode_unref (loc.parent);
21ab4e
+                                loc.parent = inode_ref (loc.inode);
21ab4e
+                                loc.name = "";
21ab4e
+                        } else {
21ab4e
+                                inode_unref (loc.inode);
21ab4e
+                                loc.inode = NULL;
21ab4e
+                        }
21ab4e
+
21ab4e
+                }
21ab4e
+        } else
21ab4e
+                loc.inode = inode_grep (parent->table, parent, component);
21ab4e
+
21ab4e
+        if (!loc.name)
21ab4e
+                loc.name = component;
21ab4e
 
21ab4e
-        loc.inode = inode_grep (parent->table, parent, component);
21ab4e
 	if (loc.inode) {
21ab4e
 		gf_uuid_copy (loc.gfid, loc.inode->gfid);
21ab4e
 		reval = 1;
21ab4e
@@ -389,7 +448,6 @@ found:
21ab4e
 out:
21ab4e
 	if (xattr_req)
21ab4e
 		dict_unref (xattr_req);
21ab4e
-
21ab4e
 	loc_wipe (&loc;;
21ab4e
 
21ab4e
 	return inode;
21ab4e
@@ -409,7 +467,6 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at,
21ab4e
 	char       *next_component = NULL;
21ab4e
 	int         ret = -1;
21ab4e
 	struct iatt ciatt = {0, };
21ab4e
-        char        dentry_name[PATH_MAX]  = {0, };
21ab4e
 
21ab4e
 	DECLARE_OLD_THIS;
21ab4e
 	__GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
21ab4e
@@ -441,7 +498,6 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at,
21ab4e
 		if (parent)
21ab4e
 			inode_unref (parent);
21ab4e
 		parent = inode;
21ab4e
-                glusterfs_normalize_dentry (&parent, &component, dentry_name);
21ab4e
 		inode = glfs_resolve_component (fs, subvol, parent,
21ab4e
 						component, &ciatt,
21ab4e
 						/* force hard lookup on the last
21ab4e
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c
21ab4e
index 90a5608..0353825 100644
21ab4e
--- a/libglusterfs/src/inode.c
21ab4e
+++ b/libglusterfs/src/inode.c
21ab4e
@@ -2549,112 +2549,30 @@ out:
21ab4e
         return size;
21ab4e
 }
21ab4e
 
21ab4e
-static void
21ab4e
-inode_parent_null_check(inode_t **parent, inode_t *inode, char **component)
21ab4e
-{
21ab4e
-        GF_VALIDATE_OR_GOTO ("inode", inode, out);
21ab4e
-        GF_VALIDATE_OR_GOTO ("inode", (*component), out);
21ab4e
-
21ab4e
-        if (!(*parent) && __is_root_gfid (inode->gfid)) {
21ab4e
-                *parent = inode_ref (inode);
21ab4e
-                *component = "/";
21ab4e
-        }
21ab4e
-out:
21ab4e
-        return;
21ab4e
-}
21ab4e
-
21ab4e
-/*
21ab4e
- * This function changes component name and parent inode
21ab4e
- * if the component name is either "." or ".."
21ab4e
- *
21ab4e
- * @Paramas:
21ab4e
- * Parent : Parent inode of current dentry
21ab4e
- * component : component name that we need to test
21ab4e
- * dentry_name : Address for memory if need to change component.
21ab4e
- *               The caller has to preallocate this memory with
21ab4e
- *               PATH_MAX as the size.
21ab4e
- *
21ab4e
- * We return the updated parent inode and component in the
21ab4e
- * respective structures.
21ab4e
- *
21ab4e
- * Basic Idea of the function:
21ab4e
- *
21ab4e
- * Example 1 :
21ab4e
- * Path /out_dir/dir/in_dir/.
21ab4e
- *     In put values :
21ab4e
- *         parent = in_dir
21ab4e
- *         component : "."
21ab4e
- *
21ab4e
- *     Out put values:
21ab4e
- *         parent : dir
21ab4e
- *         component : "in_dir"
21ab4e
- *
21ab4e
- * Example 2 :
21ab4e
- * Path /out_dir/dir/in_dir/..
21ab4e
- *     In put values :
21ab4e
- *         parent = in_dir
21ab4e
- *         component : ".."
21ab4e
- *
21ab4e
- *     Out put values:
21ab4e
- *         parent : output_dir
21ab4e
- *         component : "dir"
21ab4e
- */
21ab4e
+/* *
21ab4e
+ * This function finds name of the inode, if it has dentry. The dentry will be
21ab4e
+ * created only if inode_link happens with valid parent and name. And this
21ab4e
+ * function is only applicable for directories because multiple dentries are
21ab4e
+ * not possible(no hardlinks)
21ab4e
+ * */
21ab4e
 void
21ab4e
-glusterfs_normalize_dentry (inode_t **parent, char **component,
21ab4e
-                          char *dentry_name)
21ab4e
-{
21ab4e
-        inode_t         *temp_inode             = NULL;
21ab4e
-        dentry_t        *dentry                 = NULL;
21ab4e
+inode_find_directory_name (inode_t *inode, const char **name) {
21ab4e
+        dentry_t *dentry = NULL;
21ab4e
 
21ab4e
-        GF_VALIDATE_OR_GOTO ("inode", (*parent), out);
21ab4e
-        GF_VALIDATE_OR_GOTO ("inode", (*component), out);
21ab4e
-        GF_VALIDATE_OR_GOTO ("inode", (dentry_name), out);
21ab4e
+        GF_VALIDATE_OR_GOTO ("inode", inode, out);
21ab4e
+        GF_VALIDATE_OR_GOTO ("inode", name, out);
21ab4e
 
21ab4e
-        /* After this point, there should not be "." or ".."
21ab4e
-         * in the path. Dot and double dots are replaced with
21ab4e
-         * appropriate base name and parent inode.
21ab4e
-         */
21ab4e
+        if (!IA_ISDIR (inode->ia_type))
21ab4e
+                return;
21ab4e
 
21ab4e
-        /* During the resolving, if it goes beyond the mount point
21ab4e
-         * we do lookup on the mount itself like "/.. " will be
21ab4e
-         * converted as "/"
21ab4e
-         */
21ab4e
-        if (strcmp (*component, ".") == 0) {
21ab4e
-                temp_inode = *parent;
21ab4e
-                *parent = inode_parent (*parent, 0, 0);
21ab4e
-                inode_parent_null_check (parent, temp_inode, component);
21ab4e
-                pthread_mutex_lock (&temp_inode->table->lock);
21ab4e
-                {
21ab4e
-                        dentry = __dentry_search_arbit (temp_inode);
21ab4e
-                        if (dentry) {
21ab4e
-                                snprintf (dentry_name, PATH_MAX, "%s",
21ab4e
-                                          dentry->name);
21ab4e
-                                *component = dentry_name;
21ab4e
-                        }
21ab4e
-                }
21ab4e
-                pthread_mutex_unlock (&temp_inode->table->lock);
21ab4e
-                inode_unref (temp_inode);
21ab4e
-        } else if (strcmp (*component, "..") == 0) {
21ab4e
-                temp_inode = *parent;
21ab4e
-                *parent = inode_parent (*parent, 0, 0);
21ab4e
-                inode_parent_null_check (parent, temp_inode, component);
21ab4e
-                inode_unref (temp_inode);
21ab4e
-
21ab4e
-                temp_inode = *parent;
21ab4e
-                *parent = inode_parent (*parent, 0, 0);
21ab4e
-                inode_parent_null_check (parent, temp_inode, component);
21ab4e
-                pthread_mutex_lock (&temp_inode->table->lock);
21ab4e
-                {
21ab4e
-                        dentry = __dentry_search_arbit (temp_inode);
21ab4e
-                        if (dentry) {
21ab4e
-                                snprintf (dentry_name, PATH_MAX, "%s",
21ab4e
-                                          dentry->name);
21ab4e
-                                *component = dentry_name;
21ab4e
-                        }
21ab4e
+        pthread_mutex_lock (&inode->table->lock);
21ab4e
+        {
21ab4e
+                dentry = __dentry_search_arbit (inode);
21ab4e
+                if (dentry) {
21ab4e
+                        *name = dentry->name;
21ab4e
                 }
21ab4e
-                pthread_mutex_unlock (&temp_inode->table->lock);
21ab4e
-                inode_unref (temp_inode);
21ab4e
         }
21ab4e
+        pthread_mutex_unlock (&inode->table->lock);
21ab4e
 out:
21ab4e
         return;
21ab4e
 }
21ab4e
diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h
21ab4e
index e3c38bb..e4ad046 100644
21ab4e
--- a/libglusterfs/src/inode.h
21ab4e
+++ b/libglusterfs/src/inode.h
21ab4e
@@ -282,21 +282,6 @@ inode_has_dentry (inode_t *inode);
21ab4e
 size_t
21ab4e
 inode_ctx_size (inode_t *inode);
21ab4e
 
21ab4e
-/*
21ab4e
- * This function is used to change the dentry from a path
21ab4e
- * if it contains any "." or ".." .
21ab4e
- *
21ab4e
- * It replaces "." and ".." to proper bname after resolving
21ab4e
- * and will change the component accordingly.
21ab4e
- *
21ab4e
- * This fucntion also replaces the parent inode based on the
21ab4e
- * bname.
21ab4e
- *
21ab4e
- * We should give a allocated memory as a third argument to store
21ab4e
- * the component in case if we are modifying it.
21ab4e
- */
21ab4e
-
21ab4e
 void
21ab4e
-glusterfs_normalize_dentry (inode_t **parent, char **component,
21ab4e
-                            char *dentry_name);
21ab4e
+inode_find_directory_name (inode_t *inode, const char **name);
21ab4e
 #endif /* _INODE_H */
21ab4e
-- 
21ab4e
1.8.3.1
21ab4e