Home
last modified time | relevance | path

Searched hist:adf02418 (Results 1 – 3 of 3) sorted by relevance

/openbmc/linux/fs/btrfs/
H A Dbackref.hadf02418 Tue Nov 01 11:15:53 CDT 2022 Filipe Manana <fdmanana@suse.com> btrfs: send: skip resolution of our own backref when finding clone source

When doing backref walking to determine a source range to clone from, it
is worthless to collect and resolve our own data backref, as we can't
obviously use it as a clone source and it represents the range we want to
clone into. Collecting the backref implies doing the extra work to resolve
it, doing the search for a file extent item in a subvolume tree, etc.
Skipping the data backref is valid as long as we only have the send root
as the single clone root, otherwise the leaf with the file extent item may
be accessible from another clone root due to shared subtrees created by
snapshots, and therefore we have to collect the backref and resolve it.

So add a callback to the backref walking code to guide it to skip data
backrefs.

This change is part of a patchset comprised of the following patches:

01/17 btrfs: fix inode list leak during backref walking at resolve_indirect_refs()
02/17 btrfs: fix inode list leak during backref walking at find_parent_nodes()
03/17 btrfs: fix ulist leaks in error paths of qgroup self tests
04/17 btrfs: remove pointless and double ulist frees in error paths of qgroup tests
05/17 btrfs: send: avoid unnecessary path allocations when finding extent clone
06/17 btrfs: send: update comment at find_extent_clone()
07/17 btrfs: send: drop unnecessary backref context field initializations
08/17 btrfs: send: avoid unnecessary backref lookups when finding clone source
09/17 btrfs: send: optimize clone detection to increase extent sharing
10/17 btrfs: use a single argument for extent offset in backref walking functions
11/17 btrfs: use a structure to pass arguments to backref walking functions
12/17 btrfs: reuse roots ulist on each leaf iteration for iterate_extent_inodes()
13/17 btrfs: constify ulist parameter of ulist_next()
14/17 btrfs: send: cache leaf to roots mapping during backref walking
15/17 btrfs: send: skip unnecessary backref iterations
16/17 btrfs: send: avoid double extent tree search when finding clone source
17/17 btrfs: send: skip resolution of our own backref when finding clone source

The following test was run on non-debug kernel (Debian's default kernel
config) before and after applying the patchset:

$ cat test-send-many-shared-extents.sh
#!/bin/bash

DEV=/dev/sdh
MNT=/mnt/sdh

umount $DEV &> /dev/null
mkfs.btrfs -f $DEV
mount $DEV $MNT

num_files=50000
num_clones_per_file=50

for ((i = 1; i <= $num_files; i++)); do
xfs_io -f -c "pwrite 0 64K" $MNT/file_$i > /dev/null
echo -ne "\r$i files created..."
done
echo

btrfs subvolume snapshot -r $MNT $MNT/snap1

cloned=0
for ((i = 1; i <= $num_clones_per_file; i++)); do
for ((j = 1; j <= $num_files; j++)); do
cp --reflink=always $MNT/file_$j $MNT/file_${j}_clone_${i}
cloned=$((cloned + 1))
echo -ne "\r$cloned / $((num_files * num_clones_per_file)) clone operations"
done
done
echo

btrfs subvolume snapshot -r $MNT $MNT/snap2

# Unmount and mount again to clear all cached metadata (and data).
umount $DEV
mount $DEV $MNT

start=$(date +%s%N)
btrfs send $MNT/snap2 > /dev/null
end=$(date +%s%N)

dur=$(( (end - start) / 1000000000 ))
echo -e "\nFull send took $dur seconds"

# Unmount and mount again to clear all cached metadata (and data).
umount $DEV
mount $DEV $MNT

start=$(date +%s%N)
btrfs send -p $MNT/snap1 $MNT/snap2 > /dev/null
end=$(date +%s%N)

dur=$(( (end - start) / 1000000000 ))
echo -e "\nIncremental send took $dur seconds"

umount $MNT

Before applying the patchset:

(...)
Full send took 1108 seconds
(...)
Incremental send took 1135 seconds

After applying the whole patchset:

