GIT: unionfs2-2.6.27.y: Unionfs: create whiteout in correct dir after rename with copyup

Erez Zadok ezk at fsl.cs.sunysb.edu
Thu Aug 12 23:18:13 EDT 2010


commit 33d27dee23c5d6f0deffcc90d3f70ee657b6dfcb
Author: Erez Zadok <ezk at cs.sunysb.edu>
Date:   Sun Jan 18 21:01:41 2009 -0500

    Unionfs: create whiteout in correct dir after rename with copyup
    
    Fixes bug #625: a file renamed/moved into a directory, if resulted in a
    copyup with a whiteout creation, could cause the whiteout to be created in
    the wrong dir.
    
    Signed-off-by: Erez Zadok <ezk at cs.sunysb.edu>

diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
index 800d9ee..92f0407 100644
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -162,7 +162,7 @@ static int do_unionfs_rename(struct inode *old_dir,
 			     struct dentry *new_parent)
 {
 	int err = 0;
-	int bindex, bwh_old;
+	int bindex;
 	int old_bstart, old_bend;
 	int new_bstart, new_bend;
 	int do_copyup = -1;
@@ -171,7 +171,6 @@ static int do_unionfs_rename(struct inode *old_dir,
 	int revert = 0;
 
 	old_bstart = dbstart(old_dentry);
-	bwh_old = old_bstart;
 	old_bend = dbend(old_dentry);
 
 	new_bstart = dbstart(new_dentry);
@@ -242,7 +241,19 @@ static int do_unionfs_rename(struct inode *old_dir,
 			/* if copyup failed, try next branch to the left */
 			if (err)
 				continue;
-			bwh_old = bindex;
+			/*
+			 * create whiteout before calling __unionfs_rename
+			 * because the latter will change the old_dentry's
+			 * lower name and parent dir, resulting in the
+			 * whiteout getting created in the wrong dir.
+			 */
+			err = create_whiteout(old_dentry, bindex);
+			if (err) {
+				printk(KERN_ERR "unionfs: can't create a "
+				       "whiteout for %s in rename (err=%d)\n",
+				       old_dentry->d_name.name, err);
+				continue;
+			}
 			err = __unionfs_rename(old_dir, old_dentry, old_parent,
 					       new_dir, new_dentry, new_parent,
 					       bindex);
@@ -260,16 +271,10 @@ static int do_unionfs_rename(struct inode *old_dir,
 	/*
 	 * Create whiteout for source, only if:
 	 * (1) There is more than one underlying instance of source.
-	 * (2) We did a copy_up
+	 * (We did a copy_up is taken care of above).
 	 */
-	if ((old_bstart != old_bend) || (do_copyup != -1)) {
-		if (bwh_old < 0) {
-			printk(KERN_ERR "unionfs: rename error (bwh_old=%d)\n",
-			       bwh_old);
-			err = -EIO;
-			goto out;
-		}
-		err = create_whiteout(old_dentry, bwh_old);
+	if ((old_bstart != old_bend) && (do_copyup == -1)) {
+		err = create_whiteout(old_dentry, old_bstart);
 		if (err) {
 			/* can't fix anything now, so we exit with -EIO */
 			printk(KERN_ERR "unionfs: can't create a whiteout for "


More information about the unionfs-cvs mailing list