Now that sb-level/bdev-level fsfreeze integration has been achieved and sb-lebel/bdev-level freeze counters are always kept consistent, we need to unfreeze bdevs in addition to filesystems during emergency thaw so that we can recover from a situation where someone forgot to call thaw_bdev(). 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/block_dev.c linux-3.8-rc1/fs/block_dev.c --- linux-3.8-rc1-orig/fs/block_dev.c 2012-12-25 16:33:38.664018000 +0900 +++ linux-3.8-rc1/fs/block_dev.c 2012-12-25 16:34:01.900018000 +0900 @@ -254,18 +254,18 @@ out: EXPORT_SYMBOL(freeze_bdev); /** - * thaw_bdev - unlock a block device + * __thaw_bdev - unlock a block device * @bdev: blockdevice to unlock * @sb: associated superblock * * Unlocks the block device and, if present, the associated filesystem too. + * This is the unlocked version of thaw_bdev and it has to be called with + * ->bd_fsfreeze_mutex mutex taken. */ -int thaw_bdev(struct block_device *bdev, struct super_block *sb) +static int __thaw_bdev(struct block_device *bdev, struct super_block *sb) { int error = -EINVAL; - mutex_lock(&bdev->bd_fsfreeze_mutex); - if (!bdev->bd_fsfreeze_count) goto out; @@ -279,11 +279,49 @@ int thaw_bdev(struct block_device *bdev, if (error) bdev->bd_fsfreeze_count++; out: + return error; +} + +/** + * thaw_bdev -- unlock a block device + * @bdev: blockdevice to unlock + * @sb: associated superblock + * + * Unlocks the block device and, if present, the associated filesystem too. + */ +int thaw_bdev(struct block_device *bdev, struct super_block *sb) +{ + int error; + mutex_lock(&bdev->bd_fsfreeze_mutex); + error = __thaw_bdev(bdev, sb); mutex_unlock(&bdev->bd_fsfreeze_mutex); return error; } EXPORT_SYMBOL(thaw_bdev); +void do_thaw_one_bdev(struct block_device *bdev, void *arg) +{ + struct super_block *sb; + + mutex_lock(&bdev->bd_fsfreeze_mutex); + + if (!bdev->bd_fsfreeze_count) { + mutex_unlock(&bdev->bd_fsfreeze_mutex); + return; + } + + /* + * We know the block device is frozen so we do not need to grab a + * reference - the first call to thaw_bdev() dit it. + */ + if ((sb = get_super(bdev)) != NULL) + drop_super(sb); + + while (!__thaw_bdev(bdev, sb)); + + mutex_unlock(&bdev->bd_fsfreeze_mutex); +} + static int blkdev_writepage(struct page *page, struct writeback_control *wbc) { return block_write_full_page(page, blkdev_get_block, wbc); 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:33:38.664018000 +0900 +++ linux-3.8-rc1/fs/super.c 2012-12-25 16:34:01.900018000 +0900 @@ -1585,7 +1585,7 @@ int thaw_super_force(struct super_block return 0; } -static void do_thaw_one(struct super_block *sb, void *unused) +static void do_thaw_one_sb(struct super_block *sb, void *unused) { int error; @@ -1611,7 +1611,8 @@ static void do_thaw_one(struct super_blo static void do_thaw_all(struct work_struct *work) { - iterate_supers_write(do_thaw_one, NULL); + iterate_bdevs(do_thaw_one_bdev, NULL); + iterate_supers_write(do_thaw_one_sb, NULL); kfree(work); printk(KERN_WARNING "Emergency Thaw complete\n"); } 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:33:38.664018000 +0900 +++ linux-3.8-rc1/include/linux/fs.h 2012-12-25 16:34:01.904018000 +0900 @@ -2063,6 +2063,7 @@ extern int sync_blockdev(struct block_de extern void kill_bdev(struct block_device *); extern struct super_block *freeze_bdev(struct block_device *); extern int thaw_bdev(struct block_device *bdev, struct super_block *sb); +extern void do_thaw_one_bdev(struct block_device *bdev, void *arg); extern int fsync_bdev(struct block_device *); #else static inline void bd_forget(struct inode *inode) {} @@ -2080,6 +2081,10 @@ static inline int thaw_bdev(struct block return 0; } +static inline void do_thaw_one_bdev(struct block_device *bdev, void *arg) +{ +} + static inline void iterate_bdevs(void (*f)(struct block_device *, void *), void *arg) { } -- 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