From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Josef 'Jeff' Sipek" Subject: [PATCH 16/21] Unionfs: unionfs_create needs to revalidate the dentry Date: Mon, 9 Apr 2007 10:54:07 -0400 Message-ID: <1176130455792-git-send-email-jsipek@cs.sunysb.edu> References: <11761304521844-git-send-email-jsipek@cs.sunysb.edu> Cc: akpm@linux-foundation.org, Erez Zadok , "Josef 'Jeff' Sipek" To: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Return-path: In-Reply-To: <11761304521844-git-send-email-jsipek@cs.sunysb.edu> Sender: linux-kernel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org From: Erez Zadok We have to read-lock the superblock rwsem, and we have to revalidate the parent dentry and this one. A branch-management operation could have taken place, mid-way through a VFS operation that eventually reaches unionfs_create(). So we have to ensure consistency, just as we do with the file operations. Signed-off-by: Erez Zadok Signed-off-by: Josef 'Jeff' Sipek --- fs/unionfs/inode.c | 29 ++++++++++++++++++++++++++++- 1 files changed, 28 insertions(+), 1 deletions(-) diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c index 6dfc16f..edd226f 100644 --- a/fs/unionfs/inode.c +++ b/fs/unionfs/inode.c @@ -28,9 +28,35 @@ static int unionfs_create(struct inode *parent, struct dentry *dentry, struct dentry *hidden_parent_dentry = NULL; int bindex = 0, bstart; char *name = NULL; - + int valid = 0; + + /* + * We have to read-lock the superblock rwsem, and we have to + * revalidate the parent dentry and this one. A branch-management + * operation could have taken place, mid-way through a VFS operation + * that eventually reaches here. So we have to ensure consistency, + * just as we do with the file operations. + * + * XXX: we may need to do this for all other inode ops that take a + * dentry. + */ + unionfs_read_lock(dentry->d_sb); unionfs_lock_dentry(dentry); + unionfs_lock_dentry(dentry->d_parent); + valid = __unionfs_d_revalidate_chain(dentry->d_parent, nd); + unionfs_unlock_dentry(dentry->d_parent); + if (!valid) { + err = -ENOENT; /* same as what real_lookup does */ + goto out; + } + valid = __unionfs_d_revalidate_chain(dentry, nd); + /* + * It's only a bug if this dentry was not negative and couldn't be + * revalidated (shouldn't happen). + */ + BUG_ON(!valid && dentry->d_inode); + /* We start out in the leftmost branch. */ bstart = dbstart(dentry); hidden_dentry = unionfs_lower_dentry(dentry); @@ -184,6 +210,7 @@ out: kfree(name); unionfs_unlock_dentry(dentry); + unionfs_read_unlock(dentry->d_sb); return err; } -- 1.5.0.3.268.g3dda