Linux-BTRFS Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH] btrfs-progs: rescue-zero-log: Modify super block directly
@ 2019-10-26 10:11 Qu Wenruo
  2019-11-01 10:52 ` David Sterba
  0 siblings, 1 reply; 4+ messages in thread
From: Qu Wenruo @ 2019-10-26 10:11 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Christian Pernegger

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@gmail.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] btrfs-progs: rescue-zero-log: Modify super block directly
  2019-10-26 10:11 [PATCH] btrfs-progs: rescue-zero-log: Modify super block directly Qu Wenruo
@ 2019-11-01 10:52 ` David Sterba
  2019-11-01 10:56   ` Qu WenRuo
  0 siblings, 1 reply; 4+ messages in thread
From: David Sterba @ 2019-11-01 10:52 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs, Christian Pernegger

On Sat, Oct 26, 2019 at 06:11:27PM +0800, Qu Wenruo wrote:
> +	/*
> +	 * Log tree only exists in the primary super block, so SBREAD_DEFAULT
> +	 * is enough.

For read it should be enough to read the default one, but do you mean
that 1st and 2nd copy don't have the log_root values set? They're
written from the same buffer so I'd expect the contents to be the same.

> +	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);

So this only writes on the one device that's passed to the command.
Previously it would update superblocks on all devices.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] btrfs-progs: rescue-zero-log: Modify super block directly
  2019-11-01 10:52 ` David Sterba
@ 2019-11-01 10:56   ` Qu WenRuo
  2019-11-01 11:08     ` David Sterba
  0 siblings, 1 reply; 4+ messages in thread
From: Qu WenRuo @ 2019-11-01 10:56 UTC (permalink / raw)
  To: dsterba, linux-btrfs, Christian Pernegger



On 2019/11/1 下午6:52, David Sterba wrote:
> On Sat, Oct 26, 2019 at 06:11:27PM +0800, Qu Wenruo wrote:
>> +	/*
>> +	 * Log tree only exists in the primary super block, so SBREAD_DEFAULT
>> +	 * is enough.
> 
> For read it should be enough to read the default one, but do you mean
> that 1st and 2nd copy don't have the log_root values set? They're
> written from the same buffer so I'd expect the contents to be the same.

Log tree update only happens for primary sb.

The kernel code has this:

btrfs_sync_log()
|- ret = write_all_supers(fs_info, 1)
   |- write_dev_supers(max_mirrors); # max_mirrors == 1
      |- for (i = 0; i < max_mirrors; i++)

> 
>> +	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);
> 
> So this only writes on the one device that's passed to the command.
> Previously it would update superblocks on all devices.

Oh, you got me.

That's indeed the case. I guess we need to do the same skip_bg behavior
just like kernel to handle multiple devices.

Thanks,
Qu

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] btrfs-progs: rescue-zero-log: Modify super block directly
  2019-11-01 10:56   ` Qu WenRuo
@ 2019-11-01 11:08     ` David Sterba
  0 siblings, 0 replies; 4+ messages in thread
From: David Sterba @ 2019-11-01 11:08 UTC (permalink / raw)
  To: Qu WenRuo; +Cc: dsterba, linux-btrfs, Christian Pernegger

On Fri, Nov 01, 2019 at 10:56:36AM +0000, Qu WenRuo wrote:
> >> +	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);
> > 
> > So this only writes on the one device that's passed to the command.
> > Previously it would update superblocks on all devices.
> 
> Oh, you got me.
> 
> That's indeed the case. I guess we need to do the same skip_bg behavior
> just like kernel to handle multiple devices.

In progs we can add another mode for open_ctree to open only devices,
then iterate over their superblocks and update it in place.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, back to index

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-26 10:11 [PATCH] btrfs-progs: rescue-zero-log: Modify super block directly Qu Wenruo
2019-11-01 10:52 ` David Sterba
2019-11-01 10:56   ` Qu WenRuo
2019-11-01 11:08     ` David Sterba

Linux-BTRFS Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-btrfs/0 linux-btrfs/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-btrfs linux-btrfs/ https://lore.kernel.org/linux-btrfs \
		linux-btrfs@vger.kernel.org
	public-inbox-index linux-btrfs

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-btrfs


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git