[patch 4/5] union-directory: Make lookup continue in overlayed directories

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jan Blunck <jblunck@xxxxxxx>

This patch lets adds support for union-directory lookup to lookups from dentry
cache and real lookups. On union-directories a lookup must continue on
overlayed directories of the union. The lookup continues until the first
no-negative dentry is found. Otherwise the topmost negative dentry is
returned.

Signed-off-by: Jan Blunck <jblunck@xxxxxxx>
Signed-off-by: Miklos Szeredi <mszeredi@xxxxxxx>
---
 fs/namei.c |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

Index: linux-2.6/fs/namei.c
===================================================================
--- linux-2.6.orig/fs/namei.c	2009-05-20 15:05:15.000000000 +0200
+++ linux-2.6/fs/namei.c	2009-05-20 15:10:09.000000000 +0200
@@ -34,6 +34,7 @@
 #include <linux/device_cgroup.h>
 #include <linux/fs_struct.h>
 #include <asm/uaccess.h>
+#include "union.h"
 
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
@@ -778,6 +779,49 @@ static __always_inline void follow_dotdo
 	follow_mount(&nd->path.mnt, &nd->path.dentry);
 }
 
+static int do_lookup_union(struct nameidata *nd, struct qstr *name,
+			   struct path *path)
+{
+	int err;
+	struct path save;
+
+	save = nd->path;
+	path_get(&save);
+	while (follow_union_up(&nd->path)) {
+		struct dentry *dentry;
+
+		dentry = d_hash_and_lookup(nd->path.dentry, name);
+		if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
+			dentry = do_revalidate(dentry, nd);
+			err = PTR_ERR(dentry);
+			if (IS_ERR(dentry))
+				goto out;
+		}
+		if (!dentry) {
+			dentry = real_lookup(nd->path.dentry, name, nd);
+			err = PTR_ERR(dentry);
+			if (IS_ERR(dentry))
+				goto out;
+		}
+		if (dentry->d_inode) {
+			dput(path->dentry);
+			path->dentry = dentry;
+			path->mnt = mntget(nd->path.mnt);
+			follow_mount(&path->mnt, &path->dentry);
+			err = 0;
+			goto out;
+		}
+		dput(dentry);
+	}
+	__follow_mount(path);
+	err = 0;
+out:
+	path_put(&nd->path);
+	nd->path = save;
+
+	return err;
+}
+
 /*
  *  It's more convoluted than I'd like it to be, but... it's still fairly
  *  small and for now I'd prefer to have fast path as straight as possible.
@@ -796,6 +840,11 @@ static int do_lookup(struct nameidata *n
 done:
 	path->mnt = mnt;
 	path->dentry = dentry;
+	if (IS_MNT_UNION(mnt) && !dentry->d_inode &&
+	    nd->path.dentry == nd->path.mnt->mnt_root) {
+		return do_lookup_union(nd, name, path);
+	}
+
 	__follow_mount(path);
 	return 0;
 

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

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux