diff mbox series

[1/3] btrfs: introduce allow_backup_super_failure sysfs interface

Message ID d3141862047ff54818407044d26e1aac93c97ed7.1695535440.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: introduce 3 debug sysfs interface to tweak the error handling behavior | expand

Commit Message

Qu Wenruo Sept. 24, 2023, 6:14 a.m. UTC
Currently btrfs allows the backup super block to fail its writeback, as
long as the primary one is still fine.

This tolerance may be a little too loose for some debug purposes, thus
this patch would introduce the following sysfs interface:

  /sys/fs/btrfs/<uuid>/debug/allow_backup_super_failure

Which is a read-write entry, its content is 0/1, indicating if we allow
backup super blocks to fail its writeback.
The default value is 1, meaning we allow backup super blocks to fail its
writeback.

Writing anything but 0 would set the value to 1.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/disk-io.c |  7 +++++--
 fs/btrfs/fs.h      |  3 +++
 fs/btrfs/sysfs.c   | 37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 45 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index dc577b3c53f6..d8eb968e9e5e 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2722,6 +2722,7 @@  void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
 	INIT_LIST_HEAD(&fs_info->allocated_roots);
 	INIT_LIST_HEAD(&fs_info->allocated_ebs);
 	spin_lock_init(&fs_info->eb_leak_lock);
+	fs_info->allow_backup_super_failure = true;
 #endif
 	extent_map_tree_init(&fs_info->mapping_tree);
 	btrfs_init_block_rsv(&fs_info->global_block_rsv,
@@ -3841,8 +3842,10 @@  static int write_dev_supers(struct btrfs_device *device,
  */
 static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
 {
+	struct btrfs_fs_info *fs_info = device->fs_info;
 	int i;
 	int errors = 0;
+	bool allow_super_failure = READ_ONCE(fs_info->allow_backup_super_failure);
 	bool primary_failed = false;
 	int ret;
 	u64 bytenr;
@@ -3890,8 +3893,8 @@  static int wait_dev_supers(struct btrfs_device *device, int max_mirrors)
 	}
 
 	/* log error, force error return */
-	if (primary_failed) {
-		btrfs_err(device->fs_info, "error writing primary super block to device %llu",
+	if (primary_failed || (!allow_super_failure && errors)) {
+		btrfs_err(device->fs_info, "error writing super block to device %llu",
 			  device->devid);
 		return -1;
 	}
diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h
index 19f9a444bcd8..2dff41cb463d 100644
--- a/fs/btrfs/fs.h
+++ b/fs/btrfs/fs.h
@@ -685,6 +685,9 @@  struct btrfs_fs_info {
 	struct btrfs_work qgroup_rescan_work;
 	/* Protected by qgroup_rescan_lock */
 	bool qgroup_rescan_running;
+
+	/* If we allow backup superblocks writeback to fail. */
+	bool allow_backup_super_failure;
 	u8 qgroup_drop_subtree_thres;
 
 	/*
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 8b75e974f30b..852090622a76 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -614,12 +614,49 @@  static const struct attribute *discard_attrs[] = {
 
 #ifdef CONFIG_BTRFS_DEBUG
 
+static ssize_t allow_backup_super_failure_show(struct kobject *debug_kobj,
+					       struct kobj_attribute *a,
+					       char *buf)
+{
+	struct btrfs_fs_info *fs_info = to_fs_info(debug_kobj->parent);
+
+	ASSERT(fs_info);
+	return sysfs_emit(buf, "%d\n",
+			  READ_ONCE(fs_info->allow_backup_super_failure));
+}
+
+static ssize_t allow_backup_super_failure_store(struct kobject *debug_kobj,
+						struct kobj_attribute *a,
+						const char *buf, size_t len)
+{
+	struct btrfs_fs_info *fs_info = to_fs_info(debug_kobj->parent);
+	u8 new_number;
+	int ret;
+
+	ASSERT(fs_info);
+
+	ret = kstrtos8(buf, 10, &new_number);
+	if (ret)
+		return -EINVAL;
+	WRITE_ONCE(fs_info->allow_backup_super_failure, !!new_number);
+	return len;
+}
+BTRFS_ATTR_RW(debug, allow_backup_super_failure, allow_backup_super_failure_show,
+	      allow_backup_super_failure_store);
+
 /*
  * Per-filesystem runtime debugging exported via sysfs.
  *
  * Path: /sys/fs/btrfs/UUID/debug/
+ *
+ * - allow_backup_super_failure
+ *   RW, binary (0/1), determins if we allow backup superblock writeback to fail.
+ *
+ *   NOTE: Even with this set to 1, btrfs may still allow some errors to
+ *	   happen as btrfs can tolerate up to "rw_devs - 1" failures.
  */
 static const struct attribute *btrfs_debug_mount_attrs[] = {
+	BTRFS_ATTR_PTR(debug, allow_backup_super_failure),
 	NULL,
 };