[PATCH 29/41] union-mount: Always create topmost directory on open

From: Valerie Aurora
Date: Wed Oct 21 2009 - 15:24:52 EST


When we open a directory, always create a matching directory on the
top-level. This way we don't have to go back and create all the
directories on the path to an element when we want to copy it up.

XXX - Turn into #ifdef'able function

Signed-off-by: Jan Blunck <jblunck@xxxxxxx>
Signed-off-by: Valerie Aurora <vaurora@xxxxxxxxxx>
---
fs/namei.c | 34 ++++++++++++++++++++++++++++++----
1 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 1f2a214..8d95eb1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1284,8 +1284,31 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
if (err)
break;

- if ((nd->flags & LOOKUP_TOPMOST) &&
- (nd->um_flags & LAST_LOWLEVEL)) {
+ /*
+ * We want to create this element on the top level
+ * file system in two cases:
+ *
+ * - We are specifically told to - LOOKUP_TOPMOST.
+ * - This is a directory, and it does not yet exist on
+ * the top level. Various tricks only work if
+ * directories always exist on the top level.
+ *
+ * In either case, only create this element on the top
+ * level if the last element is located on the lower
+ * level. If the last element is located on the top
+ * level, then every single element in the path
+ * already exists on the top level.
+ *
+ * Note that we can assume that the parent is on the
+ * top level since we always create the directory on
+ * the top level.
+ */
+
+ if ((nd->um_flags & LAST_LOWLEVEL) &&
+ ((next.dentry->d_inode &&
+ S_ISDIR(next.dentry->d_inode->i_mode) &&
+ (nd->path.mnt != next.mnt)) ||
+ (nd->flags & LOOKUP_TOPMOST))) {
struct dentry *dentry;

dentry = union_create_topmost(nd, &this, &next);
@@ -1349,8 +1372,11 @@ last_component:
if (err)
break;

- if ((nd->flags & LOOKUP_TOPMOST) &&
- (nd->um_flags & LAST_LOWLEVEL)) {
+ if ((nd->um_flags & LAST_LOWLEVEL) &&
+ ((next.dentry->d_inode &&
+ S_ISDIR(next.dentry->d_inode->i_mode) &&
+ (nd->path.mnt != next.mnt)) ||
+ (nd->flags & LOOKUP_TOPMOST))) {
struct dentry *dentry;

dentry = union_create_topmost(nd, &this, &next);
--
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/