summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/src/glfs-resolve.c41
-rw-r--r--libglusterfs/src/inode.c110
-rw-r--r--libglusterfs/src/inode.h17
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 */