Commit 1fabe43
btrfs: send: fix duplicated rmdir operations when using extrefs
Commit 29d6d30 ("Btrfs: send, don't send rmdir for same target
multiple times") has fixed an issue that a send stream contained a rmdir
operation for the same directory multiple times. After that fix we keep
track of the last directory for which we sent a rmdir operation and
compare with it before sending a rmdir for the parent inode of a deleted
hardlink we are processing. But there is still a corner case that in
between rmdir dir operations for the same inode we find deleted hardlinks
for other parent inodes, so tracking just the last inode for which we sent
a rmdir operation is not enough.
Hardlinks of a file in the same directory are stored in the same INODE_REF
item, but if the number of hardlinks is too large and can not fit in a
leaf, we use INODE_EXTREF items to store them. The key of an INODE_EXTREF
item is (inode_id, INODE_EXTREF, hash[name, parent ino]), so between two
hardlinks for the same parent directory, we can find others for other
parent directories. For example for the reproducer below we get the
following (from a btrfs inspect-internal dump-tree output):
item 0 key (259 INODE_EXTREF 2309449) itemoff 16257 itemsize 26
index 6925 parent 257 namelen 8 name: foo.6923
item 1 key (259 INODE_EXTREF 2311350) itemoff 16231 itemsize 26
index 6588 parent 258 namelen 8 name: foo.6587
item 2 key (259 INODE_EXTREF 2457395) itemoff 16205 itemsize 26
index 6611 parent 257 namelen 8 name: foo.6609
(...)
So tracking the last directory's inode number does not work in this case
since we process a link for parent inode 257, then for 258 and then back
again for 257, and that second time we process a deleted link for 257 we
think we have not yet sent a rmdir operation.
Fix this by using a rbtree to keep track of all the directories for which
we have already sent rmdir operations, and add those directories to the
'check_dirs' ref list in process_recorded_refs() only if the directory is
not yet in the rbtree, otherwise skip it since it means we have already
sent a rmdir operation for that directory.
The following test script reproduces the problem:
$ cat test.sh
#!/bin/bash
DEV=/dev/sdi
MNT=/mnt/sdi
mkfs.btrfs -f $DEV
mount $DEV $MNT
mkdir $MNT/a $MNT/b
echo 123 > $MNT/a/foo
for ((i = 1; i <= 1000; i++)); do
ln $MNT/a/foo $MNT/a/foo.$i
ln $MNT/a/foo $MNT/b/foo.$i
done
btrfs subvolume snapshot -r $MNT $MNT/snap1
btrfs send $MNT/snap1 -f /tmp/base.send
rm -r $MNT/a $MNT/b
btrfs subvolume snapshot -r $MNT $MNT/snap2
btrfs send -p $MNT/snap1 $MNT/snap2 -f /tmp/incremental.send
umount $MNT
mkfs.btrfs -f $DEV
mount $DEV $MNT
btrfs receive $MNT -f /tmp/base.send
btrfs receive $MNT -f /tmp/incremental.send
rm -f /tmp/base.send /tmp/incremental.send
umount $MNT
When running it, it fails like this:
$ ./test.sh
(...)
At subvol snap1
At snapshot snap2
ERROR: rmdir o257-9-0 failed: No such file or directory
CC: <stable@vger.kernel.org>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Ting-Chang Hou <tchou@synology.com>
[ Updated changelog ]
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>1 parent 17679ac commit 1fabe43
1 file changed
Lines changed: 48 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4102 | 4102 | | |
4103 | 4103 | | |
4104 | 4104 | | |
| 4105 | + | |
| 4106 | + | |
| 4107 | + | |
| 4108 | + | |
| 4109 | + | |
| 4110 | + | |
| 4111 | + | |
| 4112 | + | |
| 4113 | + | |
| 4114 | + | |
| 4115 | + | |
| 4116 | + | |
| 4117 | + | |
| 4118 | + | |
| 4119 | + | |
| 4120 | + | |
| 4121 | + | |
| 4122 | + | |
| 4123 | + | |
| 4124 | + | |
| 4125 | + | |
| 4126 | + | |
| 4127 | + | |
| 4128 | + | |
| 4129 | + | |
| 4130 | + | |
| 4131 | + | |
| 4132 | + | |
| 4133 | + | |
| 4134 | + | |
| 4135 | + | |
| 4136 | + | |
| 4137 | + | |
| 4138 | + | |
| 4139 | + | |
| 4140 | + | |
| 4141 | + | |
| 4142 | + | |
| 4143 | + | |
| 4144 | + | |
| 4145 | + | |
| 4146 | + | |
4105 | 4147 | | |
4106 | 4148 | | |
4107 | 4149 | | |
| |||
4129 | 4171 | | |
4130 | 4172 | | |
4131 | 4173 | | |
| 4174 | + | |
4132 | 4175 | | |
4133 | 4176 | | |
4134 | 4177 | | |
4135 | 4178 | | |
4136 | | - | |
4137 | 4179 | | |
4138 | 4180 | | |
4139 | 4181 | | |
| |||
4437 | 4479 | | |
4438 | 4480 | | |
4439 | 4481 | | |
4440 | | - | |
| 4482 | + | |
4441 | 4483 | | |
4442 | 4484 | | |
4443 | 4485 | | |
| |||
4465 | 4507 | | |
4466 | 4508 | | |
4467 | 4509 | | |
4468 | | - | |
| 4510 | + | |
4469 | 4511 | | |
4470 | 4512 | | |
4471 | 4513 | | |
| |||
4475 | 4517 | | |
4476 | 4518 | | |
4477 | 4519 | | |
4478 | | - | |
| 4520 | + | |
4479 | 4521 | | |
4480 | 4522 | | |
4481 | 4523 | | |
| |||
4509 | 4551 | | |
4510 | 4552 | | |
4511 | 4553 | | |
4512 | | - | |
| 4554 | + | |
4513 | 4555 | | |
4514 | 4556 | | |
4515 | 4557 | | |
| |||
4552 | 4594 | | |
4553 | 4595 | | |
4554 | 4596 | | |
4555 | | - | |
4556 | | - | |
| 4597 | + | |
4557 | 4598 | | |
4558 | 4599 | | |
4559 | 4600 | | |
| |||
4565 | 4606 | | |
4566 | 4607 | | |
4567 | 4608 | | |
4568 | | - | |
4569 | 4609 | | |
4570 | 4610 | | |
4571 | 4611 | | |
| |||
0 commit comments