(...)
Full send took 268 seconds (-75.8%)
(...)
Incremental send took 316 seconds (-72.2%)

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
H A Dsend.cadf02418 Tue Nov 01 11:15:53 CDT 2022 Filipe Manana <fdmanana@suse.com> btrfs: send: skip resolution of our own backref when finding clone source

When doing backref walking to determine a source range to clone from, it
is worthless to collect and resolve our own data backref, as we can't
obviously use it as a clone source and it represents the range we want to
clone into. Collecting the backref implies doing the extra work to resolve
it, doing the search for a file extent item in a subvolume tree, etc.
Skipping the data backref is valid as long as we only have the send root
as the single clone root, otherwise the leaf with the file extent item may
be accessible from another clone root due to shared subtrees created by
snapshots, and therefore we have to collect the backref and resolve it.

So add a callback to the backref walking code to guide it to skip data
backrefs.

This change is part of a patchset comprised of the following patches:

01/17 btrfs: fix inode list leak during backref walking at resolve_indirect_refs()
02/17 btrfs: fix inode list leak during backref walking at find_parent_nodes()
03/17 btrfs: fix ulist leaks in error paths of qgroup self tests
04/17 btrfs: remove pointless and double ulist frees in error paths of qgroup tests
05/17 btrfs: send: avoid unnecessary path allocations when finding extent clone
06/17 btrfs: send: update comment at find_extent_clone()
07/17 btrfs: send: drop unnecessary backref context field initializations
08/17 btrfs: send: avoid unnecessary backref lookups when finding clone source
09/17 btrfs: send: optimize clone detection to increase extent sharing
10/17 btrfs: use a single argument for extent offset in backref walking functions
11/17 btrfs: use a structure to pass arguments to backref walking functions
12/17 btrfs: reuse roots ulist on each leaf iteration for iterate_extent_inodes()
13/17 btrfs: constify ulist parameter of ulist_next()
14/17 btrfs: send: cache leaf to roots mapping during backref walking
15/17 btrfs: send: skip unnecessary backref iterations
16/17 btrfs: send: avoid double extent tree search when finding clone source
17/17 btrfs: send: skip resolution of our own backref when finding clone source

The following test was run on non-debug kernel (Debian's default kernel
config) before and after applying the patchset:

$ cat test-send-many-shared-extents.sh
#!/bin/bash

DEV=/dev/sdh
MNT=/mnt/sdh

umount $DEV &> /dev/null
mkfs.btrfs -f $DEV
mount $DEV $MNT

num_files=50000
num_clones_per_file=50

for ((i = 1; i <= $num_files; i++)); do
xfs_io -f -c "pwrite 0 64K" $MNT/file_$i > /dev/null
echo -ne "\r$i files created..."
done
echo

btrfs subvolume snapshot -r $MNT $MNT/snap1

cloned=0
for ((i = 1; i <= $num_clones_per_file; i++)); do
for ((j = 1; j <= $num_files; j++)); do
cp --reflink=always $MNT/file_$j $MNT/file_${j}_clone_${i}
cloned=$((cloned + 1))
echo -ne "\r$cloned / $((num_files * num_clones_per_file)) clone operations"
done
done
echo

btrfs subvolume snapshot -r $MNT $MNT/snap2

# Unmount and mount again to clear all cached metadata (and data).
umount $DEV
mount $DEV $MNT

start=$(date +%s%N)
btrfs send $MNT/snap2 > /dev/null
end=$(date +%s%N)

dur=$(( (end - start) / 1000000000 ))
echo -e "\nFull send took $dur seconds"

# Unmount and mount again to clear all cached metadata (and data).
umount $DEV
mount $DEV $MNT

start=$(date +%s%N)
btrfs send -p $MNT/snap1 $MNT/snap2 > /dev/null
end=$(date +%s%N)

dur=$(( (end - start) / 1000000000 ))
echo -e "\nIncremental send took $dur seconds"

umount $MNT

Before applying the patchset:

(...)
Full send took 1108 seconds
(...)
Incremental send took 1135 seconds

After applying the whole patchset:

