commit 19a2b51bb83807c98056a841f85943afa48cc68b
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Tue May 22 16:08:01 2007 -0400

    rename bug:
    
    if the dst dentry exists at the start of the rename, then at the end
    we need to purge its inode's lower inode pointers if it is not used
    by anyone else, since it might remain in the cache and the odf might
    give this inode number to a new inode, resulting in the new inode
    having the old inode's pointers.

diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
index b5ebc5a..f0896bc 100644
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -415,32 +415,31 @@ out:
                        atomic_dec(&UNIONFS_D(old_dentry)->generation);
                else
                        unionfs_purge_extras(old_dentry);
-               if (new_dentry->d_inode &&
-                   !S_ISDIR(new_dentry->d_inode->i_mode)) {
-                       unionfs_purge_extras(new_dentry);
-                       unionfs_inherit_mnt(new_dentry);
-                       if (!unionfs_lower_inode(new_dentry->d_inode)) {
-                               /*
-                                * If we get here, it means that no copyup
-                                * was needed, and that a file by the old
-                                * name already existing on the destination
-                                * branch; that file got renamed earlier in
-                                * this function, so all we need to do here
-                                * is set the lower inode.
-                                */
-                               struct inode *inode;
-                               inode = 
unionfs_lower_inode(old_dentry->d_inode);
-                               atomic_inc(&inode->i_count);
-                               unionfs_set_lower_inode_idx(
-                                       new_dentry->d_inode,
-                                       dbstart(new_dentry), inode);
-                       }
 
+               /* If the dentry already existed before the rename and is not 
used
+                * by anyone else, we must purge its lower pointers, since it 
might
+                * remain in the cache for a while and the odf might give the 
same
+                * inode number to a new inode, so we don't want the new inode 
to
+                * have the old inode's pointers.
+                *
+                * If its i_count >= 2 we must not modify its lower pointers. 
The
+                * odf will silly rename this inode so it doesn't give it to 
another
+                * inode
+                */
+               if (new_dentry->d_inode && 
+                       atomic_read(&new_dentry->d_inode->i_count) < 2) {
+                       int bindex;
+                       struct inode *i = new_dentry->d_inode;
+                       for (bindex = ibstart(i); bindex <= ibend(i); bindex++) 
{
+                               if (unionfs_lower_inode_idx(i, bindex)) 
+                                       iput(unionfs_lower_inode_idx(i, 
bindex));
+                               unionfs_set_lower_inode_idx(i, bindex, NULL);
+                       }
                }
+
                unionfs_check_inode(old_dir);
                unionfs_check_inode(new_dir);
                unionfs_check_dentry(old_dentry);
-               unionfs_check_dentry(new_dentry);
        }
 
        unionfs_unlock_dentry(new_dentry);
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to