On Tue, Jan 26, 2021 at 7:19 PM Roman Anasal | BDSU <roman.ana...@bdsu.de> wrote: > > Am Montag, den 25.01.2021, 20:51 +0000 schrieb Filipe Manana: > > On Mon, Jan 25, 2021 at 7:51 PM Roman Anasal <roman.ana...@bdsu.de> > > wrote: > > > This is analogous to the preceding patch ("btrfs: send: fix invalid > > > commands for inodes with changed type but same gen") but for > > > changed > > > rdev: > > > > > > When doing an incremental send, if a new inode has the same number > > > as an > > > inode in the parent subvolume, was created with the same generation > > > but > > > has differing rdev it will not be detected as changed and thus not > > > recreated. This will lead to incorrect results on the receiver > > > where the > > > inode will keep the rdev of the inode in the parent subvolume or > > > even > > > fail when also the ref is unchanged. > > > > > > This case does not happen when doing incremental sends with > > > snapshots > > > that are kept read-only by the user all the time, but it may happen > > > if > > > - a snapshot was modified in the same transaction as its parent > > > after it > > > was created > > > - the subvol used as parent was created independently from the sent > > > subvol > > > > > > Example reproducers: > > > > > > # case 1: same ino at same path > > > btrfs subvolume create subvol1 > > > btrfs subvolume create subvol2 > > > mknod subvol1/a c 1 3 > > > mknod subvol2/a c 1 5 > > > btrfs property set subvol1 ro true > > > btrfs property set subvol2 ro true > > > btrfs send -p subvol1 subvol2 | btrfs receive --dump > > > > > > The produced tree state here is: > > > |-- subvol1 > > > | `-- a (ino 257, c 1,3) > > > | > > > `-- subvol2 > > > `-- a (ino 257, c 1,5) > > > > > > Where subvol1/a and subvol2/a are character devices with differing > > > minor > > > numbers but same inode number and same generation. > > > > > > Example output of the receive command: > > > At subvol subvol2 > > > snapshot ./subvol2 uuid=7513941c- > > > 4ef7-f847-b05e-4fdfe003af7b transid=9 parent_uuid=b66f015b-c226- > > > 2548-9e39-048c7fdbec99 parent_transid=9 > > > utimes ./subvol2/ atime=2021-01- > > > 25T17:14:36+0000 mtime=2021-01-25T17:14:36+0000 ctime=2021-01- > > > 25T17:14:36+0000 > > > link ./subvol2/a dest=a > > > unlink ./subvol2/a > > > utimes ./subvol2/ atime=2021-01- > > > 25T17:14:36+0000 mtime=2021-01-25T17:14:36+0000 ctime=2021-01- > > > 25T17:14:36+0000 > > > utimes ./subvol2/a atime=2021-01- > > > 25T17:14:36+0000 mtime=2021-01-25T17:14:36+0000 ctime=2021-01- > > > 25T17:14:36+0000 > > > > > > => the `link` command causes the receiver to fail with: > > > ERROR: link a -> a failed: File exists > > > > > > Second example: > > > # case 2: same ino at different path > > > btrfs subvolume create subvol1 > > > btrfs subvolume create subvol2 > > > mknod subvol1/a c 1 3 > > > mknod subvol2/b c 1 5 > > > btrfs property set subvol1 ro true > > > btrfs property set subvol2 ro true > > > btrfs send -p subvol1 subvol2 | btrfs receive --dump > > > > As I've told you before for the v1 patchset from a week or two ago, > > this is not a supported scenario for incremental sends. > > Incremental sends are meant to be used on RO snapshots of the same > > subvolume, and those snapshots must never be changed after they were > > created. > > > > Incremental sends were simply not designed for these cases, and can > > never be guaranteed to work with such cases. > > > > The bug is not having incremental sends fail right away, with an > > explicit error message, when the send and parent roots aren't RO > > snapshots of the same subvolume. > > I am sorry, I didn't want to anger you or to appear to be just stubborn > by posting this. > > As I wrote in the cover letter I am aware that this is not a supported > use case and I understand that that makes the patches likely to be > rejected.
Ok, now I got the cover letter and the remaining v2 patches. Vger has been having some lag this week, only got the mails during the last evening. Thanks. > As said the reason I _wrote_ the patches was simply to learn more about > the btrfs code and its internals and see if I would be able to > understand it enough. The reason I _submitted_ them was just to > document what I found out so others could have a look into it and just > in case it maybe useful at a later time. > > I also don't want to claim that these will add full support for sending > unrelated roots - they don't! They only handle those very specific edge > cases I found, which are currently _possible_, although still not > supported. > > I took a deeper look into the rest to see if it could be supported: > the comparing algorithm actually works fine, even with completely > unrelated subvolumes (i.e. btrfs_compare_trees, changed_cb, > changed_inode etc.), but the processing of the changes (i.e. > process_recorded_refs etc.) is heavily based on (ino, gen) as > identifying handle, which can not be changed without the high risk of > regression - just as you said in your earlier comments - since side > effects of any changes are hard to see or understand without a very > deep understanding of the whole code; which is why I didn't even try to > touch that parts. > > I apologize if I appeared to be stubborn or ignorant of your feedback! > That really wasn't my intent. > > > > > The produced tree state here is: > > > |-- subvol1 > > > | `-- a (ino 257, c 1,3) > > > | > > > `-- subvol2 > > > `-- b (ino 257, c 1,5) > > > > > > Where subvol1/a and subvol2/b are character devices with differing > > > minor > > > numbers but same inode number and same generation. > > > > > > Example output of the receive command: > > > At subvol subvol2 > > > snapshot ./subvol2 uuid=1c175819- > > > 8b97-0046-a20e-5f95e37cbd40 transid=13 parent_uuid=bad4a908-21b4- > > > 6f40-9a08-6b0768346725 parent_transid=13 > > > utimes ./subvol2/ atime=2021-01- > > > 25T17:18:46+0000 mtime=2021-01-25T17:18:46+0000 ctime=2021-01- > > > 25T17:18:46+0000 > > > link ./subvol2/b dest=a > > > unlink ./subvol2/a > > > utimes ./subvol2/ atime=2021-01- > > > 25T17:18:46+0000 mtime=2021-01-25T17:18:46+0000 ctime=2021-01- > > > 25T17:18:46+0000 > > > utimes ./subvol2/b atime=2021-01- > > > 25T17:18:46+0000 mtime=2021-01-25T17:18:46+0000 ctime=2021-01- > > > 25T17:18:46+0000 > > > > > > => subvol1/a is renamed to subvol2/b instead of recreated to > > > updated > > > rdev which results in received subvol2/b having the wrong minor > > > number: > > > > > > 257 crw-r--r--. 1 root root 1, 3 Jan 25 17:18 subvol2/b > > > > > > Signed-off-by: Roman Anasal <roman.ana...@bdsu.de> > > > --- > > > v2: > > > - add this patch to also handle changed rdev > > > --- > > > fs/btrfs/send.c | 15 ++++++++++----- > > > 1 file changed, 10 insertions(+), 5 deletions(-) > > > > > > diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c > > > index c8b1f441f..ef544525f 100644 > > > --- a/fs/btrfs/send.c > > > +++ b/fs/btrfs/send.c > > > @@ -6263,6 +6263,7 @@ static int changed_inode(struct send_ctx > > > *sctx, > > > struct btrfs_inode_item *right_ii = NULL; > > > u64 left_gen = 0; > > > u64 right_gen = 0; > > > + u64 left_rdev, right_rdev; > > > u64 left_type, right_type; > > > > > > sctx->cur_ino = key->objectid; > > > @@ -6285,6 +6286,8 @@ static int changed_inode(struct send_ctx > > > *sctx, > > > struct btrfs_inode_item); > > > left_gen = btrfs_inode_generation(sctx->left_path- > > > >nodes[0], > > > left_ii); > > > + left_rdev = btrfs_inode_rdev(sctx->left_path- > > > >nodes[0], > > > + left_ii); > > > } else { > > > right_ii = btrfs_item_ptr(sctx->right_path- > > > >nodes[0], > > > sctx->right_path->slots[0], > > > @@ -6300,6 +6303,9 @@ static int changed_inode(struct send_ctx > > > *sctx, > > > right_gen = btrfs_inode_generation(sctx- > > > >right_path->nodes[0], > > > right_ii); > > > > > > + right_rdev = btrfs_inode_rdev(sctx->right_path- > > > >nodes[0], > > > + right_ii); > > > + > > > left_type = S_IFMT & btrfs_inode_mode( > > > sctx->left_path->nodes[0], > > > left_ii); > > > right_type = S_IFMT & btrfs_inode_mode( > > > @@ -6310,7 +6316,8 @@ static int changed_inode(struct send_ctx > > > *sctx, > > > * the inode as deleted+reused because it would > > > generate a > > > * stream that tries to delete/mkdir the root dir. > > > */ > > > - if ((left_gen != right_gen || left_type != > > > right_type) && > > > + if ((left_gen != right_gen || left_type != > > > right_type || > > > + left_rdev != right_rdev) && > > > sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) > > > sctx->cur_inode_recreated = 1; > > > } > > > @@ -6350,8 +6357,7 @@ static int changed_inode(struct send_ctx > > > *sctx, > > > sctx->left_path->nodes[0], > > > left_ii); > > > sctx->cur_inode_mode = btrfs_inode_mode( > > > sctx->left_path->nodes[0], > > > left_ii); > > > - sctx->cur_inode_rdev = btrfs_inode_rdev( > > > - sctx->left_path->nodes[0], > > > left_ii); > > > + sctx->cur_inode_rdev = left_rdev; > > > if (sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) > > > ret = send_create_inode_if_needed(sctx); > > > } else if (result == BTRFS_COMPARE_TREE_DELETED) { > > > @@ -6396,8 +6402,7 @@ static int changed_inode(struct send_ctx > > > *sctx, > > > sctx->left_path->nodes[0], > > > left_ii); > > > sctx->cur_inode_mode = btrfs_inode_mode( > > > sctx->left_path->nodes[0], > > > left_ii); > > > - sctx->cur_inode_rdev = btrfs_inode_rdev( > > > - sctx->left_path->nodes[0], > > > left_ii); > > > + sctx->cur_inode_rdev = left_rdev; > > > ret = send_create_inode_if_needed(sctx); > > > if (ret < 0) > > > goto out; > > > -- > > > 2.26.2 > > > > > > > -- Filipe David Manana, “Whether you think you can, or you think you can't — you're right.”