Pass nameidata structures as needed to the lower file system, support LOOKUP_ACCESS/OPEN intents. This makes unionfs work on top of nfsv4. Signed-off-by: Erez Zadok <ezk@xxxxxxxxxxxxx> Acked-by: Josef 'Jeff' Sipek <jsipek@xxxxxxxxxxxxx> --- fs/unionfs/dentry.c | 11 +++++++++-- fs/unionfs/inode.c | 8 +++++++- fs/unionfs/lookup.c | 20 +++++++++++++++++--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c index b21f1e3..52bcb18 100644 --- a/fs/unionfs/dentry.c +++ b/fs/unionfs/dentry.c @@ -156,8 +156,15 @@ static bool __unionfs_d_revalidate_one(struct dentry *dentry, if (!lower_dentry || !lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) continue; - if (!lower_dentry->d_op->d_revalidate(lower_dentry, - &lowernd)) + /* + * Don't pass nameidata to lower file system, because we + * don't want an arbitrary lower file being opened or + * returned to us: it may be useless to us because of the + * fanout nature of unionfs (cf. file/directory open-file + * invariants). We will open lower files as and when needed + * later on. + */ + if (!lower_dentry->d_op->d_revalidate(lower_dentry, NULL)) valid = false; } diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c index f8b2c88..7ee4760 100644 --- a/fs/unionfs/inode.c +++ b/fs/unionfs/inode.c @@ -27,6 +27,7 @@ static int unionfs_create(struct inode *parent, struct dentry *dentry, struct dentry *lower_parent_dentry = NULL; char *name = NULL; int valid = 0; + struct nameidata lower_nd; unionfs_read_lock(dentry->d_sb); unionfs_lock_dentry(dentry); @@ -113,7 +114,12 @@ static int unionfs_create(struct inode *parent, struct dentry *dentry, goto out; } - err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd); + err = init_lower_nd(&lower_nd, LOOKUP_CREATE); + if (err < 0) + goto out; + err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, + &lower_nd); + release_lower_nd(&lower_nd, err); if (!err) { err = PTR_ERR(unionfs_interpose(dentry, parent->i_sb, 0)); diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c index 963d622..2109714 100644 --- a/fs/unionfs/lookup.c +++ b/fs/unionfs/lookup.c @@ -583,6 +583,11 @@ void update_bstart(struct dentry *dentry) * Inside that nd structure, this function may also return an allocated * struct file (for open intents). The caller, when done with this nd, must * kfree the intent file (using release_lower_nd). + * + * XXX: this code, and the callers of this code, should be redone using + * vfs_path_lookup() when (1) the nameidata structure is refactored into a + * separate intent-structure, and (2) open_namei() is broken into a VFS-only + * function and a method that other file systems can call. */ int init_lower_nd(struct nameidata *nd, unsigned int flags) { @@ -597,11 +602,16 @@ int init_lower_nd(struct nameidata *nd, unsigned int flags) #endif /* ALLOC_LOWER_ND_FILE */ memset(nd, 0, sizeof(struct nameidata)); + if (!flags) + return err; switch (flags) { case LOOKUP_CREATE: - nd->flags = LOOKUP_CREATE; - nd->intent.open.flags = FMODE_READ | FMODE_WRITE | O_CREAT; + nd->intent.open.flags |= O_CREAT; + /* fall through: shared code for create/open cases */ + case LOOKUP_OPEN: + nd->flags = flags; + nd->intent.open.flags |= (FMODE_READ | FMODE_WRITE); #ifdef ALLOC_LOWER_ND_FILE file = kzalloc(sizeof(struct file), GFP_KERNEL); if (!file) { @@ -611,11 +621,15 @@ int init_lower_nd(struct nameidata *nd, unsigned int flags) nd->intent.open.file = file; #endif /* ALLOC_LOWER_ND_FILE */ break; + case LOOKUP_ACCESS: + nd->flags = flags; + break; default: /* * We should never get here, for now. * We can add new cases here later on. */ + dprintk("unionfs: unknown nameidata flag 0x%x\n", flags); BUG(); break; } @@ -627,7 +641,7 @@ void release_lower_nd(struct nameidata *nd, int err) { if (!nd->intent.open.file) return; - if (!err) + else if (!err) release_open_intent(nd); #ifdef ALLOC_LOWER_ND_FILE kfree(nd->intent.open.file); -- 1.5.2.2 - 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