(...)
Full send took 268 seconds (-75.8%)
(...)
Incremental send took 316 seconds (-72.2%)

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
H A Dbackref.cadf02418 Tue Nov 01 11:15:53 CDT 2022 Filipe Manana <fdmanana@suse.com> btrfs: send: skip resolution of our own backref when finding clone source

When doing backref walking to determine a source range to clone from, it
is worthless to collect and resolve our own data backref, as we can't
obviously use it as a clone source and it represents the range we want to
clone into. Collecting the backref implies doing the extra work to resolve
it, doing the search for a file extent item in a subvolume tree, etc.
Skipping the data backref is valid as long as we only have the send root
as the single clone root, otherwise the leaf with the file extent item may
be accessible from another clone root due to shared subtrees created by
snapshots, and therefore we have to collect the backref and resolve it.

So add a callback to the backref walking code to guide it to skip data
backrefs.

This change is part of a patchset comprised of the following patches:

01/17 btrfs: fix inode list leak during backref walking at resolve_indirect_refs()
02/17 btrfs: fix inode list leak during backref walking at find_parent_nodes()
03/17 btrfs: fix ulist leaks in error paths of qgroup self tests
04/17 btrfs: remove pointless and double ulist frees in error paths of qgroup tests
05/17 btrfs: send: avoid unnecessary path allocations when finding extent clone
06/17 btrfs: send: update comment at find_extent_clone()
07/17 btrfs: send: drop unnecessary backref context field initializations
08/17 btrfs: send: avoid unnecessary backref lookups when finding clone source
09/17 btrfs: send: optimize clone detection to increase extent sharing
10/17 btrfs: use a single argument for extent offset in backref walking functions
11/17 btrfs: use a structure to pass arguments to backref walking functions
12/17 btrfs: reuse roots ulist on each leaf iteration for iterate_extent_inodes()
13/17 btrfs: constify ulist parameter of ulist_next()
14/17 btrfs: send: cache leaf to roots mapping during backref walking
15/17 btrfs: send: skip unnecessary backref iterations
16/17 btrfs: send: avoid double extent tree search when finding clone source
17/17 btrfs: send: skip resolution of our own backref when finding clone source

The following test was run on non-debug kernel (Debian's default kernel
config) before and after applying the patchset:

$ cat test-send-many-shared-extents.sh
#!/bin/bash

DEV=/dev/sdh
MNT=/mnt/sdh

umount $DEV &> /dev/null
mkfs.btrfs -f $DEV
mount $DEV $MNT

num_files=50000
num_clones_per_file=50

for ((i = 1; i <= $num_files; i++)); do
xfs_io -f -c "pwrite 0 64K" $MNT/file_$i > /dev/null
echo -ne "\r$i files created..."
done
echo

btrfs subvolume snapshot -r $MNT $MNT/snap1

cloned=0
for ((i = 1; i <= $num_clones_per_file; i++)); do
for ((j = 1; j <= $num_files; j++)); do
cp --reflink=always $MNT/file_$j $MNT/file_${j}_clone_${i}
cloned=$((cloned + 1))
echo -ne "\r$cloned / $((num_files * num_clones_per_file)) clone operations"
done
done
echo

btrfs subvolume snapshot -r $MNT $MNT/snap2

# Unmount and mount again to clear all cached metadata (and data).
umount $DEV
mount $DEV $MNT

start=$(date +%s%N)
btrfs send $MNT/snap2 > /dev/null
end=$(date +%s%N)

dur=$(( (end - start) / 1000000000 ))
echo -e "\nFull send took $dur seconds"

# Unmount and mount again to clear all cached metadata (and data).
umount $DEV
mount $DEV $MNT

start=$(date +%s%N)
btrfs send -p $MNT/snap1 $MNT/snap2 > /dev/null
end=$(date +%s%N)

dur=$(( (end - start) / 1000000000 ))
echo -e "\nIncremental send took $dur seconds"

umount $MNT

Before applying the patchset:

(...)
Full send took 1108 seconds
(...)
Incremental send took 1135 seconds

After applying the whole patchset:

(...)
Full send took 268 seconds (-75.8%)
(...)
Incremental send took 316 seconds (-72.2%)

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>