|
|
21ab4e |
From 557bb6c344247b1c4763943ec737aa6963ac5572 Mon Sep 17 00:00:00 2001
|
|
|
21ab4e |
From: Mohammed Rafi KC <rkavunga@redhat.com>
|
|
|
21ab4e |
Date: Wed, 3 May 2017 17:19:57 +0530
|
|
|
21ab4e |
Subject: [PATCH 448/473] gfapi: fix handling of dot and double dot in path
|
|
|
21ab4e |
|
|
|
21ab4e |
This patch is to handle "." and ".." in file path. Which means
|
|
|
21ab4e |
this special dentry names will be resolved before sending fops
|
|
|
21ab4e |
on the path.
|
|
|
21ab4e |
|
|
|
21ab4e |
Backport of>
|
|
|
21ab4e |
>Change-Id: I5e92f6d1ad1412bf432eb2488e53fb7731edb013
|
|
|
21ab4e |
>BUG: 1447266
|
|
|
21ab4e |
>Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
|
|
|
21ab4e |
>Reviewed-on: https://review.gluster.org/17177
|
|
|
21ab4e |
>Smoke: Gluster Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
>Reviewed-by: Niels de Vos <ndevos@redhat.com>
|
|
|
21ab4e |
>CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
>NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
>Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
|
|
|
21ab4e |
|
|
|
21ab4e |
Change-Id: I5e92f6d1ad1412bf432eb2488e53fb7731edb013
|
|
|
21ab4e |
BUG: 1441280
|
|
|
21ab4e |
Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
|
|
|
21ab4e |
Reviewed-on: https://code.engineering.redhat.com/gerrit/106338
|
|
|
21ab4e |
Reviewed-by: Poornima Gurusiddaiah <pgurusid@redhat.com>
|
|
|
21ab4e |
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
|
|
|
21ab4e |
---
|
|
|
21ab4e |
api/src/glfs-resolve.c | 41 ++++++++----------
|
|
|
21ab4e |
libglusterfs/src/inode.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
21ab4e |
libglusterfs/src/inode.h | 17 ++++++++
|
|
|
21ab4e |
3 files changed, 144 insertions(+), 24 deletions(-)
|
|
|
21ab4e |
|
|
|
21ab4e |
diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c
|
|
|
21ab4e |
index d495cd2..a2be87f 100644
|
|
|
21ab4e |
--- a/api/src/glfs-resolve.c
|
|
|
21ab4e |
+++ b/api/src/glfs-resolve.c
|
|
|
21ab4e |
@@ -25,12 +25,10 @@
|
|
|
21ab4e |
#include "syncop.h"
|
|
|
21ab4e |
#include "call-stub.h"
|
|
|
21ab4e |
#include "gfapi-messages.h"
|
|
|
21ab4e |
-
|
|
|
21ab4e |
+#include "inode.h"
|
|
|
21ab4e |
#include "glfs-internal.h"
|
|
|
21ab4e |
|
|
|
21ab4e |
#define graphid_str(subvol) (uuid_utoa((unsigned char *)subvol->graph->graph_uuid))
|
|
|
21ab4e |
-
|
|
|
21ab4e |
-
|
|
|
21ab4e |
int
|
|
|
21ab4e |
glfs_first_lookup_safe (xlator_t *subvol)
|
|
|
21ab4e |
{
|
|
|
21ab4e |
@@ -251,33 +249,26 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
|
|
|
21ab4e |
loc.parent = inode_ref (parent);
|
|
|
21ab4e |
gf_uuid_copy (loc.pargfid, parent->gfid);
|
|
|
21ab4e |
|
|
|
21ab4e |
- /* /.. and /. should point back to /
|
|
|
21ab4e |
- we lookup using inode and gfid of root
|
|
|
21ab4e |
- Fill loc.name so that we make use md-cache.
|
|
|
21ab4e |
- md-cache is not valid for nameless lookups.
|
|
|
21ab4e |
- */
|
|
|
21ab4e |
+ /* At this point we should never have '.' or ".." in path */
|
|
|
21ab4e |
if (__is_root_gfid (parent->gfid) &&
|
|
|
21ab4e |
- (strcmp (component, "..") == 0)) {
|
|
|
21ab4e |
- loc.inode = inode_ref (parent);
|
|
|
21ab4e |
- loc.name = ".";
|
|
|
21ab4e |
- } else {
|
|
|
21ab4e |
- if (strcmp (component, ".") == 0)
|
|
|
21ab4e |
- loc.inode = inode_ref (parent);
|
|
|
21ab4e |
- else if (strcmp (component, "..") == 0)
|
|
|
21ab4e |
- loc.inode = inode_parent (parent, 0, 0);
|
|
|
21ab4e |
- else
|
|
|
21ab4e |
- loc.inode = inode_grep (parent->table, parent,
|
|
|
21ab4e |
- component);
|
|
|
21ab4e |
+ (strcmp (component, "/") == 0)) {
|
|
|
21ab4e |
+ if (!force_lookup) {
|
|
|
21ab4e |
+ inode = inode_ref (parent);
|
|
|
21ab4e |
+ } else {
|
|
|
21ab4e |
+ ret = glfs_resolve_base (fs, subvol, parent, &ciatt);
|
|
|
21ab4e |
+ if (!ret)
|
|
|
21ab4e |
+ inode = inode_ref (parent);
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+ goto found;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
|
|
|
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 |
|
|
|
21ab4e |
if (!(force_lookup || inode_needs_lookup (loc.inode, THIS))) {
|
|
|
21ab4e |
inode = inode_ref (loc.inode);
|
|
|
21ab4e |
- ciatt.ia_type = inode->ia_type;
|
|
|
21ab4e |
goto found;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
} else {
|
|
|
21ab4e |
@@ -357,8 +348,10 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent,
|
|
|
21ab4e |
} else if (inode == loc.inode)
|
|
|
21ab4e |
inode_ctx_set (inode, THIS, &ctx_value);
|
|
|
21ab4e |
found:
|
|
|
21ab4e |
- if (inode)
|
|
|
21ab4e |
+ if (inode) {
|
|
|
21ab4e |
+ ciatt.ia_type = inode->ia_type;
|
|
|
21ab4e |
inode_lookup (inode);
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
if (iatt)
|
|
|
21ab4e |
*iatt = ciatt;
|
|
|
21ab4e |
out:
|
|
|
21ab4e |
@@ -384,6 +377,7 @@ 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 |
@@ -414,9 +408,8 @@ priv_glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at,
|
|
|
21ab4e |
|
|
|
21ab4e |
if (parent)
|
|
|
21ab4e |
inode_unref (parent);
|
|
|
21ab4e |
-
|
|
|
21ab4e |
parent = inode;
|
|
|
21ab4e |
-
|
|
|
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 747c1f1..90a5608 100644
|
|
|
21ab4e |
--- a/libglusterfs/src/inode.c
|
|
|
21ab4e |
+++ b/libglusterfs/src/inode.c
|
|
|
21ab4e |
@@ -2548,3 +2548,113 @@ inode_ctx_size (inode_t *inode)
|
|
|
21ab4e |
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 |
+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 |
+
|
|
|
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 |
+
|
|
|
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 |
+
|
|
|
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 |
+ }
|
|
|
21ab4e |
+ pthread_mutex_unlock (&temp_inode->table->lock);
|
|
|
21ab4e |
+ inode_unref (temp_inode);
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+out:
|
|
|
21ab4e |
+ return;
|
|
|
21ab4e |
+}
|
|
|
21ab4e |
diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h
|
|
|
21ab4e |
index 5289b15..e3c38bb 100644
|
|
|
21ab4e |
--- a/libglusterfs/src/inode.h
|
|
|
21ab4e |
+++ b/libglusterfs/src/inode.h
|
|
|
21ab4e |
@@ -282,4 +282,21 @@ 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 |
#endif /* _INODE_H */
|
|
|
21ab4e |
--
|
|
|
21ab4e |
1.8.3.1
|
|
|
21ab4e |
|