GIT: unionfs2-2.6.27.y: bugfix: ensure dentry/inode/mnt validity after a successful ioctl
Erez Zadok
ezk at fsl.cs.sunysb.edu
Thu Aug 12 23:16:33 EDT 2010
commit a855ca7e3d8f6f1d14411525050e2c1d169003f3
Author: Erez_Zadok <ezk at cs.sunysb.edu>
Date: Wed May 30 20:14:07 2007 -0400
bugfix: ensure dentry/inode/mnt validity after a successful ioctl
We call unionfs_partial_lookup in our queryfile ioctl method, so we can find
all instances of a lower object to report back to a suer. This can violate
the fanout invariants (e.g., a regular file should have only one lower
object active at a time). So we have to re-establish the invariants on the
lower dentries, inodes, and mnts.
Signed-off-by: Erez Zadok <ezk at cs.sunysb.edu>
diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index b730934..427f70b 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -686,10 +686,14 @@ static int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd,
int err = 0;
fd_set branchlist;
int bstart = 0, bend = 0, bindex = 0;
+ int orig_bstart, orig_bend;
struct dentry *dentry, *hidden_dentry;
+ struct vfsmount *mnt;
dentry = file->f_dentry;
unionfs_lock_dentry(dentry);
+ orig_bstart = dbstart(dentry);
+ orig_bend = dbend(dentry);
if ((err = unionfs_partial_lookup(dentry)))
goto out;
bstart = dbstart(dentry);
@@ -703,7 +707,24 @@ static int unionfs_ioctl_queryfile(struct file *file, unsigned int cmd,
continue;
if (hidden_dentry->d_inode)
FD_SET(bindex, &branchlist);
+ /* purge any lower objects after partial_lookup */
+ if (bindex < orig_bstart || bindex > orig_bend) {
+ dput(hidden_dentry);
+ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
+ iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
+ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
+ NULL);
+ mnt = unionfs_lower_mnt_idx(dentry, bindex);
+ if (!mnt)
+ continue;
+ unionfs_mntput(dentry, bindex);
+ unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
+ }
}
+ /* restore original dentry's offsets */
+ set_dbstart(dentry, orig_bstart);
+ set_dbend(dentry, orig_bend);
+ ibstart(dentry->d_inode) = ibend(dentry->d_inode) = orig_bend;
err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set));
if (err)
More information about the unionfs-cvs
mailing list