[PATCH 13/17] fsfreeze: unfreeze bdevs in addition to filesystems during emergency thaw

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

 



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


[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