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