diff options
| -rw-r--r-- | api/src/glfs-resolve.c | 41 | ||||
| -rw-r--r-- | libglusterfs/src/inode.c | 110 | ||||
| -rw-r--r-- | libglusterfs/src/inode.h | 17 | 
3 files changed, 144 insertions, 24 deletions
diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c index d495cd21413..a2be87f1c1e 100644 --- a/api/src/glfs-resolve.c +++ b/api/src/glfs-resolve.c @@ -25,12 +25,10 @@  #include "syncop.h"  #include "call-stub.h"  #include "gfapi-messages.h" - +#include "inode.h"  #include "glfs-internal.h"  #define graphid_str(subvol) (uuid_utoa((unsigned char *)subvol->graph->graph_uuid)) - -  int  glfs_first_lookup_safe (xlator_t *subvol)  { @@ -251,33 +249,26 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,  	loc.parent = inode_ref (parent);  	gf_uuid_copy (loc.pargfid, parent->gfid); -        /* /.. and /. should point back to / -           we lookup using inode and gfid of root -           Fill loc.name so that we make use md-cache. -           md-cache is not valid for nameless lookups. -        */ +        /* At this point we should never have '.' or ".." in path */          if (__is_root_gfid (parent->gfid) && -            (strcmp (component, "..") == 0)) { -                loc.inode = inode_ref (parent); -                loc.name = "."; -        } else { -                if (strcmp (component, ".") == 0) -                        loc.inode = inode_ref (parent); -                else if (strcmp (component, "..") == 0) -                        loc.inode = inode_parent (parent, 0, 0); -                else -                        loc.inode = inode_grep (parent->table, parent, -                                                component); +            (strcmp (component, "/") == 0)) { +                if (!force_lookup) { +                        inode = inode_ref (parent); +                } else { +                        ret = glfs_resolve_base (fs, subvol, parent, &ciatt); +                        if (!ret) +                                inode = inode_ref (parent); +                } +                goto found;          } - +        loc.inode = inode_grep (parent->table, parent, component);  	if (loc.inode) {  		gf_uuid_copy (loc.gfid, loc.inode->gfid);  		reval = 1;                  if (!(force_lookup || inode_needs_lookup (loc.inode, THIS))) {  			inode = inode_ref (loc.inode); -			ciatt.ia_type = inode->ia_type;  			goto found;  		}  	} else { @@ -357,8 +348,10 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,          } else if (inode == loc.inode)                  inode_ctx_set (inode, THIS, &ctx_value);  found: -	if (inode) +	if (inode) { +                ciatt.ia_type = inode->ia_type;  		inode_lookup (inode); +        }  	if (iatt)  		*iatt = ciatt;  out: @@ -384,6 +377,7 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at,  	char       *next_component = NULL;  	int         ret = -1;  	struct iatt ciatt = {0, }; +        char        dentry_name[PATH_MAX]  = {0, };  	DECLARE_OLD_THIS;  	__GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs); @@ -414,9 +408,8 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at,  		if (parent)  			inode_unref (parent); -  		parent = inode; - +                glusterfs_normalize_dentry (&parent, &component, dentry_name);  		inode = glfs_resolve_component (fs, subvol, parent,  						component, &ciatt,  						/* force hard lookup on the last diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index 3a6464ac5e1..6f3bc535a14 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -2569,3 +2569,113 @@ inode_ctx_size (inode_t *inode)  out:          return size;  } + +static void +inode_parent_null_check(inode_t **parent, inode_t *inode, char **component) +{ +        GF_VALIDATE_OR_GOTO ("inode", inode, out); +        GF_VALIDATE_OR_GOTO ("inode", (*component), out); + +        if (!(*parent) && __is_root_gfid (inode->gfid)) { +                *parent = inode_ref (inode); +                *component = "/"; +        } +out: +        return; +} + +/* + * This function changes component name and parent inode + * if the component name is either "." or ".." + * + * @Paramas: + * Parent : Parent inode of current dentry + * component : component name that we need to test + * dentry_name : Address for memory if need to change component. + *               The caller has to preallocate this memory with + *               PATH_MAX as the size. + * + * We return the updated parent inode and component in the + * respective structures. + * + * Basic Idea of the function: + * + * Example 1 : + * Path /out_dir/dir/in_dir/. + *     In put values : + *         parent = in_dir + *         component : "." + * + *     Out put values: + *         parent : dir + *         component : "in_dir" + * + * Example 2 : + * Path /out_dir/dir/in_dir/.. + *     In put values : + *         parent = in_dir + *         component : ".." + * + *     Out put values: + *         parent : output_dir + *         component : "dir" + */ +void +glusterfs_normalize_dentry (inode_t **parent, char **component, +                          char *dentry_name) +{ +        inode_t         *temp_inode             = NULL; +        dentry_t        *dentry                 = NULL; + +        GF_VALIDATE_OR_GOTO ("inode", (*parent), out); +        GF_VALIDATE_OR_GOTO ("inode", (*component), out); +        GF_VALIDATE_OR_GOTO ("inode", (dentry_name), out); + +        /* After this point, there should not be "." or ".." +         * in the path. Dot and double dots are replaced with +         * appropriate base name and parent inode. +         */ + +        /* During the resolving, if it goes beyond the mount point +         * we do lookup on the mount itself like "/.. " will be +         * converted as "/" +         */ +        if (strcmp (*component, ".") == 0) { +                temp_inode = *parent; +                *parent = inode_parent (*parent, 0, 0); +                inode_parent_null_check (parent, temp_inode, component); +                pthread_mutex_lock (&temp_inode->table->lock); +                { +                        dentry = __dentry_search_arbit (temp_inode); +                        if (dentry) { +                                snprintf (dentry_name, PATH_MAX, "%s", +                                          dentry->name); +                                *component = dentry_name; +                        } +                } +                pthread_mutex_unlock (&temp_inode->table->lock); +                inode_unref (temp_inode); +        } else if (strcmp (*component, "..") == 0) { +                temp_inode = *parent; +                *parent = inode_parent (*parent, 0, 0); +                inode_parent_null_check (parent, temp_inode, component); +                inode_unref (temp_inode); + +                temp_inode = *parent; +                *parent = inode_parent (*parent, 0, 0); +                inode_parent_null_check (parent, temp_inode, component); +                pthread_mutex_lock (&temp_inode->table->lock); +                { +                        dentry = __dentry_search_arbit (temp_inode); +                        if (dentry) { +                                snprintf (dentry_name, PATH_MAX, "%s", +                                          dentry->name); +                                *component = dentry_name; +                        } +                } +                pthread_mutex_unlock (&temp_inode->table->lock); +                inode_unref (temp_inode); +        } +out: +        return; +} diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index cdc2095a0e8..253196378a8 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -286,4 +286,21 @@ inode_has_dentry (inode_t *inode);  size_t  inode_ctx_size (inode_t *inode); +/* + * This function is used to change the dentry from a path + * if it contains any "." or ".." . + * + * It replaces "." and ".." to proper bname after resolving + * and will change the component accordingly. + * + * This fucntion also replaces the parent inode based on the + * bname. + * + * We should give a allocated memory as a third argument to store + * the component in case if we are modifying it. + */ + +void +glusterfs_normalize_dentry (inode_t **parent, char **component, +                            char *dentry_name);  #endif /* _INODE_H */  | 
