commit 7de01cabadbb93cc5ed7aecd76150eb59be783b5
Author: Erez_Zadok <[EMAIL PROTECTED]>
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 <[EMAIL PROTECTED]>

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index 
db77412ddf550bb9dc0cf35087559f1ad4845f65..8ef583684d7699fa0f0ddb6db6bfbac325962e48
 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -757,10 +757,14 @@ static int unionfs_ioctl_queryfile(struc
        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);
@@ -774,7 +778,24 @@ static int unionfs_ioctl_queryfile(struc
                        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)
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to