public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: linux-btrfs@vger.kernel.org
Subject: [PATCH 2/3] btrfs-progs: disk-io: Handle backup root more correctly
Date: Mon, 21 Oct 2019 17:37:54 +0800	[thread overview]
Message-ID: <20191021093755.56835-3-wqu@suse.com> (raw)
In-Reply-To: <20191021093755.56835-1-wqu@suse.com>

Current backup root handling has extra check on super generation:

static int find_best_backup_root(struct btrfs_super_block *super)
{
	u64 orig_gen = btrfs_super_generation(super);
...
		if (btrfs_backup_tree_root_gen(backup) != orig_gen &&
 		    btrfs_backup_tree_root_gen(backup) > gen) {
 			best_index = i;
 			gen = btrfs_backup_tree_root_gen(backup);

This check is to ensure we don't get backup root with current
generation, but it can still return backup root newer than current root.

So for the following super:
generation:		10
backup[0] generation:	8
backup[1] generation:	9
backup[2] generation:	10
backup[3] generation:	11

If we're calling find_best_backup_root() then we can pick up slot 3
which is newer than current generation.

This patch introduce a new parameter for find_best_backup_root() to
specify the max generation.

So with above superblock, calling find_best_backup_root(sb, sb_gen - 1)
will ensure we get slot 1, other than slot 3.
This also affects how we update backup roots.

Furthermore, due to the change in the return value,
find_best_backup_root() can now return -1 to indicates error (no valid
backup found), so change callers to co-operate.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 disk-io.c | 34 ++++++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/disk-io.c b/disk-io.c
index be44eead5cef..36db1be264cd 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -845,17 +845,22 @@ int btrfs_check_fs_compatibility(struct btrfs_super_block *sb,
 	return 0;
 }
 
-static int find_best_backup_root(struct btrfs_super_block *super)
+/*
+ * Find the newest backup slot whose generation <= @max_gen
+ *
+ * Can return <0 for error, indicating no valid backup slot for @max_gen.
+ */
+static int find_best_backup_root(struct btrfs_super_block *super,
+				 u64 max_gen)
 {
 	struct btrfs_root_backup *backup;
-	u64 orig_gen = btrfs_super_generation(super);
 	u64 gen = 0;
-	int best_index = 0;
+	int best_index = -1;
 	int i;
 
 	for (i = 0; i < BTRFS_NUM_BACKUP_ROOTS; i++) {
 		backup = super->super_roots + i;
-		if (btrfs_backup_tree_root_gen(backup) != orig_gen &&
+		if (btrfs_backup_tree_root_gen(backup) <= max_gen &&
 		    btrfs_backup_tree_root_gen(backup) > gen) {
 			best_index = i;
 			gen = btrfs_backup_tree_root_gen(backup);
@@ -908,9 +913,10 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 		root_tree_bytenr = btrfs_super_root(sb);
 	} else if (flags & OPEN_CTREE_BACKUP_ROOT) {
 		struct btrfs_root_backup *backup;
-		int index = find_best_backup_root(sb);
-		if (index >= BTRFS_NUM_BACKUP_ROOTS) {
-			fprintf(stderr, "Invalid backup root number\n");
+		int index = find_best_backup_root(sb,
+					btrfs_super_generation(sb) - 1);
+		if (index < 0) {
+			error("can't find any valid backup root");
 			return -EIO;
 		}
 		backup = fs_info->super_copy->super_roots + index;
@@ -1707,10 +1713,22 @@ static int write_dev_supers(struct btrfs_fs_info *fs_info,
 static void backup_super_roots(struct btrfs_fs_info *info)
 {
 	struct btrfs_root_backup *root_backup;
+	u64 current_gen = btrfs_super_generation(info->super_copy);
 	int next_backup;
 	int last_backup;
 
-	last_backup = find_best_backup_root(info->super_copy);
+	last_backup = find_best_backup_root(info->super_copy, current_gen - 1);
+	/* No older backups, retry current gen */
+	if (last_backup < 0) {
+		last_backup = find_best_backup_root(info->super_copy,
+						    current_gen);
+		/*
+		 * Still failed, means no valid backup root at all, restart
+		 * from slot 0.
+		 */
+		if (last_backup < 0)
+			last_backup = 0;
+	}
 	next_backup = (last_backup + 1) % BTRFS_NUM_BACKUP_ROOTS;
 
 	/* just overwrite the last backup if we're at the same generation */
-- 
2.23.0


  parent reply	other threads:[~2019-10-21  9:38 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-21  9:37 [PATCH 0/3] btrfs-progs: check: Introduce optional argument for -b|--backup Qu Wenruo
2019-10-21  9:37 ` [PATCH 1/3] btrfs-progs: utils-lib: Use error() to replace fprintf(stderr, "ERROR: ") Qu Wenruo
2019-10-21  9:48   ` Johannes Thumshirn
2019-10-21  9:37 ` Qu Wenruo [this message]
2019-10-21  9:37 ` [PATCH 3/3] btrfs-progs: check: Introduce optional argument for -b|--backup Qu Wenruo
2019-11-15 12:32 ` [PATCH 0/3] " David Sterba
2019-11-15 12:36   ` Qu Wenruo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191021093755.56835-3-wqu@suse.com \
    --to=wqu@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox