On Mon, 2021-01-11 at 22:30 +0300, Andrei Borzenkov wrote: > 11.01.2021 22:02, Roman Anasal пишет: > > When doing a send, if a new inode has the same number as an inode > > in the > > parent subvolume it will only be detected as to be recreated when > > the > > genrations differ. But with inodes in the same generation the > > emitted > > commands will cause the receiver to fail. > > > > 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 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 > > mkdir subvol1/a > > touch subvol2/a > > What happens in case of > > echo foo > subvol1/a > echo bar > subvol2/a > > ?
`echo foo > subvol1/a` wouldn't work since subvol1/a is a directory. However, replacing both preceding lines with: mkdir subvol1/a echo bar > subvol2/a => same as before with/without the patch, plus an additional write command for the content And with both lines as echo foo > subvol1/a echo bar > subvol2/a => produces an invalid stream (with and without this patch) with a `link a -> a` followed by `unlink a` as seen in the example output quoted further below. So there is another bug here. The conditions for this seem to roughly be: changed/new inode with same number, type and generation, since reordering the commands so the inodes have different generations produces a valid stream. Changing the name to subvol2/b like in the second case below produces a valid stream with a `link b -> a` followed by `unlink a`. I'll take a look into this, too, and if possible provide another patch for that case. > > 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) > > | > > `-- subvol2 > > `-- a (ino 257) > > > > Where subvol1/a/ is a directory and subvol2/a is a file with the > > same > > inode number and same generation. > > > > Example output of the receive command: > > At subvol subvol2 > > snapshot ./subvol2 uuid=19d2be0a- > > 5af1-fa44-9b3f-f21815178d00 transid=9 parent_uuid=1bac8b12-ddb2- > > 6441-8551-700456991785 parent_transid=9 > > utimes ./subvol2/ atime=2021-01- > > 11T13:41:36+0000 mtime=2021-01-11T13:41:36+0000 ctime=2021-01- > > 11T13:41:36+0000 > > link ./subvol2/a dest=a > > unlink ./subvol2/a > > utimes ./subvol2/ atime=2021-01- > > 11T13:41:36+0000 mtime=2021-01-11T13:41:36+0000 ctime=2021-01- > > 11T13:41:36+0000 > > chmod ./subvol2/a mode=644 > > utimes ./subvol2/a atime=2021-01- > > 11T13:41:36+0000 mtime=2021-01-11T13:41:36+0000 ctime=2021-01- > > 11T13:41: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 > > mkdir subvol1/a > > touch subvol2/b > > 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) > > | > > `-- subvol2 > > `-- b (ino 257) > > > > Where subvol1/a/ is a directory and subvol2/b is a file with the > > same > > inode number and same generation. > > > > Example output of the receive command: > > At subvol subvol2 > > snapshot ./subvol2 uuid=ea93c47a- > > 5f47-724f-8a43-e15ce745aef0 transid=20 parent_uuid=f03578ef-5bca- > > 1445-a480-3df63677fddf parent_transid=20 > > utimes ./subvol2/ atime=2021-01- > > 11T13:58:00+0000 mtime=2021-01-11T13:58:00+0000 ctime=2021-01- > > 11T13:58:00+0000 > > link ./subvol2/b dest=a > > unlink ./subvol2/a > > utimes ./subvol2/ atime=2021-01- > > 11T13:58:00+0000 mtime=2021-01-11T13:58:00+0000 ctime=2021-01- > > 11T13:58:00+0000 > > chmod ./subvol2/b mode=644 > > utimes ./subvol2/b atime=2021-01- > > 11T13:58:00+0000 mtime=2021-01-11T13:58:00+0000 ctime=2021-01- > > 11T13:58:00+0000 > > > > => the `link` command causes the receiver to fail with: > > ERROR: link b -> a failed: Operation not permitted > > > > Signed-off-by: Roman Anasal <roman.ana...@bdsu.de>