[PATCH 16/17] fsfreeze: allow freeze counter lock nesting

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A side effect of adding support for multi-device filesystem to the bdev level
API is that we can have nested calls to thaw_super() from the bdev layer (for
example, the user may try to dm-snapshot all the devices of a btrfs filesystem
at the same time), which means that the lock for the sb-level freeze counter
needs to become a counter.
 
Cc: linux-fsdevel@xxxxxxxxxxxxxxx
Cc: Josef Bacik <jbacik@xxxxxxxxxxxx>
Cc: Eric Sandeen <sandeen@xxxxxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx>
Cc: Dave Chinner <dchinner@xxxxxxxxxx> 
Cc: Jan Kara <jack@xxxxxxx>
Cc: Luiz Capitulino <lcapitulino@xxxxxxxxxx>
Signed-off-by: Fernando Luis Vazquez Cao <fernando@xxxxxxxxxxxxx>
---

diff -urNp linux-3.8-rc1-orig/fs/super.c linux-3.8-rc1/fs/super.c
--- linux-3.8-rc1-orig/fs/super.c	2012-12-25 16:37:51.172018000 +0900
+++ linux-3.8-rc1/fs/super.c	2012-12-25 16:55:22.240018000 +0900
@@ -1346,24 +1346,19 @@ static void sb_wait_write(struct super_b
  * freezing. Then we transition to SB_FREEZE_COMPLETE state. This state is
  * mostly auxiliary for filesystems to verify they do not modify frozen fs.
  *
- * sb->s_writers.frozen, sb->s_freeze_count and sb->s_freeze_locked are
+ * sb->s_writers.frozen, sb->s_freeze_count and sb->s_freeze_lock_count are
  * protected by sb->s_umount.
  */
 int __freeze_super(struct super_block *sb, bool lock)
 {
 	int ret = 0;
-	bool locked_old = sb->s_freeze_locked;
+	int lock_count_old = sb->s_freeze_lock_count;
 
 	atomic_inc(&sb->s_active);
 	down_write(&sb->s_umount);
 
-	/* The freeze counter lock does not nest. */
-	if (sb->s_freeze_locked && lock) {
-		ret = -EBUSY;
-		goto out_deactivate;
-	}
-
-	sb->s_freeze_locked = lock ? true : sb->s_freeze_locked;
+	if (lock)
+		sb->s_freeze_lock_count++;
 	if (++sb->s_freeze_count > 1)
 		goto out_deactivate;
 
@@ -1411,7 +1406,7 @@ int __freeze_super(struct super_block *s
 		if (ret) {
 			printk(KERN_ERR
 				"VFS:Filesystem freeze failed\n");
-			sb->s_freeze_locked = locked_old;
+			sb->s_freeze_lock_count = lock_count_old;
 			sb->s_freeze_count--;
 			sb->s_writers.frozen = SB_UNFROZEN;
 			smp_wmb();
@@ -1507,7 +1502,7 @@ int __thaw_super(struct super_block *sb,
 	 * An unfrozen filesystem cannot be thawed. Similarly, an unlocked
 	 * freeze counter cannot be unlocked.
 	 */
-	if (!sb->s_freeze_count || (!sb->s_freeze_locked && unlock)) {
+	if (!sb->s_freeze_count || (!sb->s_freeze_lock_count && unlock)) {
 		error = -EINVAL;
 		goto out_unlock;
 	}
@@ -1517,12 +1512,13 @@ int __thaw_super(struct super_block *sb,
 	 * trigger the actual filesystem thaw.
 	 */
 	if (sb->s_freeze_count > 1) {
+		if (unlock)
+			sb->s_freeze_lock_count--;
 		sb->s_freeze_count--;
-		sb->s_freeze_locked = unlock ? false: sb->s_freeze_locked;
 		goto out_unlock;
 	}
 	/* A locked filesystem cannot be thawed unless unlock was requested. */
-	else if (sb->s_freeze_locked && !unlock) {
+	else if (sb->s_freeze_lock_count && !unlock) {
 		error = -EINVAL;
 		goto out_unlock;
 	}
@@ -1531,7 +1527,7 @@ int __thaw_super(struct super_block *sb,
 
 	if (!error) {
 		sb->s_freeze_count = 0;
-		sb->s_freeze_locked = false;
+		sb->s_freeze_lock_count = 0;
 	}
 	else
 		goto out_unlock;
@@ -1577,9 +1573,9 @@ int thaw_super_force(struct super_block
 		return -EINVAL;
 	}
 
-	if (sb->s_freeze_locked) {
+	if (sb->s_freeze_lock_count) {
 		/* Ensure superblock gets thawed at unlock time */
-		sb->s_freeze_count = 1;
+		sb->s_freeze_count = sb->s_freeze_lock_count;
 		up_write(&sb->s_umount);
 		return -EINVAL;
 	}
diff -urNp linux-3.8-rc1-orig/include/linux/fs.h linux-3.8-rc1/include/linux/fs.h
--- linux-3.8-rc1-orig/include/linux/fs.h	2012-12-25 16:35:43.104018000 +0900
+++ linux-3.8-rc1/include/linux/fs.h	2012-12-25 16:55:22.244018000 +0900
@@ -1325,7 +1325,7 @@ struct super_block {
 	int s_freeze_count;
 
 	/* Is freeze state locked? */
-	bool s_freeze_locked;
+	int s_freeze_lock_count;
 };
 
 /* superblock cache pruning functions */


--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux