From: Erez Zadok Date: Fri, 23 Mar 2007 00:01:56 +0000 (-0400) Subject: Unionfs: unionfs_create needs to revalidate the dentry X-Git-Tag: unionfs-2.1.1~176 X-Git-Url: https://git.fsl.cs.sunysb.edu/?a=commitdiff_plain;h=aa50f98a0d9e04404098d178db17b422c22c1b1c;p=unionfs-2.6.37.y.git Unionfs: unionfs_create needs to revalidate the dentry 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 --- diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c index 6dfc16f29d0..edd226f5d29 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; }