linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols
@ 2021-09-14  9:05 Nikolay Borisov
  2021-09-14  9:05 ` [PATCH v2 1/8] btrfs-progs: Add btrfs_is_empty_uuid Nikolay Borisov
                   ` (10 more replies)
  0 siblings, 11 replies; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov

Here's V2 which takes into account Qu's suggestions, namely:

- Add a helper which contains the common code to clear receive-related data
- Now there is a single patch which impements the check/clear for both orig and
lowmem modes
- Added Reviewed-by from Qu.


Nikolay Borisov (8):
  btrfs-progs: Add btrfs_is_empty_uuid
  btrfs-progs: Remove root argument from btrfs_fixup_low_keys
  btrfs-progs: Remove fs_info argument from leaf_data_end
  btrfs-progs: Remove root argument from btrfs_truncate_item
  btrfs-progs: Add btrfs_uuid_tree_remove
  btrfs-progs: Implement helper to remove received information of RW
    subvol
  btrfs-progs: check: Implement removing received data for RW subvols
  btrfs-progs: tests: Add test for received information removal

 check/main.c                                  |  21 +++-
 check/mode-common.c                           |  40 ++++++++
 check/mode-common.h                           |   1 +
 check/mode-lowmem.c                           |  11 ++-
 kernel-shared/ctree.c                         |  62 +++++-------
 kernel-shared/ctree.h                         |  12 ++-
 kernel-shared/dir-item.c                      |   2 +-
 kernel-shared/extent-tree.c                   |   2 +-
 kernel-shared/file-item.c                     |   4 +-
 kernel-shared/inode-item.c                    |   4 +-
 kernel-shared/uuid-tree.c                     |  93 ++++++++++++++++++
 .../050-subvol-recv-clear/test.raw.xz         | Bin 0 -> 493524 bytes
 12 files changed, 202 insertions(+), 50 deletions(-)
 create mode 100644 tests/fsck-tests/050-subvol-recv-clear/test.raw.xz

--
2.17.1


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

* [PATCH v2 1/8] btrfs-progs: Add btrfs_is_empty_uuid
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
@ 2021-09-14  9:05 ` Nikolay Borisov
  2021-09-16  7:26   ` Anand Jain
  2021-09-14  9:05 ` [PATCH v2 2/8] btrfs-progs: Remove root argument from btrfs_fixup_low_keys Nikolay Borisov
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov

This utility function is needed by the RO->RW snapshot detection code.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 kernel-shared/ctree.h     |  2 ++
 kernel-shared/uuid-tree.c | 11 +++++++++++
 2 files changed, 13 insertions(+)

diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 3cca60323e3d..f53436a7f38b 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -2860,6 +2860,8 @@ int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid,
 int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
 			u64 subvol_id_cpu);
 
+int btrfs_is_empty_uuid(u8 *uuid);
+
 static inline int is_fstree(u64 rootid)
 {
 	if (rootid == BTRFS_FS_TREE_OBJECTID ||
diff --git a/kernel-shared/uuid-tree.c b/kernel-shared/uuid-tree.c
index 21115a4d2d09..51a7b5d9ff5d 100644
--- a/kernel-shared/uuid-tree.c
+++ b/kernel-shared/uuid-tree.c
@@ -109,3 +109,14 @@ int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid,
 					  BTRFS_UUID_KEY_RECEIVED_SUBVOL,
 					  subvol_id);
 }
+
+int btrfs_is_empty_uuid(u8 *uuid)
+{
+	int i;
+
+	for (i = 0; i < BTRFS_UUID_SIZE; i++) {
+		if (uuid[i])
+			return 0;
+	}
+	return 1;
+}
-- 
2.17.1


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

* [PATCH v2 2/8] btrfs-progs: Remove root argument from btrfs_fixup_low_keys
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
  2021-09-14  9:05 ` [PATCH v2 1/8] btrfs-progs: Add btrfs_is_empty_uuid Nikolay Borisov
@ 2021-09-14  9:05 ` Nikolay Borisov
  2021-09-14  9:05 ` [PATCH v2 3/8] btrfs-progs: Remove fs_info argument from leaf_data_end Nikolay Borisov
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov, Qu Wenruo

