[PATCH] btrfs-progs: rescue-zero-log: Modify super block directly

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

 



For log zeroing, we only need to reset log_root and log_root_level to 0.

However current zero-log still goes full open_ctree() which can be
rejected easily by extent tree corruption.

So this patch will change the behavior to modifying super block
directly, avoid any possible rejection from open_ctree()

Reported-by: Christian Pernegger <pernegger@xxxxxxxxx>
Signed-off-by: Qu Wenruo <wqu@xxxxxxxx>
---
 cmds/rescue.c | 48 ++++++++++++++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/cmds/rescue.c b/cmds/rescue.c
index e8eab6808bc3..3e2dedf04fda 100644
--- a/cmds/rescue.c
+++ b/cmds/rescue.c
@@ -19,6 +19,9 @@
 #include "kerncompat.h"
 
 #include <getopt.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
 #include "ctree.h"
 #include "volumes.h"
 #include "transaction.h"
@@ -164,10 +167,11 @@ static const char * const cmd_rescue_zero_log_usage[] = {
 static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
 			       int argc, char **argv)
 {
-	struct btrfs_root *root;
-	struct btrfs_trans_handle *trans;
-	struct btrfs_super_block *sb;
 	char *devname;
+	u8 buf[BTRFS_SUPER_INFO_SIZE];
+	u8 result[BTRFS_CSUM_SIZE];
+	struct btrfs_super_block *sb = (struct btrfs_super_block *)buf;
+	int fd;
 	int ret;
 
 	clean_args_no_options(cmd, argc, argv);
@@ -187,24 +191,44 @@ static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
 		goto out;
 	}
 
-	root = open_ctree(devname, 0, OPEN_CTREE_WRITES | OPEN_CTREE_PARTIAL);
-	if (!root) {
-		error("could not open ctree");
-		return 1;
+	fd = open(devname, O_RDWR);
+	if (fd < 0) {
+		ret = -errno;
+		error("failed to open '%s': %m", devname);
+		goto out;
+	}
+	/*
+	 * Log tree only exists in the primary super block, so SBREAD_DEFAULT
+	 * is enough.
+	 */
+	ret = btrfs_read_dev_super(fd, sb, BTRFS_SUPER_INFO_OFFSET,
+				   SBREAD_DEFAULT);
+	if (ret < 0) {
+		errno = -ret;
+		error("failed to read super block on '%s': %m", devname);
+		goto close_fd;
 	}
 
-	sb = root->fs_info->super_copy;
 	printf("Clearing log on %s, previous log_root %llu, level %u\n",
 			devname,
 			(unsigned long long)btrfs_super_log_root(sb),
 			(unsigned)btrfs_super_log_root_level(sb));
-	trans = btrfs_start_transaction(root, 1);
-	BUG_ON(IS_ERR(trans));
 	btrfs_set_super_log_root(sb, 0);
 	btrfs_set_super_log_root_level(sb, 0);
-	btrfs_commit_transaction(trans, root);
-	close_ctree(root);
+	btrfs_csum_data(btrfs_super_csum_type(sb), (u8 *)sb + BTRFS_CSUM_SIZE,
+			result, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
+	memcpy(&sb->csum[0], result, BTRFS_CSUM_SIZE);
+	ret = pwrite64(fd, sb, BTRFS_SUPER_INFO_SIZE, BTRFS_SUPER_INFO_OFFSET);
+	if (ret != BTRFS_SUPER_INFO_SIZE) {
+		ret = -EIO;
+		errno = -ret;
+		error("failed to write super block for '%s': %m", devname);
+	} else {
+		ret = 0;
+	}
 
+close_fd:
+	close(fd);
 out:
 	return !!ret;
 }
-- 
2.23.0




[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux