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