GIT: unionfs2-2.6.27.y: bug fix: prevent self deadlock with remount code in pivot_root scenarios

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


commit f6c75cfa4b142befcd83a986d645cfa0605f45e1
Author: Erez Zadok <ezk at bigvaio.(none)>
Date:   Tue May 22 23:50:44 2007 -0400

    bug fix: prevent self deadlock with remount code in pivot_root scenarios
    
    Signed-off-by: Erez Zadok <ezk at cs.sunysb.edu>

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index fcdd739..dfe516e 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -967,7 +967,23 @@ static int unionfs_permission(struct inode *inode, int mask,
 	const int is_file = !S_ISDIR(inode->i_mode);
 	const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);
 
-	unionfs_read_lock(inode->i_sb);
+	/*
+	 * If the same process which is pivot_root'ed on a unionfs, tries to
+	 * insert a new branch, then the caller (remount code) already has
+	 * the write lock on this rwsem.  It then calls here to check the
+	 * permission of a new branch to add.  It could get into a self
+	 * deadlock with this attempt to get the read lock (which is crucial
+	 * for dynamic branch-management) unless no one else is waiting on
+	 * this lock.  Essentially this test tries to figure out if the same
+	 * process which also holds a write lock on the rwsem, also tries to
+	 * grab a read lock, and then skip trying to grab this "harmless"
+	 * read lock; otherwise we DO want to grab the read lock, and block
+	 * as needed (dynamic branch management).  (BTW, if there's a better
+	 * way to find out who is the lock owner compared to "current", that
+	 * should be used instead.)
+	 */
+	if (!list_empty(&UNIONFS_SB(inode->i_sb)->rwsem.wait_list))
+		unionfs_read_lock(inode->i_sb);
 
 	bstart = ibstart(inode);
 	bend = ibend(inode);
@@ -1021,7 +1037,8 @@ static int unionfs_permission(struct inode *inode, int mask,
 	}
 
 out:
-	unionfs_read_unlock(inode->i_sb);
+	if (!list_empty(&UNIONFS_SB(inode->i_sb)->rwsem.wait_list))
+		unionfs_read_unlock(inode->i_sb);
 	unionfs_check_inode(inode);
 	return err;
 }


More information about the unionfs-cvs mailing list