It's not used, so just remove it.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
---
 check/main.c          |  5 ++---
 kernel-shared/ctree.c | 24 +++++++++++-------------
 kernel-shared/ctree.h |  4 ++--
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/check/main.c b/check/main.c
index a88518159830..6369bdd90656 100644
--- a/check/main.c
+++ b/check/main.c
@@ -4197,8 +4197,7 @@ static int swap_values(struct btrfs_root *root, struct btrfs_path *path,
 			struct btrfs_disk_key key;

 			btrfs_node_key(buf, &key, 0);
-			btrfs_fixup_low_keys(root, path, &key,
-					     btrfs_header_level(buf) + 1);
+			btrfs_fixup_low_keys(path, &key, btrfs_header_level(buf) + 1);
 		}
 	} else {
 		struct btrfs_item *item1, *item2;
@@ -4302,7 +4301,7 @@ static int delete_bogus_item(struct btrfs_root *root,
 		struct btrfs_disk_key disk_key;

 		btrfs_item_key(buf, &disk_key, 0);
-		btrfs_fixup_low_keys(root, path, &disk_key, 1);
+		btrfs_fixup_low_keys(path, &disk_key, 1);
 	}
 	btrfs_mark_buffer_dirty(buf);
 	return 0;
diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c
index 518718de04dd..02eb975338e5 100644
--- a/kernel-shared/ctree.c
+++ b/kernel-shared/ctree.c
@@ -1437,8 +1437,8 @@ int btrfs_search_slot_for_read(struct btrfs_root *root,
  * fixing up pointers when a given leaf/node is not in slot 0 of the
  * higher levels
  */
-void btrfs_fixup_low_keys(struct btrfs_root *root, struct btrfs_path *path,
-			  struct btrfs_disk_key *key, int level)
+void btrfs_fixup_low_keys( struct btrfs_path *path, struct btrfs_disk_key *key,
+		int level)
 {
 	int i;
 	struct extent_buffer *t;
@@ -1485,7 +1485,7 @@ int btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path,
 	btrfs_set_item_key(eb, &disk_key, slot);
 	btrfs_mark_buffer_dirty(eb);
 	if (slot == 0)
-		btrfs_fixup_low_keys(root, path, &disk_key, 1);
+		btrfs_fixup_low_keys(path, &disk_key, 1);
 	return 0;
 }

@@ -1508,7 +1508,7 @@ void btrfs_set_item_key_unsafe(struct btrfs_root *root,
 	btrfs_set_item_key(eb, &disk_key, slot);
 	btrfs_mark_buffer_dirty(eb);
 	if (slot == 0)
-		btrfs_fixup_low_keys(root, path, &disk_key, 1);
+		btrfs_fixup_low_keys(path, &disk_key, 1);
 }

 /*
@@ -2184,7 +2184,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
 		btrfs_mark_buffer_dirty(right);

 	btrfs_item_key(right, &disk_key, 0);
-	btrfs_fixup_low_keys(root, path, &disk_key, 1);
+	btrfs_fixup_low_keys(path, &disk_key, 1);

 	/* then fixup the leaf pointer in the path */
 	if (path->slots[0] < push_items) {
@@ -2415,10 +2415,8 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans,
 			free_extent_buffer(path->nodes[0]);
 			path->nodes[0] = right;
 			path->slots[0] = 0;
-			if (path->slots[1] == 0) {
-				btrfs_fixup_low_keys(root, path,
-						     &disk_key, 1);
-			}
+			if (path->slots[1] == 0)
+				btrfs_fixup_low_keys(path, &disk_key, 1);
 		}
 		btrfs_mark_buffer_dirty(right);
 		return ret;
@@ -2632,7 +2630,7 @@ int btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path,
 		btrfs_set_disk_key_offset(&disk_key, offset + size_diff);
 		btrfs_set_item_key(leaf, &disk_key, slot);
 		if (slot == 0)
-			btrfs_fixup_low_keys(root, path, &disk_key, 1);
+			btrfs_fixup_low_keys(path, &disk_key, 1);
 	}

 	item = btrfs_item_nr(slot);
@@ -2809,7 +2807,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
 	ret = 0;
 	if (slot == 0) {
 		btrfs_cpu_key_to_disk(&disk_key, cpu_key);
-		btrfs_fixup_low_keys(root, path, &disk_key, 1);
+		btrfs_fixup_low_keys(path, &disk_key, 1);
 	}

 	if (btrfs_leaf_free_space(leaf) < 0) {
@@ -2882,7 +2880,7 @@ int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path,
 		struct btrfs_disk_key disk_key;

 		btrfs_node_key(parent, &disk_key, 0);
-		btrfs_fixup_low_keys(root, path, &disk_key, level + 1);
+		btrfs_fixup_low_keys(path, &disk_key, level + 1);
 	}
 	btrfs_mark_buffer_dirty(parent);
 	return ret;
@@ -2982,7 +2980,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 			struct btrfs_disk_key disk_key;

 			btrfs_item_key(leaf, &disk_key, 0);
-			btrfs_fixup_low_keys(root, path, &disk_key, 1);
+			btrfs_fixup_low_keys(path, &disk_key, 1);
 		}

 		/* delete the leaf if it is mostly empty */
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index f53436a7f38b..a17bf50e29b4 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -2747,8 +2747,8 @@ static inline int btrfs_next_item(struct btrfs_root *root,

 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_leaf_free_space(struct extent_buffer *leaf);
-void btrfs_fixup_low_keys(struct btrfs_root *root, struct btrfs_path *path,
-			  struct btrfs_disk_key *key, int level);
+void btrfs_fixup_low_keys(struct btrfs_path *path, struct btrfs_disk_key *key,
+		int level);
 int btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path,
 			    struct btrfs_key *new_key);
 void btrfs_set_item_key_unsafe(struct btrfs_root *root,
--
2.17.1


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

* [PATCH v2 3/8] btrfs-progs: Remove fs_info argument from leaf_data_end
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
  2021-09-14  9:05 ` [PATCH v2 1/8] btrfs-progs: Add btrfs_is_empty_uuid Nikolay Borisov
  2021-09-14  9:05 ` [PATCH v2 2/8] btrfs-progs: Remove root argument from btrfs_fixup_low_keys Nikolay Borisov
@ 2021-09-14  9:05 ` Nikolay Borisov
  2021-09-14  9:05 ` [PATCH v2 4/8] btrfs-progs: Remove root argument from btrfs_truncate_item Nikolay Borisov
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov, Qu Wenruo

The function already takes an extent_buffer which has a reference to
the owning filesystem's fs_info. This also brings the function in line
with the kernel's signature.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
---
 kernel-shared/ctree.c | 35 +++++++++++++++--------------------
 1 file changed, 15 insertions(+), 20 deletions(-)

diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c
index 02eb975338e5..77766c2a7931 100644
--- a/kernel-shared/ctree.c
+++ b/kernel-shared/ctree.c
@@ -557,12 +557,11 @@ static int btrfs_comp_keys(struct btrfs_disk_key *disk,
  * this returns the address of the start of the last item,
  * which is the stop of the leaf data stack
  */
-static inline unsigned int leaf_data_end(const struct btrfs_fs_info *fs_info,
-					 const struct extent_buffer *leaf)
+static inline unsigned int leaf_data_end(const struct extent_buffer *leaf)
 {
 	u32 nr = btrfs_header_nritems(leaf);
 	if (nr == 0)
-		return BTRFS_LEAF_DATA_SIZE(fs_info);
+		return BTRFS_LEAF_DATA_SIZE(leaf->fs_info);
 	return btrfs_item_offset_nr(leaf, nr - 1);
 }

@@ -1980,10 +1979,10 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
 	right_nritems = btrfs_header_nritems(right);

 	push_space = btrfs_item_end_nr(left, left_nritems - push_items);
-	push_space -= leaf_data_end(fs_info, left);
+	push_space -= leaf_data_end(left);

 	/* make room in the right data area */
-	data_end = leaf_data_end(fs_info, right);
+	data_end = leaf_data_end(right);
 	memmove_extent_buffer(right,
 			      btrfs_leaf_data(right) + data_end - push_space,
 			      btrfs_leaf_data(right) + data_end,
@@ -1992,8 +1991,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
 	/* copy from the left data area */
 	copy_extent_buffer(right, left, btrfs_leaf_data(right) +
 		     BTRFS_LEAF_DATA_SIZE(root->fs_info) - push_space,
-		     btrfs_leaf_data(left) + leaf_data_end(fs_info, left),
-		     push_space);
+		     btrfs_leaf_data(left) + leaf_data_end(left), push_space);

 	memmove_extent_buffer(right, btrfs_item_nr_offset(push_items),
 			      btrfs_item_nr_offset(0),
@@ -2130,7 +2128,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
 		     btrfs_item_offset_nr(right, push_items -1);

 	copy_extent_buffer(left, right, btrfs_leaf_data(left) +
-		     leaf_data_end(fs_info, left) - push_space,
+		     leaf_data_end(left) - push_space,
 		     btrfs_leaf_data(right) +
 		     btrfs_item_offset_nr(right, push_items - 1),
 		     push_space);
@@ -2157,13 +2155,12 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root

 	if (push_items < right_nritems) {
 		push_space = btrfs_item_offset_nr(right, push_items - 1) -
-						  leaf_data_end(fs_info, right);
+						  leaf_data_end(right);
 		memmove_extent_buffer(right, btrfs_leaf_data(right) +
 				      BTRFS_LEAF_DATA_SIZE(root->fs_info) -
 				      push_space,
 				      btrfs_leaf_data(right) +
-				      leaf_data_end(fs_info, right),
-				      push_space);
+				      leaf_data_end(right), push_space);

 		memmove_extent_buffer(right, btrfs_item_nr_offset(0),
 			      btrfs_item_nr_offset(push_items),
@@ -2222,8 +2219,7 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans,

 	nritems = nritems - mid;
 	btrfs_set_header_nritems(right, nritems);
-	data_copy_size = btrfs_item_end_nr(l, mid) -
-		leaf_data_end(root->fs_info, l);
+	data_copy_size = btrfs_item_end_nr(l, mid) - leaf_data_end(l);

 	copy_extent_buffer(right, l, btrfs_item_nr_offset(0),
 			   btrfs_item_nr_offset(mid),
@@ -2231,9 +2227,8 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans,

 	copy_extent_buffer(right, l,
 		     btrfs_leaf_data(right) +
-		     BTRFS_LEAF_DATA_SIZE(root->fs_info) -
-		     data_copy_size, btrfs_leaf_data(l) +
-		     leaf_data_end(root->fs_info, l), data_copy_size);
+		     BTRFS_LEAF_DATA_SIZE(root->fs_info) - data_copy_size,
+			 btrfs_leaf_data(l) + leaf_data_end(l), data_copy_size);

 	rt_data_off = BTRFS_LEAF_DATA_SIZE(root->fs_info) -
 		      btrfs_item_end_nr(l, mid);
@@ -2572,7 +2567,7 @@ int btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path,
 		return 0;

 	nritems = btrfs_header_nritems(leaf);
-	data_end = leaf_data_end(root->fs_info, leaf);
+	data_end = leaf_data_end(leaf);

 	old_data_start = btrfs_item_offset_nr(leaf, slot);

@@ -2661,7 +2656,7 @@ int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path,
 	leaf = path->nodes[0];

 	nritems = btrfs_header_nritems(leaf);
-	data_end = leaf_data_end(root->fs_info, leaf);
+	data_end = leaf_data_end(leaf);

 	if (btrfs_leaf_free_space(leaf) < data_size) {
 		btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT);
@@ -2747,7 +2742,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
 	leaf = path->nodes[0];

 	nritems = btrfs_header_nritems(leaf);
-	data_end = leaf_data_end(root->fs_info, leaf);
+	data_end = leaf_data_end(leaf);

 	if (btrfs_leaf_free_space(leaf) < total_size) {
 		btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT);
@@ -2940,7 +2935,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 	nritems = btrfs_header_nritems(leaf);

 	if (slot + nr != nritems) {
-		int data_end = leaf_data_end(root->fs_info, leaf);
+		int data_end = leaf_data_end(leaf);

 		memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) +
 			      data_end + dsize,
--
2.17.1


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

* [PATCH v2 4/8] btrfs-progs: Remove root argument from btrfs_truncate_item
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
                   ` (2 preceding siblings ...)
  2021-09-14  9:05 ` [PATCH v2 3/8] btrfs-progs: Remove fs_info argument from leaf_data_end Nikolay Borisov
@ 2021-09-14  9:05 ` Nikolay Borisov
  2021-09-14  9:05 ` [PATCH v2 5/8] btrfs-progs: Add btrfs_uuid_tree_remove Nikolay Borisov
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov, Qu Wenruo

This function lies in the kernel-shared directory and is supposed to be
close to 1:1 copy with its kernel counterpart, yet it takes one extra
argument - root. But this is now unused to simply remove it.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
---
 kernel-shared/ctree.c       | 3 +--
 kernel-shared/ctree.h       | 3 +--
 kernel-shared/dir-item.c    | 2 +-
 kernel-shared/extent-tree.c | 2 +-
 kernel-shared/file-item.c   | 4 ++--
 kernel-shared/inode-item.c  | 4 ++--
 6 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c
index 77766c2a7931..78f94c6cd42f 100644
--- a/kernel-shared/ctree.c
+++ b/kernel-shared/ctree.c
@@ -2545,8 +2545,7 @@ int btrfs_split_item(struct btrfs_trans_handle *trans,
 	return ret;
 }

-int btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path,
-			u32 new_size, int from_end)
+int btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end)
 {
 	int ret = 0;
 	int slot;
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index a17bf50e29b4..91a85796a678 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -2670,8 +2670,7 @@ int btrfs_create_root(struct btrfs_trans_handle *trans,
 		      struct btrfs_fs_info *fs_info, u64 objectid);
 int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path,
 		u32 data_size);
-int btrfs_truncate_item(struct btrfs_root *root, struct btrfs_path *path,
-			u32 new_size, int from_end);
+int btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end);
 int btrfs_split_item(struct btrfs_trans_handle *trans,
 		     struct btrfs_root *root,
 		     struct btrfs_path *path,
diff --git a/kernel-shared/dir-item.c b/kernel-shared/dir-item.c
index 7dc606c132b5..590b79a929d3 100644
--- a/kernel-shared/dir-item.c
+++ b/kernel-shared/dir-item.c
@@ -284,7 +284,7 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
 		start = btrfs_item_ptr_offset(leaf, path->slots[0]);
 		memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
 			item_len - (ptr + sub_item_len - start));
-		btrfs_truncate_item(root, path, item_len - sub_item_len, 1);
+		btrfs_truncate_item(path, item_len - sub_item_len, 1);
 	}
 	return ret;
 }
diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
index 056a9256b9a4..a8e0c1e60e2e 100644
--- a/kernel-shared/extent-tree.c
+++ b/kernel-shared/extent-tree.c
@@ -1166,7 +1166,7 @@ static int update_inline_extent_backref(struct btrfs_trans_handle *trans,
 			memmove_extent_buffer(leaf, ptr, ptr + size,
 					      end - ptr - size);
 		item_size -= size;
-		ret = btrfs_truncate_item(root, path, item_size, 1);
+		ret = btrfs_truncate_item(path, item_size, 1);
 		BUG_ON(ret);
 	}
 	btrfs_mark_buffer_dirty(leaf);
diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c
index 7e16b747e36c..c910e27e5a5d 100644
--- a/kernel-shared/file-item.c
+++ b/kernel-shared/file-item.c
@@ -362,7 +362,7 @@ static noinline int truncate_one_csum(struct btrfs_root *root,
 		 */
 		u32 new_size = (bytenr - key->offset) / blocksize;
 		new_size *= csum_size;
-		ret = btrfs_truncate_item(root, path, new_size, 1);
+		ret = btrfs_truncate_item(path, new_size, 1);
 		BUG_ON(ret);
 	} else if (key->offset >= bytenr && csum_end > end_byte &&
 		   end_byte > key->offset) {
@@ -375,7 +375,7 @@ static noinline int truncate_one_csum(struct btrfs_root *root,
 		u32 new_size = (csum_end - end_byte) / blocksize;
 		new_size *= csum_size;

-		ret = btrfs_truncate_item(root, path, new_size, 0);
+		ret = btrfs_truncate_item(path, new_size, 0);
 		BUG_ON(ret);

 		key->offset = end_byte;
diff --git a/kernel-shared/inode-item.c b/kernel-shared/inode-item.c
index 4e009746de0e..67173eb141d8 100644
--- a/kernel-shared/inode-item.c
+++ b/kernel-shared/inode-item.c
@@ -311,7 +311,7 @@ int btrfs_del_inode_extref(struct btrfs_trans_handle *trans,
 	memmove_extent_buffer(leaf, ptr, ptr + del_len,
 			      item_size - (ptr + del_len - item_start));

-	btrfs_truncate_item(root, path, item_size - del_len, 1);
+	btrfs_truncate_item(path, item_size - del_len, 1);

 out:
 	btrfs_free_path(path);
@@ -432,7 +432,7 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
 	item_start = btrfs_item_ptr_offset(leaf, path->slots[0]);
 	memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
 			      item_size - (ptr + sub_item_len - item_start));
-	btrfs_truncate_item(root, path, item_size - sub_item_len, 1);
+	btrfs_truncate_item(path, item_size - sub_item_len, 1);
 	btrfs_mark_buffer_dirty(path->nodes[0]);
 out:
 	btrfs_free_path(path);
--
2.17.1


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

* [PATCH v2 5/8] btrfs-progs: Add btrfs_uuid_tree_remove
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
                   ` (3 preceding siblings ...)
  2021-09-14  9:05 ` [PATCH v2 4/8] btrfs-progs: Remove root argument from btrfs_truncate_item Nikolay Borisov
@ 2021-09-14  9:05 ` Nikolay Borisov
  2021-09-14  9:22   ` Qu Wenruo
  2021-09-14  9:05 ` [PATCH v2 6/8] btrfs-progs: Implement helper to remove received information of RW subvol Nikolay Borisov
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov

It will be used to clear received data on RW snapshots that were
received.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 kernel-shared/ctree.h     |  3 ++
 kernel-shared/uuid-tree.c | 82 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 91a85796a678..158281a9fd67 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -2860,6 +2860,9 @@ int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
 			u64 subvol_id_cpu);
 
 int btrfs_is_empty_uuid(u8 *uuid);
+int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
+               u64 subid);
+
 
 static inline int is_fstree(u64 rootid)
 {
diff --git a/kernel-shared/uuid-tree.c b/kernel-shared/uuid-tree.c
index 51a7b5d9ff5d..0f0fbf667dda 100644
--- a/kernel-shared/uuid-tree.c
+++ b/kernel-shared/uuid-tree.c
@@ -120,3 +120,85 @@ int btrfs_is_empty_uuid(u8 *uuid)
 	}
 	return 1;
 }
+
+int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
+		u64 subid)
+{
+	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *uuid_root = fs_info->uuid_root;
+	int ret;
+	struct btrfs_path *path = NULL;
+	struct btrfs_key key;
+	struct extent_buffer *eb;
+	int slot;
+	unsigned long offset;
+	u32 item_size;
+	unsigned long move_dst;
+	unsigned long move_src;
+	unsigned long move_len;
+
+	if (!uuid_root) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	btrfs_uuid_to_key(uuid, &key);
+	key.type = type;
+
+	path = btrfs_alloc_path();
+	if (!path) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = btrfs_search_slot(trans, uuid_root, &key, path, -1, 1);
+	if (ret < 0) {
+		warning("error %d while searching for uuid item!", ret);
+		goto out;
+	}
+	if (ret > 0) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+
+	eb = path->nodes[0];
+	slot = path->slots[0];
+	offset = btrfs_item_ptr_offset(eb, slot);
+	item_size = btrfs_item_size_nr(eb, slot);
+	if (!IS_ALIGNED(item_size, sizeof(u64))) {
+		warning("uuid item with illegal size %lu!",	(unsigned long)item_size);
+		ret = -ENOENT;
+		goto out;
+	}
+	while (item_size) {
+		__le64 read_subid;
+
+		read_extent_buffer(eb, &read_subid, offset, sizeof(read_subid));
+		if (le64_to_cpu(read_subid) == subid)
+			break;
+		offset += sizeof(read_subid);
+		item_size -= sizeof(read_subid);
+	}
+
+	if (!item_size) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	item_size = btrfs_item_size_nr(eb, slot);
+	if (item_size == sizeof(subid)) {
+		ret = btrfs_del_item(trans, uuid_root, path);
+		goto out;
+	}
+
+	move_dst = offset;
+	move_src = offset + sizeof(subid);
+	move_len = item_size - (move_src - btrfs_item_ptr_offset(eb, slot));
+	memmove_extent_buffer(eb, move_dst, move_src, move_len);
+	btrfs_truncate_item(path, item_size - sizeof(subid), 1);
+
+out:
+	btrfs_free_path(path);
+	return ret;
+}
-- 
2.17.1


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

* [PATCH v2 6/8] btrfs-progs: Implement helper to remove received information of RW subvol
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
                   ` (4 preceding siblings ...)
  2021-09-14  9:05 ` [PATCH v2 5/8] btrfs-progs: Add btrfs_uuid_tree_remove Nikolay Borisov
@ 2021-09-14  9:05 ` Nikolay Borisov
  2021-09-14  9:23   ` Qu Wenruo
  2021-09-14  9:05 ` [PATCH v2 7/8] btrfs-progs: check: Implement removing received data for RW subvols Nikolay Borisov
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 check/mode-common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 check/mode-common.h |  1 +
 2 files changed, 41 insertions(+)

diff --git a/check/mode-common.c b/check/mode-common.c
index 0059672c6402..7a5313280f3f 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -1301,3 +1301,43 @@ int repair_dev_item_bytes_used(struct btrfs_fs_info *fs_info,
 	btrfs_abort_transaction(trans, ret);
 	return ret;
 }
+
+int repair_received_subvol(struct btrfs_root *root)
+{
+	struct btrfs_root_item *root_item = &root->root_item;
+	struct btrfs_trans_handle *trans;
+	int ret;
+
+	trans = btrfs_start_transaction(root, 2);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
+	ret = btrfs_uuid_tree_remove(trans, root_item->received_uuid,
+			BTRFS_UUID_KEY_RECEIVED_SUBVOL, root->root_key.objectid);
+
+	if (ret && ret != -ENOENT) {
+		btrfs_abort_transaction(trans, ret);
+		return ret;
+	}
+
+	memset(root_item->received_uuid, 0, BTRFS_UUID_SIZE);
+	btrfs_set_root_stransid(root_item, 0);
+	btrfs_set_root_rtransid(root_item, 0);
+	btrfs_set_stack_timespec_sec(&root_item->stime, 0);
+	btrfs_set_stack_timespec_nsec(&root_item->stime, 0);
+	btrfs_set_stack_timespec_sec(&root_item->rtime, 0);
+	btrfs_set_stack_timespec_nsec(&root_item->rtime, 0);
+
+	ret = btrfs_update_root(trans, gfs_info->tree_root, &root->root_key,
+			root_item);
+	if (ret < 0) {
+		btrfs_abort_transaction(trans, ret);
+		return ret;
+	}
+
+	ret = btrfs_commit_transaction(trans, gfs_info->tree_root);
+	if (!ret)
+		printf("Cleared received information for subvol: %llu\n",
+				root->root_key.objectid);
+	return ret;
+}
diff --git a/check/mode-common.h b/check/mode-common.h
index cdfb10d58cde..f1ec5dca0199 100644
--- a/check/mode-common.h
+++ b/check/mode-common.h
@@ -130,6 +130,7 @@ int reset_imode(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		struct btrfs_path *path, u64 ino, u32 mode);
 int repair_imode_common(struct btrfs_root *root, struct btrfs_path *path);
 int check_repair_free_space_inode(struct btrfs_path *path);
+int repair_received_subvol(struct btrfs_root *root);
 
 /*
  * Check if the inode mode @imode is valid
-- 
2.17.1


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

* [PATCH v2 7/8] btrfs-progs: check: Implement removing received data for RW subvols
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
                   ` (5 preceding siblings ...)
  2021-09-14  9:05 ` [PATCH v2 6/8] btrfs-progs: Implement helper to remove received information of RW subvol Nikolay Borisov
@ 2021-09-14  9:05 ` Nikolay Borisov
  2021-09-14  9:25   ` Qu Wenruo
  2021-09-14  9:05 ` [PATCH v2 8/8] btrfs-progs: tests: Add test for received information removal Nikolay Borisov
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov

Making a received subvolume RO should preclude doing an incremental send
of said subvolume since it can't be guaranteed that nothing changed in
the structure and this in turn has correctness implications for send.

There is a pending kernel change that implements this behavior and
ensures that in the future RO volumes which are switched to RW can't be
used for incremental send. However, old kernels won't have that patch
backported. To ensure there is a supported way for users to put their
subvolumes in sane state let's implement the same functionality in
progs.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 check/main.c        | 16 +++++++++++++++-
 check/mode-lowmem.c | 11 ++++++++++-
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/check/main.c b/check/main.c
index 6369bdd90656..9d3822a2ebae 100644
--- a/check/main.c
+++ b/check/main.c
@@ -3544,6 +3544,7 @@ static int check_fs_root(struct btrfs_root *root,
 	int ret = 0;
 	int err = 0;
 	bool generation_err = false;
+	bool rw_received_err = false;
 	int wret;
 	int level;
 	u64 super_generation;
@@ -3658,6 +3659,19 @@ static int check_fs_root(struct btrfs_root *root,
 					sizeof(found_key)));
 	}
 
+	if (!((btrfs_root_flags(root_item) & BTRFS_ROOT_SUBVOL_RDONLY) ||
+			btrfs_is_empty_uuid(root_item->received_uuid))) {
+		error("Subvolume id: %llu is RW and has a received uuid",
+				root->root_key.objectid);
+		rw_received_err = true;
+		if (repair) {
+			ret = repair_received_subvol(root);
+			if (ret)
+				return ret;
+			rw_received_err = false;
+		}
+	}
+
 	while (1) {
 		ctx.item_count++;
 		wret = walk_down_tree(root, &path, wc, &level, &nrefs);
@@ -3722,7 +3736,7 @@ static int check_fs_root(struct btrfs_root *root,
 
 	free_corrupt_blocks_tree(&corrupt_blocks);
 	gfs_info->corrupt_blocks = NULL;
-	if (!ret && generation_err)
+	if (!ret && (generation_err ||  rw_received_err))
 		ret = -1;
 	return ret;
 }
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index 323e66bc4cb1..d8f783bea424 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -5197,8 +5197,17 @@ static int check_btrfs_root(struct btrfs_root *root, int check_all)
 		ret = check_fs_first_inode(root);
 		if (ret < 0)
 			return FATAL_ERROR;
-	}
 
+		if (!((btrfs_root_flags(root_item) & BTRFS_ROOT_SUBVOL_RDONLY) ||
+					btrfs_is_empty_uuid(root_item->received_uuid))) {
+			error("Subvolume id: %llu is RW and has a received uuid",
+				  root->root_key.objectid);
+			if (repair)
+				ret = repair_received_subvol(root);
+			if (ret < 0)
+				return FATAL_ERROR;
+		}
+	}
 
 	level = btrfs_header_level(root->node);
 	btrfs_init_path(&path);
-- 
2.17.1


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

* [PATCH v2 8/8] btrfs-progs: tests: Add test for received information removal
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
                   ` (6 preceding siblings ...)
  2021-09-14  9:05 ` [PATCH v2 7/8] btrfs-progs: check: Implement removing received data for RW subvols Nikolay Borisov
@ 2021-09-14  9:05 ` Nikolay Borisov
  2021-09-14  9:30 ` [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Qu Wenruo
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:05 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Nikolay Borisov

The image contains a subvolume which as been received i.e has relevant
received fields populated and subsequently has been switched to RW mode.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 .../050-subvol-recv-clear/test.raw.xz          | Bin 0 -> 493524 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 tests/fsck-tests/050-subvol-recv-clear/test.raw.xz

diff --git a/tests/fsck-tests/050-subvol-recv-clear/test.raw.xz b/tests/fsck-tests/050-subvol-recv-clear/test.raw.xz
new file mode 100644
index 0000000000000000000000000000000000000000..074a53b49cdd473af4f2a97cbf7e3f0d3c6518aa
GIT binary patch
literal 493524
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

literal 0
HcmV?d00001

-- 
2.17.1


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

* Re: [PATCH v2 5/8] btrfs-progs: Add btrfs_uuid_tree_remove
  2021-09-14  9:05 ` [PATCH v2 5/8] btrfs-progs: Add btrfs_uuid_tree_remove Nikolay Borisov
@ 2021-09-14  9:22   ` Qu Wenruo
  0 siblings, 0 replies; 20+ messages in thread
From: Qu Wenruo @ 2021-09-14  9:22 UTC (permalink / raw)
  To: Nikolay Borisov, linux-btrfs



On 2021/9/14 下午5:05, Nikolay Borisov wrote:
> It will be used to clear received data on RW snapshots that were
> received.

It would be more helpful to mention it's a backport of kernel function.

>
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu

> ---
>   kernel-shared/ctree.h     |  3 ++
>   kernel-shared/uuid-tree.c | 82 +++++++++++++++++++++++++++++++++++++++
>   2 files changed, 85 insertions(+)
>
> diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
> index 91a85796a678..158281a9fd67 100644
> --- a/kernel-shared/ctree.h
> +++ b/kernel-shared/ctree.h
> @@ -2860,6 +2860,9 @@ int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
>   			u64 subvol_id_cpu);
>
>   int btrfs_is_empty_uuid(u8 *uuid);
> +int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
> +               u64 subid);
> +
>
>   static inline int is_fstree(u64 rootid)
>   {
> diff --git a/kernel-shared/uuid-tree.c b/kernel-shared/uuid-tree.c
> index 51a7b5d9ff5d..0f0fbf667dda 100644
> --- a/kernel-shared/uuid-tree.c
> +++ b/kernel-shared/uuid-tree.c
> @@ -120,3 +120,85 @@ int btrfs_is_empty_uuid(u8 *uuid)
>   	}
>   	return 1;
>   }
> +
> +int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
> +		u64 subid)
> +{
> +	struct btrfs_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *uuid_root = fs_info->uuid_root;
> +	int ret;
> +	struct btrfs_path *path = NULL;
> +	struct btrfs_key key;
> +	struct extent_buffer *eb;
> +	int slot;
> +	unsigned long offset;
> +	u32 item_size;
> +	unsigned long move_dst;
> +	unsigned long move_src;
> +	unsigned long move_len;
> +
> +	if (!uuid_root) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	btrfs_uuid_to_key(uuid, &key);
> +	key.type = type;
> +
> +	path = btrfs_alloc_path();
> +	if (!path) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	ret = btrfs_search_slot(trans, uuid_root, &key, path, -1, 1);
> +	if (ret < 0) {
> +		warning("error %d while searching for uuid item!", ret);
> +		goto out;
> +	}
> +	if (ret > 0) {
> +		ret = -ENOENT;
> +		goto out;
> +	}
> +
> +
> +	eb = path->nodes[0];
> +	slot = path->slots[0];
> +	offset = btrfs_item_ptr_offset(eb, slot);
> +	item_size = btrfs_item_size_nr(eb, slot);
> +	if (!IS_ALIGNED(item_size, sizeof(u64))) {
> +		warning("uuid item with illegal size %lu!",	(unsigned long)item_size);
> +		ret = -ENOENT;
> +		goto out;
> +	}
> +	while (item_size) {
> +		__le64 read_subid;
> +
> +		read_extent_buffer(eb, &read_subid, offset, sizeof(read_subid));
> +		if (le64_to_cpu(read_subid) == subid)
> +			break;
> +		offset += sizeof(read_subid);
> +		item_size -= sizeof(read_subid);
> +	}
> +
> +	if (!item_size) {
> +		ret = -ENOENT;
> +		goto out;
> +	}
> +
> +	item_size = btrfs_item_size_nr(eb, slot);
> +	if (item_size == sizeof(subid)) {
> +		ret = btrfs_del_item(trans, uuid_root, path);
> +		goto out;
> +	}
> +
> +	move_dst = offset;
> +	move_src = offset + sizeof(subid);
> +	move_len = item_size - (move_src - btrfs_item_ptr_offset(eb, slot));
> +	memmove_extent_buffer(eb, move_dst, move_src, move_len);
> +	btrfs_truncate_item(path, item_size - sizeof(subid), 1);
> +
> +out:
> +	btrfs_free_path(path);
> +	return ret;
> +}
>

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

* Re: [PATCH v2 6/8] btrfs-progs: Implement helper to remove received information of RW subvol
  2021-09-14  9:05 ` [PATCH v2 6/8] btrfs-progs: Implement helper to remove received information of RW subvol Nikolay Borisov
@ 2021-09-14  9:23   ` Qu Wenruo
  0 siblings, 0 replies; 20+ messages in thread
From: Qu Wenruo @ 2021-09-14  9:23 UTC (permalink / raw)
  To: Nikolay Borisov, linux-btrfs



On 2021/9/14 下午5:05, Nikolay Borisov wrote:
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu
> ---
>   check/mode-common.c | 40 ++++++++++++++++++++++++++++++++++++++++
>   check/mode-common.h |  1 +
>   2 files changed, 41 insertions(+)
>
> diff --git a/check/mode-common.c b/check/mode-common.c
> index 0059672c6402..7a5313280f3f 100644
> --- a/check/mode-common.c
> +++ b/check/mode-common.c
> @@ -1301,3 +1301,43 @@ int repair_dev_item_bytes_used(struct btrfs_fs_info *fs_info,
>   	btrfs_abort_transaction(trans, ret);
>   	return ret;
>   }
> +
> +int repair_received_subvol(struct btrfs_root *root)
> +{
> +	struct btrfs_root_item *root_item = &root->root_item;
> +	struct btrfs_trans_handle *trans;
> +	int ret;
> +
> +	trans = btrfs_start_transaction(root, 2);
> +	if (IS_ERR(trans))
> +		return PTR_ERR(trans);
> +
> +	ret = btrfs_uuid_tree_remove(trans, root_item->received_uuid,
> +			BTRFS_UUID_KEY_RECEIVED_SUBVOL, root->root_key.objectid);
> +
> +	if (ret && ret != -ENOENT) {
> +		btrfs_abort_transaction(trans, ret);
> +		return ret;
> +	}
> +
> +	memset(root_item->received_uuid, 0, BTRFS_UUID_SIZE);
> +	btrfs_set_root_stransid(root_item, 0);
> +	btrfs_set_root_rtransid(root_item, 0);
> +	btrfs_set_stack_timespec_sec(&root_item->stime, 0);
> +	btrfs_set_stack_timespec_nsec(&root_item->stime, 0);
> +	btrfs_set_stack_timespec_sec(&root_item->rtime, 0);
> +	btrfs_set_stack_timespec_nsec(&root_item->rtime, 0);
> +
> +	ret = btrfs_update_root(trans, gfs_info->tree_root, &root->root_key,
> +			root_item);
> +	if (ret < 0) {
> +		btrfs_abort_transaction(trans, ret);
> +		return ret;
> +	}
> +
> +	ret = btrfs_commit_transaction(trans, gfs_info->tree_root);
> +	if (!ret)
> +		printf("Cleared received information for subvol: %llu\n",
> +				root->root_key.objectid);
> +	return ret;
> +}
> diff --git a/check/mode-common.h b/check/mode-common.h
> index cdfb10d58cde..f1ec5dca0199 100644
> --- a/check/mode-common.h
> +++ b/check/mode-common.h
> @@ -130,6 +130,7 @@ int reset_imode(struct btrfs_trans_handle *trans, struct btrfs_root *root,
>   		struct btrfs_path *path, u64 ino, u32 mode);
>   int repair_imode_common(struct btrfs_root *root, struct btrfs_path *path);
>   int check_repair_free_space_inode(struct btrfs_path *path);
> +int repair_received_subvol(struct btrfs_root *root);
>
>   /*
>    * Check if the inode mode @imode is valid
>

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

* Re: [PATCH v2 7/8] btrfs-progs: check: Implement removing received data for RW subvols
  2021-09-14  9:05 ` [PATCH v2 7/8] btrfs-progs: check: Implement removing received data for RW subvols Nikolay Borisov
@ 2021-09-14  9:25   ` Qu Wenruo
  2021-09-14  9:55     ` Nikolay Borisov
  0 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2021-09-14  9:25 UTC (permalink / raw)
  To: Nikolay Borisov, linux-btrfs



On 2021/9/14 下午5:05, Nikolay Borisov wrote:
> Making a received subvolume RO should preclude doing an incremental send
> of said subvolume since it can't be guaranteed that nothing changed in
> the structure and this in turn has correctness implications for send.
>
> There is a pending kernel change that implements this behavior and
> ensures that in the future RO volumes which are switched to RW can't be
> used for incremental send. However, old kernels won't have that patch
> backported. To ensure there is a supported way for users to put their
> subvolumes in sane state let's implement the same functionality in
> progs.
>
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>
> ---
>   check/main.c        | 16 +++++++++++++++-
>   check/mode-lowmem.c | 11 ++++++++++-
>   2 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/check/main.c b/check/main.c
> index 6369bdd90656..9d3822a2ebae 100644
> --- a/check/main.c
> +++ b/check/main.c
> @@ -3544,6 +3544,7 @@ static int check_fs_root(struct btrfs_root *root,
>   	int ret = 0;
>   	int err = 0;
>   	bool generation_err = false;
> +	bool rw_received_err = false;
>   	int wret;
>   	int level;
>   	u64 super_generation;
> @@ -3658,6 +3659,19 @@ static int check_fs_root(struct btrfs_root *root,
>   					sizeof(found_key)));
>   	}
>
> +	if (!((btrfs_root_flags(root_item) & BTRFS_ROOT_SUBVOL_RDONLY) ||
> +			btrfs_is_empty_uuid(root_item->received_uuid))) {
> +		error("Subvolume id: %llu is RW and has a received uuid",
> +				root->root_key.objectid);
> +		rw_received_err = true;
> +		if (repair) {
> +			ret = repair_received_subvol(root);
> +			if (ret)
> +				return ret;
> +			rw_received_err = false;
> +		}
> +	}
> +
>   	while (1) {
>   		ctx.item_count++;
>   		wret = walk_down_tree(root, &path, wc, &level, &nrefs);
> @@ -3722,7 +3736,7 @@ static int check_fs_root(struct btrfs_root *root,
>
>   	free_corrupt_blocks_tree(&corrupt_blocks);
>   	gfs_info->corrupt_blocks = NULL;
> -	if (!ret && generation_err)
> +	if (!ret && (generation_err ||  rw_received_err))
>   		ret = -1;
>   	return ret;
>   }
> diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
> index 323e66bc4cb1..d8f783bea424 100644
> --- a/check/mode-lowmem.c
> +++ b/check/mode-lowmem.c
> @@ -5197,8 +5197,17 @@ static int check_btrfs_root(struct btrfs_root *root, int check_all)
>   		ret = check_fs_first_inode(root);
>   		if (ret < 0)
>   			return FATAL_ERROR;
> -	}
>
> +		if (!((btrfs_root_flags(root_item) & BTRFS_ROOT_SUBVOL_RDONLY) ||
> +					btrfs_is_empty_uuid(root_item->received_uuid))) {
> +			error("Subvolume id: %llu is RW and has a received uuid",
> +				  root->root_key.objectid);
> +			if (repair)
> +				ret = repair_received_subvol(root);
> +			if (ret < 0)
> +				return FATAL_ERROR;
> +		}

Not sure if we need to error out completely.

I guess continue the check would be better?

Despite that, everything looks good to me.

Thanks,
Qu
> +	}
>
>   	level = btrfs_header_level(root->node);
>   	btrfs_init_path(&path);
>

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

* Re: [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
                   ` (7 preceding siblings ...)
  2021-09-14  9:05 ` [PATCH v2 8/8] btrfs-progs: tests: Add test for received information removal Nikolay Borisov
@ 2021-09-14  9:30 ` Qu Wenruo
  2021-09-14  9:30 ` Qu Wenruo
  2021-09-21 18:51 ` David Sterba
  10 siblings, 0 replies; 20+ messages in thread
From: Qu Wenruo @ 2021-09-14  9:30 UTC (permalink / raw)
  To: Nikolay Borisov, linux-btrfs



On 2021/9/14 下午5:05, Nikolay Borisov wrote:
> Here's V2 which takes into account Qu's suggestions, namely:
>
> - Add a helper which contains the common code to clear receive-related data
> - Now there is a single patch which impements the check/clear for both orig and
> lowmem modes
> - Added Reviewed-by from Qu.
>
>
> Nikolay Borisov (8):
>    btrfs-progs: Add btrfs_is_empty_uuid
>    btrfs-progs: Remove root argument from btrfs_fixup_low_keys
>    btrfs-progs: Remove fs_info argument from leaf_data_end
>    btrfs-progs: Remove root argument from btrfs_truncate_item
>    btrfs-progs: Add btrfs_uuid_tree_remove
>    btrfs-progs: Implement helper to remove received information of RW
>      subvol
>    btrfs-progs: check: Implement removing received data for RW subvols
>    btrfs-progs: tests: Add test for received information removal
>
>   check/main.c                                  |  21 +++-
>   check/mode-common.c                           |  40 ++++++++
>   check/mode-common.h                           |   1 +
>   check/mode-lowmem.c                           |  11 ++-
>   kernel-shared/ctree.c                         |  62 +++++-------
>   kernel-shared/ctree.h                         |  12 ++-
>   kernel-shared/dir-item.c                      |   2 +-
>   kernel-shared/extent-tree.c                   |   2 +-
>   kernel-shared/file-item.c                     |   4 +-
>   kernel-shared/inode-item.c                    |   4 +-
>   kernel-shared/uuid-tree.c                     |  93 ++++++++++++++++++
>   .../050-subvol-recv-clear/test.raw.xz         | Bin 0 -> 493524 bytes

The images looks a little large than expected, so that the mailing list
is rejected the armored patch.

Can we use btrfs-image? As there is no need for special layout which
can't be dumped by btrfs-image.
Thus using btrfs-image -c9 would save quite some space.

Thanks,
Qu

>   12 files changed, 202 insertions(+), 50 deletions(-)
>   create mode 100644 tests/fsck-tests/050-subvol-recv-clear/test.raw.xz
>
> --
> 2.17.1
>

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

* Re: [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
                   ` (8 preceding siblings ...)
  2021-09-14  9:30 ` [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Qu Wenruo
@ 2021-09-14  9:30 ` Qu Wenruo
  2021-09-14  9:31   ` Nikolay Borisov
  2021-09-21 18:51 ` David Sterba
  10 siblings, 1 reply; 20+ messages in thread
From: Qu Wenruo @ 2021-09-14  9:30 UTC (permalink / raw)
  To: Nikolay Borisov, linux-btrfs



On 2021/9/14 下午5:05, Nikolay Borisov wrote:
> Here's V2 which takes into account Qu's suggestions, namely:
>
> - Add a helper which contains the common code to clear receive-related data
> - Now there is a single patch which impements the check/clear for both orig and
> lowmem modes
> - Added Reviewed-by from Qu.
>
>
> Nikolay Borisov (8):
>    btrfs-progs: Add btrfs_is_empty_uuid
>    btrfs-progs: Remove root argument from btrfs_fixup_low_keys
>    btrfs-progs: Remove fs_info argument from leaf_data_end
>    btrfs-progs: Remove root argument from btrfs_truncate_item
>    btrfs-progs: Add btrfs_uuid_tree_remove
>    btrfs-progs: Implement helper to remove received information of RW
>      subvol
>    btrfs-progs: check: Implement removing received data for RW subvols
>    btrfs-progs: tests: Add test for received information removal
>
>   check/main.c                                  |  21 +++-
>   check/mode-common.c                           |  40 ++++++++
>   check/mode-common.h                           |   1 +
>   check/mode-lowmem.c                           |  11 ++-
>   kernel-shared/ctree.c                         |  62 +++++-------
>   kernel-shared/ctree.h                         |  12 ++-
>   kernel-shared/dir-item.c                      |   2 +-
>   kernel-shared/extent-tree.c                   |   2 +-
>   kernel-shared/file-item.c                     |   4 +-
>   kernel-shared/inode-item.c                    |   4 +-
>   kernel-shared/uuid-tree.c                     |  93 ++++++++++++++++++
>   .../050-subvol-recv-clear/test.raw.xz         | Bin 0 -> 493524 bytes

The image looks a little large than expected, so that the mailing list
is rejected the armored patch.

Can we use btrfs-image? As there is no need for special layout which
can't be dumped by btrfs-image.
Thus using btrfs-image -c9 would save quite some space.

Thanks,
Qu

>   12 files changed, 202 insertions(+), 50 deletions(-)
>   create mode 100644 tests/fsck-tests/050-subvol-recv-clear/test.raw.xz
>
> --
> 2.17.1
>

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

* Re: [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols
  2021-09-14  9:30 ` Qu Wenruo
@ 2021-09-14  9:31   ` Nikolay Borisov
  0 siblings, 0 replies; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:31 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs



On 14.09.21 г. 12:30, Qu Wenruo wrote:
> 
> 
> On 2021/9/14 下午5:05, Nikolay Borisov wrote:
>> Here's V2 which takes into account Qu's suggestions, namely:
>>
>> - Add a helper which contains the common code to clear receive-related
>> data
>> - Now there is a single patch which impements the check/clear for both
>> orig and
>> lowmem modes
>> - Added Reviewed-by from Qu.
>>
>>
>> Nikolay Borisov (8):
>>    btrfs-progs: Add btrfs_is_empty_uuid
>>    btrfs-progs: Remove root argument from btrfs_fixup_low_keys
>>    btrfs-progs: Remove fs_info argument from leaf_data_end
>>    btrfs-progs: Remove root argument from btrfs_truncate_item
>>    btrfs-progs: Add btrfs_uuid_tree_remove
>>    btrfs-progs: Implement helper to remove received information of RW
>>      subvol
>>    btrfs-progs: check: Implement removing received data for RW subvols
>>    btrfs-progs: tests: Add test for received information removal
>>
>>   check/main.c                                  |  21 +++-
>>   check/mode-common.c                           |  40 ++++++++
>>   check/mode-common.h                           |   1 +
>>   check/mode-lowmem.c                           |  11 ++-
>>   kernel-shared/ctree.c                         |  62 +++++-------
>>   kernel-shared/ctree.h                         |  12 ++-
>>   kernel-shared/dir-item.c                      |   2 +-
>>   kernel-shared/extent-tree.c                   |   2 +-
>>   kernel-shared/file-item.c                     |   4 +-
>>   kernel-shared/inode-item.c                    |   4 +-
>>   kernel-shared/uuid-tree.c                     |  93 ++++++++++++++++++
>>   .../050-subvol-recv-clear/test.raw.xz         | Bin 0 -> 493524 bytes
> 
> The image looks a little large than expected, so that the mailing list
> is rejected the armored patch.
> 
> Can we use btrfs-image? As there is no need for special layout which
> can't be dumped by btrfs-image.
> Thus using btrfs-image -c9 would save quite some space.

Well I did use a raw image, compressed with xz. But sure, I'll look into
this but for the time being will wait to gather more feedback.

> 
> Thanks,
> Qu
> 
>>   12 files changed, 202 insertions(+), 50 deletions(-)
>>   create mode 100644 tests/fsck-tests/050-subvol-recv-clear/test.raw.xz
>>
>> -- 
>> 2.17.1
>>
> 

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

* Re: [PATCH v2 7/8] btrfs-progs: check: Implement removing received data for RW subvols
  2021-09-14  9:25   ` Qu Wenruo
@ 2021-09-14  9:55     ` Nikolay Borisov
  0 siblings, 0 replies; 20+ messages in thread
From: Nikolay Borisov @ 2021-09-14  9:55 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs



On 14.09.21 г. 12:25, Qu Wenruo wrote:
> 
> 
> On 2021/9/14 下午5:05, Nikolay Borisov wrote:
>> Making a received subvolume RO should preclude doing an incremental send
>> of said subvolume since it can't be guaranteed that nothing changed in
>> the structure and this in turn has correctness implications for send.
>>
>> There is a pending kernel change that implements this behavior and
>> ensures that in the future RO volumes which are switched to RW can't be
>> used for incremental send. However, old kernels won't have that patch
>> backported. To ensure there is a supported way for users to put their
>> subvolumes in sane state let's implement the same functionality in
>> progs.
>>
>> Signed-off-by: Nikolay Borisov <nborisov@suse.com>
>> ---
>>   check/main.c        | 16 +++++++++++++++-
>>   check/mode-lowmem.c | 11 ++++++++++-
>>   2 files changed, 25 insertions(+), 2 deletions(-)
>>
>> diff --git a/check/main.c b/check/main.c
>> index 6369bdd90656..9d3822a2ebae 100644
>> --- a/check/main.c
>> +++ b/check/main.c
>> @@ -3544,6 +3544,7 @@ static int check_fs_root(struct btrfs_root *root,
>>       int ret = 0;
>>       int err = 0;
>>       bool generation_err = false;
>> +    bool rw_received_err = false;
>>       int wret;
>>       int level;
>>       u64 super_generation;
>> @@ -3658,6 +3659,19 @@ static int check_fs_root(struct btrfs_root *root,
>>                       sizeof(found_key)));
>>       }
>>
>> +    if (!((btrfs_root_flags(root_item) & BTRFS_ROOT_SUBVOL_RDONLY) ||
>> +            btrfs_is_empty_uuid(root_item->received_uuid))) {
>> +        error("Subvolume id: %llu is RW and has a received uuid",
>> +                root->root_key.objectid);
>> +        rw_received_err = true;
>> +        if (repair) {
>> +            ret = repair_received_subvol(root);
>> +            if (ret)
>> +                return ret;
>> +            rw_received_err = false;
>> +        }
>> +    }
>> +
>>       while (1) {
>>           ctx.item_count++;
>>           wret = walk_down_tree(root, &path, wc, &level, &nrefs);
>> @@ -3722,7 +3736,7 @@ static int check_fs_root(struct btrfs_root *root,
>>
>>       free_corrupt_blocks_tree(&corrupt_blocks);
>>       gfs_info->corrupt_blocks = NULL;
>> -    if (!ret && generation_err)
>> +    if (!ret && (generation_err ||  rw_received_err))
>>           ret = -1;
>>       return ret;
>>   }
>> diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
>> index 323e66bc4cb1..d8f783bea424 100644
>> --- a/check/mode-lowmem.c
>> +++ b/check/mode-lowmem.c
>> @@ -5197,8 +5197,17 @@ static int check_btrfs_root(struct btrfs_root
>> *root, int check_all)
>>           ret = check_fs_first_inode(root);
>>           if (ret < 0)
>>               return FATAL_ERROR;
>> -    }
>>
>> +        if (!((btrfs_root_flags(root_item) &
>> BTRFS_ROOT_SUBVOL_RDONLY) ||
>> +                    btrfs_is_empty_uuid(root_item->received_uuid))) {
>> +            error("Subvolume id: %llu is RW and has a received uuid",
>> +                  root->root_key.objectid);
>> +            if (repair)
>> +                ret = repair_received_subvol(root);
>> +            if (ret < 0)
>> +                return FATAL_ERROR;
>> +        }
> 
> Not sure if we need to error out completely.
> 
> I guess continue the check would be better?

There's that, but we still need to find a way to signify there is an
error. So for lowmem mode the possibility is to introduce yet another
bit (from 26 to 27) to signify this particular problem. Ok, will fix it
in the next iteration but I'm still waiting for more feedback,
especially from David.
> 
> Despite that, everything looks good to me.
> 
> Thanks,
> Qu
>> +    }
>>
>>       level = btrfs_header_level(root->node);
>>       btrfs_init_path(&path);
>>
> 

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

* Re: [PATCH v2 1/8] btrfs-progs: Add btrfs_is_empty_uuid
  2021-09-14  9:05 ` [PATCH v2 1/8] btrfs-progs: Add btrfs_is_empty_uuid Nikolay Borisov
@ 2021-09-16  7:26   ` Anand Jain
  2021-09-20 11:41     ` David Sterba
  0 siblings, 1 reply; 20+ messages in thread
From: Anand Jain @ 2021-09-16  7:26 UTC (permalink / raw)
  To: Nikolay Borisov, linux-btrfs

On 14/09/2021 17:05, Nikolay Borisov wrote:
> This utility function is needed by the RO->RW snapshot detection code.
> 
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>
> ---
>   kernel-shared/ctree.h     |  2 ++
>   kernel-shared/uuid-tree.c | 11 +++++++++++
>   2 files changed, 13 insertions(+)
> 
> diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
> index 3cca60323e3d..f53436a7f38b 100644
> --- a/kernel-shared/ctree.h
> +++ b/kernel-shared/ctree.h
> @@ -2860,6 +2860,8 @@ int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid,
>   int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type,
>   			u64 subvol_id_cpu);
>   
> +int btrfs_is_empty_uuid(u8 *uuid);
> +
>   static inline int is_fstree(u64 rootid)
>   {
>   	if (rootid == BTRFS_FS_TREE_OBJECTID ||
> diff --git a/kernel-shared/uuid-tree.c b/kernel-shared/uuid-tree.c
> index 21115a4d2d09..51a7b5d9ff5d 100644
> --- a/kernel-shared/uuid-tree.c
> +++ b/kernel-shared/uuid-tree.c
> @@ -109,3 +109,14 @@ int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid,
>   					  BTRFS_UUID_KEY_RECEIVED_SUBVOL,
>   					  subvol_id);
>   }
> +
> +int btrfs_is_empty_uuid(u8 *uuid)
> +{
> +	int i;
> +
> +	for (i = 0; i < BTRFS_UUID_SIZE; i++) {
> +		if (uuid[i])
> +			return 0;
> +	}
> +	return 1;
> +}
> 

   You could use uuid_is_null(). No?



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

* Re: [PATCH v2 1/8] btrfs-progs: Add btrfs_is_empty_uuid
  2021-09-16  7:26   ` Anand Jain
@ 2021-09-20 11:41     ` David Sterba
  0 siblings, 0 replies; 20+ messages in thread
From: David Sterba @ 2021-09-20 11:41 UTC (permalink / raw)
  To: Anand Jain; +Cc: Nikolay Borisov, linux-btrfs

On Thu, Sep 16, 2021 at 03:26:30PM +0800, Anand Jain wrote:
> On 14/09/2021 17:05, Nikolay Borisov wrote:
> > --- a/kernel-shared/uuid-tree.c
> > +++ b/kernel-shared/uuid-tree.c
> > @@ -109,3 +109,14 @@ int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid,
> >   					  BTRFS_UUID_KEY_RECEIVED_SUBVOL,
> >   					  subvol_id);
> >   }
> > +
> > +int btrfs_is_empty_uuid(u8 *uuid)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < BTRFS_UUID_SIZE; i++) {
> > +		if (uuid[i])
> > +			return 0;
> > +	}
> > +	return 1;
> > +}
> > 
> 
>    You could use uuid_is_null(). No?

Yeah, no need to duplicate that.

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

* Re: [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols
  2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
                   ` (9 preceding siblings ...)
  2021-09-14  9:30 ` Qu Wenruo
@ 2021-09-21 18:51 ` David Sterba
  2021-09-21 22:08   ` Graham Cobb
  10 siblings, 1 reply; 20+ messages in thread
From: David Sterba @ 2021-09-21 18:51 UTC (permalink / raw)
  To: Nikolay Borisov; +Cc: linux-btrfs

On Tue, Sep 14, 2021 at 12:05:50PM +0300, Nikolay Borisov wrote:
> Here's V2 which takes into account Qu's suggestions, namely:
> 
> - Add a helper which contains the common code to clear receive-related data
> - Now there is a single patch which impements the check/clear for both orig and
> lowmem modes
> - Added Reviewed-by from Qu.
> 
> 
> Nikolay Borisov (8):
>   btrfs-progs: Add btrfs_is_empty_uuid
>   btrfs-progs: Remove root argument from btrfs_fixup_low_keys
>   btrfs-progs: Remove fs_info argument from leaf_data_end
>   btrfs-progs: Remove root argument from btrfs_truncate_item
>   btrfs-progs: Add btrfs_uuid_tree_remove
>   btrfs-progs: Implement helper to remove received information of RW
>     subvol
>   btrfs-progs: check: Implement removing received data for RW subvols
>   btrfs-progs: tests: Add test for received information removal

Patches 2-5 added to devel as they're preparatory and otherwise OK as
independent cleanups.

Regarding the rw and received_uuid, it's choosing between these options:

1) ro->rw resets received_uuid unconditionally

Pros:
- safe as it does not lead to unexpected results after incremental send

Cons:
- unconditional, so it's too easy to break the incremental send usecase,
  which is the main usecase, if that' for backups breaking the
  continuity is IMNSHO serious usability problem -- and main reason why
  I'm personally looking for other options

Issuing a warning when the ro status is changed by btrfs-progs is only
partially fixing that as the raw ioctl or it's wrapper in libbtrfsutil
will happily destroy the received_uuid. There's no log or other
information that would make it possible to restore it.

Note that received_uuid can be set to any value using the
BTRFS_IOC_SET_RECEIVED_SUBVOL ioctl, as long as the subvolume is
writable.

2) don't allow ro->rw if received_uuid is set, it must be cleared first

As mentioned above, the received_uuid can be changed or reset (setting
all zeros), but there's still the condition that the subvolume must be
writable.

After 'receive' the subvolume is snapshotted, updated from stream, set
received_uuid and set rw->ro.

Reusing the SET_RECEIVED_SUBVOL can't be used as-is, the subvol would
have to be rw first. Which is a chicken-egg problem.

The safe steps would be:

- (after receive, subvolume is RO)
- set it to RW
- clear received_uuid
- either keep it RW or set RO again

This would be the single "clear received_uuid manually" and it would be
up to the user to knowingly destroy the continuity of the incremental
send.

The fix here is that the above steps would have to be atomic from user
perspective, inside SET_RECEIVED_SUBVOL, eg. based on flag. And we'd
have to add a btrfs-progs command somewhere.

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

* Re: [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols
  2021-09-21 18:51 ` David Sterba
@ 2021-09-21 22:08   ` Graham Cobb
  0 siblings, 0 replies; 20+ messages in thread
From: Graham Cobb @ 2021-09-21 22:08 UTC (permalink / raw)
  To: dsterba, Nikolay Borisov, linux-btrfs

On 21/09/2021 19:51, David Sterba wrote:
> On Tue, Sep 14, 2021 at 12:05:50PM +0300, Nikolay Borisov wrote:
>> Here's V2 which takes into account Qu's suggestions, namely:
>>
>> - Add a helper which contains the common code to clear receive-related data
>> - Now there is a single patch which impements the check/clear for both orig and
>> lowmem modes
>> - Added Reviewed-by from Qu.
>>
>>
>> Nikolay Borisov (8):
>>   btrfs-progs: Add btrfs_is_empty_uuid
>>   btrfs-progs: Remove root argument from btrfs_fixup_low_keys
>>   btrfs-progs: Remove fs_info argument from leaf_data_end
>>   btrfs-progs: Remove root argument from btrfs_truncate_item
>>   btrfs-progs: Add btrfs_uuid_tree_remove
>>   btrfs-progs: Implement helper to remove received information of RW
>>     subvol
>>   btrfs-progs: check: Implement removing received data for RW subvols
>>   btrfs-progs: tests: Add test for received information removal
> 
> Patches 2-5 added to devel as they're preparatory and otherwise OK as
> independent cleanups.
> 
> Regarding the rw and received_uuid, it's choosing between these options:
> 
> 1) ro->rw resets received_uuid unconditionally
> 
> Pros:
> - safe as it does not lead to unexpected results after incremental send
> 
> Cons:
> - unconditional, so it's too easy to break the incremental send usecase,
>   which is the main usecase, if that' for backups breaking the
>   continuity is IMNSHO serious usability problem -- and main reason why
>   I'm personally looking for other options
> 
> Issuing a warning when the ro status is changed by btrfs-progs is only
> partially fixing that as the raw ioctl or it's wrapper in libbtrfsutil
> will happily destroy the received_uuid. There's no log or other
> information that would make it possible to restore it.
> 
> Note that received_uuid can be set to any value using the
> BTRFS_IOC_SET_RECEIVED_SUBVOL ioctl, as long as the subvolume is
> writable.

How about...

Add a --force option.

ro->rw with received_uuid non-zero fails without --force, but displays a
message something like:

"Subvolume is a received subvolume (received_uuid
a0fd481e-ac7f-f14f-8bec-f09e3e096344). Setting the subvolume read-write
would remove the received_uuid and prevent the subvolume being
referenced in future btrfs receive operations. To avoid this, take a rw
snapshot of the subvolume instead of setting it rw. If you are happy to
clear the received_uuid, specify the --force option".

Don't bother to explain about the BTRFS_IOC_SET_RECEIVED_SUBVOL ioctl
but at least the received_uuid has been displayed if the user wants to
record it. Maybe even log it in a kernel message - I presume this will
be a fairly rare action.

> 
> 2) don't allow ro->rw if received_uuid is set, it must be cleared first
> 
> As mentioned above, the received_uuid can be changed or reset (setting
> all zeros), but there's still the condition that the subvolume must be
> writable.
> 
> After 'receive' the subvolume is snapshotted, updated from stream, set
> received_uuid and set rw->ro.
> 
> Reusing the SET_RECEIVED_SUBVOL can't be used as-is, the subvol would
> have to be rw first. Which is a chicken-egg problem.
> 
> The safe steps would be:
> 
> - (after receive, subvolume is RO)
> - set it to RW
> - clear received_uuid
> - either keep it RW or set RO again
> 
> This would be the single "clear received_uuid manually" and it would be
> up to the user to knowingly destroy the continuity of the incremental
> send.
> 
> The fix here is that the above steps would have to be atomic from user
> perspective, inside SET_RECEIVED_SUBVOL, eg. based on flag. And we'd
> have to add a btrfs-progs command somewhere.
> 


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

end of thread, other threads:[~2021-09-21 22:14 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-14  9:05 [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Nikolay Borisov
2021-09-14  9:05 ` [PATCH v2 1/8] btrfs-progs: Add btrfs_is_empty_uuid Nikolay Borisov
2021-09-16  7:26   ` Anand Jain
2021-09-20 11:41     ` David Sterba
2021-09-14  9:05 ` [PATCH v2 2/8] btrfs-progs: Remove root argument from btrfs_fixup_low_keys Nikolay Borisov
2021-09-14  9:05 ` [PATCH v2 3/8] btrfs-progs: Remove fs_info argument from leaf_data_end Nikolay Borisov
2021-09-14  9:05 ` [PATCH v2 4/8] btrfs-progs: Remove root argument from btrfs_truncate_item Nikolay Borisov
2021-09-14  9:05 ` [PATCH v2 5/8] btrfs-progs: Add btrfs_uuid_tree_remove Nikolay Borisov
2021-09-14  9:22   ` Qu Wenruo
2021-09-14  9:05 ` [PATCH v2 6/8] btrfs-progs: Implement helper to remove received information of RW subvol Nikolay Borisov
2021-09-14  9:23   ` Qu Wenruo
2021-09-14  9:05 ` [PATCH v2 7/8] btrfs-progs: check: Implement removing received data for RW subvols Nikolay Borisov
2021-09-14  9:25   ` Qu Wenruo
2021-09-14  9:55     ` Nikolay Borisov
2021-09-14  9:05 ` [PATCH v2 8/8] btrfs-progs: tests: Add test for received information removal Nikolay Borisov
2021-09-14  9:30 ` [PATCH v2 0/8] Implement progs support for removing received uuid on RW vols Qu Wenruo
2021-09-14  9:30 ` Qu Wenruo
2021-09-14  9:31   ` Nikolay Borisov
2021-09-21 18:51 ` David Sterba
2021-09-21 22:08   ` Graham Cobb

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).