lkml.org 
[lkml]   [2012]   [Feb]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 58/73] unionmount: Add LOOKUP_COPY_UP [ver #2]
Date
Add LOOKUP_COPY_UP as a pathwalk flag to indicate that if we hit a file on a
lower layer in the union, we definitely want it copying up.

Signed-off-by: David Howells <dhowells@redhat.com>
---

fs/namei.c | 23 +++++++++++++++++++++--
fs/union.h | 12 ++++++++++--
include/linux/namei.h | 1 +
3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index be505cd..6ec5725 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1214,6 +1214,16 @@ static int __lookup_union(struct nameidata *nd, struct qstr *name,
return 0;

out_found_file:
+ /* If the caller demands a top-level dentry then we have to copy up. */
+ if (nd->flags & LOOKUP_COPY_UP) {
+ nd->path = parent;
+ err = union_copyup_file(nd, &lower, topmost->dentry,
+ i_size_read(lower.dentry->d_inode));
+ if (err)
+ goto out_err;
+ goto out_lookup_done;
+ }
+
/* Swap out the positive lower dentry with the negative upper
* dentry for this file. Note that the matching mntput() is done
* in link_path_walk().
@@ -1350,6 +1360,15 @@ static bool lookup_union_rcu(struct nameidata *nd,
(IS_OPAQUE(parent_inode) && !d_is_fallthru(dentry)))
return true;

+ /* The dentry is a fallthru in an opaque unioned directory.
+ *
+ * If the caller demands that the terminal dentry be instantiated in
+ * the top layer of the union (copied up) immediately, that will
+ * require a mutex.
+ */
+ if (nd->flags & LOOKUP_COPY_UP)
+ return false;
+
/* At this point we have a negative dentry in the unionmount that may
* be overlaying a non-directory file in a lower filesystem, so we loop
* through the union stack of the parent directory to try to find a
@@ -1588,7 +1607,7 @@ retry:
if (err)
nd->flags |= LOOKUP_JUMPED;

- if (needs_lookup_union(&nd->path, path)) {
+ if (needs_lookup_union(nd, &nd->path, path)) {
int err = lookup_union(nd, name, path);
if (err < 0)
return err;
@@ -2147,7 +2166,7 @@ static int lookup_hash(struct nameidata *nd, struct qstr *name,
path->mnt = nd->path.mnt;
path->dentry = result;

- if (needs_lookup_union(&nd->path, path))
+ if (needs_lookup_union(nd, &nd->path, path))
return lookup_union_locked(nd, name, path);
return 0;
}
diff --git a/fs/union.h b/fs/union.h
index 62d8ef5..5c4db67 100644
--- a/fs/union.h
+++ b/fs/union.h
@@ -92,7 +92,8 @@ struct path *union_find_dir(struct dentry *dentry, unsigned int layer)
* dentry.
*/
static inline
-bool needs_lookup_union(struct path *parent_path, struct path *path)
+bool needs_lookup_union(struct nameidata *nd,
+ struct path *parent_path, struct path *path)
{
if (!IS_DIR_UNIONED(parent_path->dentry))
return false;
@@ -102,6 +103,12 @@ bool needs_lookup_union(struct path *parent_path, struct path *path)
if (IS_ROOT(path->dentry))
return false;

+ /* If this is a fallthru dentry and the caller requires the underlying
+ * inode to be copied up, then do so.
+ */
+ if (nd->flags & LOOKUP_COPY_UP && d_is_fallthru(path->dentry))
+ return true;
+
/* It's okay not to have the lock; will recheck in lookup_union() */
/* XXX set for root dentry at mount? */
return !(path->dentry->d_flags & DCACHE_UNION_LOOKUP_DONE);
@@ -134,7 +141,8 @@ static inline int union_create_topmost_dir(struct path *parent, struct qstr *nam
return 0;
}

-static inline bool needs_lookup_union(struct path *parent_path, struct path *path)
+static inline bool needs_lookup_union(struct nameidata *nd,
+ struct path *parent_path, struct path *path)
{
return false;
}
diff --git a/include/linux/namei.h b/include/linux/namei.h
index e273639..1736ece 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -65,6 +65,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
#define LOOKUP_JUMPED 0x1000
#define LOOKUP_ROOT 0x2000
#define LOOKUP_EMPTY 0x4000
+#define LOOKUP_COPY_UP 0x8000 /* Copy up from lower mount if unionmounted */

extern int user_path_at(int, const char __user *, unsigned, struct path *);
extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);


\
 
 \ /
  Last update: 2012-02-21 20:59    [W:0.217 / U:0.708 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site