lkml.org 
[lkml]   [2009]   [May]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[patch 4/5] union-directory: Make lookup continue in overlayed directories
From: Jan Blunck <jblunck@suse.de>

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@suse.de>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
---
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;

--


\
 
 \ /
  Last update: 2009-05-21 11:27    [W:0.049 / U:0.264 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site