aboutsummaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
9 daysbtrfs: redirect I/O for remapped block groupsMark Harmstone3-0/+69
Change btrfs_map_block() so that if the block group has the REMAPPED flag set, we call btrfs_translate_remap() to obtain a new address. btrfs_translate_remap() searches the remap tree for a range corresponding to the logical address passed to btrfs_map_block(). If it is within an identity remap, this part of the block group hasn't yet been relocated, and so we use the existing address. If it is within an actual remap, we subtract the start of the remap range and add the address of its destination, contained in the item's payload. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Mark Harmstone <mark@harmstone.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: allow mounting filesystems with remap-tree incompat flagMark Harmstone7-15/+116
If we encounter a filesystem with the remap-tree incompat flag set, validate its compatibility with the other flags, and load the remap tree using the values that have been added to the superblock. The remap-tree feature depends on the free-space-tree, but no-holes and block-group-tree have been made dependencies to reduce the testing matrix. Similarly I'm not aware of any reason why mixed-bg and zoned would be incompatible with remap-tree, but this is blocked for the time being until it can be fully tested. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Mark Harmstone <mark@harmstone.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: add extended version of struct block_group_itemMark Harmstone6-28/+114
Add a struct btrfs_block_group_item_v2, which is used in the block group tree if the remap-tree incompat flag is set. This adds two new fields to the block group item: `remap_bytes` and `identity_remap_count`. `remap_bytes` records the amount of data that's physically within this block group, but nominally in another, remapped block group. This is necessary because this data will need to be moved first if this block group is itself relocated. If `remap_bytes` > 0, this is an indicator to the relocation thread that it will need to search the remap-tree for backrefs. A block group must also have `remap_bytes` == 0 before it can be dropped. `identity_remap_count` records how many identity remap items are located in the remap tree for this block group. When relocation is begun for this block group, this is set to the number of holes in the free-space tree for this range. As identity remaps are converted into actual remaps by the relocation process, this number is decreased. Once it reaches 0, either because of relocation or because extents have been deleted, the block group has been fully remapped and its chunk's device extents are removed. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Mark Harmstone <mark@harmstone.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: rename struct btrfs_block_group field commit_used to last_usedMark Harmstone2-14/+14
Rename the field commit_used in struct btrfs_block_group to last_used, for clarity and consistency with the similar fields we're about to add. It's not obvious that commit_flags means "flags as of the last commit" rather than "flags related to a commit". Signed-off-by: Mark Harmstone <mark@harmstone.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: don't add metadata items for the remap tree to the extent treeMark Harmstone3-1/+35
There is the following potential problem with the remap tree and delayed refs: * Remapped extent freed in a delayed ref, which removes an entry from the remap tree * Remap tree now small enough to fit in a single leaf * Corruption as we now have a level-0 block with a level-1 metadata item in the extent tree One solution to this would be to rework the remap tree code so that it operates via delayed refs. But as we're hoping to remove cow-only metadata items in the future anyway, change things so that the remap tree doesn't have any entries in the extent tree. This also has the benefit of reducing write amplification. We also make it so that the clear_cache mount option is a no-op, as with the extent tree v2, as the free-space tree can no longer be recreated from the extent tree. Finally disable relocating the remap tree itself, which is added back in a later patch. As it is we would get corruption as the traditional relocation method walks the extent tree, and we're removing its metadata items. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Mark Harmstone <mark@harmstone.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: remove remapped block groups from the free-space-treeMark Harmstone2-3/+19
No new allocations can be done from block groups that have the REMAPPED flag set, so there's no value in their having entries in the free-space tree. Prevent a search through the free-space tree being scheduled for such a block group, and prevent any additions to the in-memory free-space tree. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Mark Harmstone <mark@harmstone.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: allow remapped chunks to have zero stripesMark Harmstone2-21/+41
When a chunk has been fully remapped, we are going to set its num_stripes to 0, as it will no longer represent a physical location on disk. Change tree-checker to allow for this, and fix read_one_chunk() to avoid a divide by zero. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Mark Harmstone <mark@harmstone.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: add METADATA_REMAP chunk typeMark Harmstone10-5/+52
Add a new METADATA_REMAP chunk type, which is a metadata chunk that holds the remap tree. This is needed for bootstrapping purposes: the remap tree can't itself be remapped, and must be relocated the existing way, by COWing every leaf. The remap tree can't go in the SYSTEM chunk as space there is limited, because a copy of the chunk item gets placed in the superblock. The changes in fs/btrfs/volumes.h are because we're adding a new block group type bit after the profile bits, and so can no longer rely on the const_ilog2 trick. The sizing to 32MB per chunk, matching the SYSTEM chunk, is an estimate here, we can adjust it later if it proves to be too big or too small. This works out to be ~500,000 remap items, which for a 4KB block size covers ~2GB of remapped data in the worst case and ~500TB in the best case. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Mark Harmstone <mark@harmstone.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: add definitions and constants for remap-treeMark Harmstone8-4/+34
Add an incompat flag for the new remap-tree feature, and the constants and definitions needed to support it. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Mark Harmstone <mark@harmstone.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: add and use helper to compute the available space for a block groupFilipe Manana3-9/+11
We have currently three places that compute how much available space a block group has. Add a helper function for this and use it in those places. Reviewed-by: Boris Burkov <boris@bur.io> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: tag as unlikely error handling in run_one_delayed_ref()Filipe Manana1-3/+5
We don't expect to get errors unless we have a corrupted fs, bad RAM or a bug. So tag the error handling as unlikely. This slightly reduces the module's text size on x86_64 using gcc 14.2.0-19 from Debian. Before this change: $ size fs/btrfs/btrfs.ko text data bss dec hex filename 1939458 172512 15592 2127562 2076ca fs/btrfs/btrfs.ko After this change: $ size fs/btrfs/btrfs.ko text data bss dec hex filename 1939398 172512 15592 2127502 20768e fs/btrfs/btrfs.ko Reviewed-by: Boris Burkov <boris@bur.io> Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: remove unnecessary else branch in run_one_delayed_ref()Filipe Manana1-3/+1
There is no need for an else branch to deal with an unexpected delayed ref type. We can just change the previous branch to deal with this by checking if the ref type is not BTRFS_EXTENT_OWNER_REF_KEY, since that branch is useless as it only sets 'ret' to zero when it's already zero. So merge the two branches. Reviewed-by: Boris Burkov <boris@bur.io> Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: don't BUG() on unexpected delayed ref type in run_one_delayed_ref()Filipe Manana1-8/+12
There is no need to BUG(), we can just return an error and log an error message. Reviewed-by: Boris Burkov <boris@bur.io> Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: use READA_FORWARD_ALWAYS for device extent verificationjinbaohong1-1/+1
btrfs_verify_dev_extents() iterates through the entire device tree during mount to verify dev extents against chunks. Since this function scans the whole tree, READA_FORWARD_ALWAYS is more appropriate than READA_FORWARD. While the device tree is typically small (a few hundred KB even for multi-TB filesystems), using the correct readahead mode for full-tree iteration is more consistent with the intended usage. Signed-off-by: robbieko <robbieko@synology.com> Signed-off-by: jinbaohong <jinbaohong@synology.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: shrink the size of btrfs_deviceQu Wenruo3-11/+12
There are two main causes of holes inside btrfs_device: - The single bytes member of last_flush_error Not only it's a single byte member, but we never really care about the exact error number. - The @devt member Which is placed between two u64 members. Shrink the size of btrfs_device by: - Use a single bit flag for flush error Use BTRFS_DEV_STATE_FLUSH_FAILED so that we no longer need that dedicated member. - Move @devt to the hole after dev_stat_values[] This reduces the size of btrfs_device from 528 to exact 512 bytes for x86_64. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: update comment for delalloc flush and oe wait in btrfs_clone_files()Filipe Manana1-2/+7
Make the comment more detailed about why we need to flush delalloc and wait for ordered extent completion before attempting to invalidate the page cache. Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: remove experimental offload csum modeQu Wenruo4-74/+0
The offload csum mode was introduced to allow developers to compare the performance of generating checksum for data writes at different timings: - During btrfs_submit_chunk() This is the most common one, if any of the following condition is met we go this path: * The csum is fast For now it's CRC32C and xxhash. * It's a synchronous write * Zoned - Delay the checksum generation to a workqueue However since commit dd57c78aec39 ("btrfs: introduce btrfs_bio::async_csum") we no longer need to bother any of them. As if it's an experimental build, async checksum generation at the background will be faster anyway. And if not an experimental build, we won't even have the offload csum mode support. Considering the async csum will be the new default, let's remove the offload csum mode code. There will be no impact to end users, and offload csum mode is still under experimental features. Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: split btrfs_fs_closing() and change return type to boolDavid Sterba2-9/+11
There are two tests in btrfs_fs_closing() but checking the BTRFS_FS_CLOSING_DONE bit is done only in one place load_extent_tree_free(). As this is an inline we can reduce size of the generated code. The types can be also changed to bool as this becomes a simple condition. text data bss dec hex filename 1674006 146704 15560 1836270 1c04ee pre/btrfs.ko 1673772 146704 15560 1836036 1c0404 post/btrfs.ko DELTA: -234 Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: reject single block sized compression earlyQu Wenruo1-12/+8
Currently for an inode that needs compression, even if there is a delalloc range that is single fs block sized and can not be inlined, we will still go through the compression path. Then inside compress_file_range(), we have one extra check to reject single block sized range, and fall back to regular uncompressed write. This rejection is in fact a little too late, we have already allocated memory to async_chunk, delayed the submission, just to fallback to the same uncompressed write. Change the behavior to reject such cases earlier at inode_need_compress(), so for such single block sized range we won't even bother trying to go through compress path. And since the inline small block check is inside inode_need_compress() and compress_file_range() also calls that function, we no longer need a dedicate check inside compress_file_range(). Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: update outdated comment in __add_block_group_free_space()Julia Lawall1-3/+3
The function add_block_group_free_space() was renamed btrfs_add_block_group_free_space() by commit 6fc5ef782988 ("btrfs: add btrfs prefix to free space tree exported functions"). Update the comment accordingly. Do some reorganization of the next few lines to keep the comment within 80 characters. Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: add mount time auto fix for orphan fst entriesQu Wenruo3-0/+113
[BUG] Before btrfs-progs v6.16.1 release, mkfs.btrfs can leave free space tree entries for deleted chunks: # mkfs.btrfs -f -O fst $dev # btrfs ins dump-tree -t chunk $dev btrfs-progs v6.16 chunk tree leaf 22036480 items 4 free space 15781 generation 8 owner CHUNK_TREE leaf 22036480 flags 0x1(WRITTEN) backref revision 1 item 0 key (DEV_ITEMS DEV_ITEM 1) itemoff 16185 itemsize 98 item 1 key (FIRST_CHUNK_TREE CHUNK_ITEM 13631488) itemoff 16105 itemsize 80 ^^^ The first chunk is at 13631488 item 2 key (FIRST_CHUNK_TREE CHUNK_ITEM 22020096) itemoff 15993 itemsize 112 item 3 key (FIRST_CHUNK_TREE CHUNK_ITEM 30408704) itemoff 15881 itemsize 112 # btrfs ins dump-tree -t free-space-tree $dev btrfs-progs v6.16 free space tree key (FREE_SPACE_TREE ROOT_ITEM 0) leaf 30556160 items 13 free space 15918 generation 8 owner FREE_SPACE_TREE leaf 30556160 flags 0x1(WRITTEN) backref revision 1 item 0 key (1048576 FREE_SPACE_INFO 4194304) itemoff 16275 itemsize 8 free space info extent count 1 flags 0 item 1 key (1048576 FREE_SPACE_EXTENT 4194304) itemoff 16275 itemsize 0 free space extent item 2 key (5242880 FREE_SPACE_INFO 8388608) itemoff 16267 itemsize 8 free space info extent count 1 flags 0 item 3 key (5242880 FREE_SPACE_EXTENT 8388608) itemoff 16267 itemsize 0 free space extent ^^^ Above 4 items are all before the first chunk. item 4 key (13631488 FREE_SPACE_INFO 8388608) itemoff 16259 itemsize 8 free space info extent count 1 flags 0 item 5 key (13631488 FREE_SPACE_EXTENT 8388608) itemoff 16259 itemsize 0 free space extent ... This can trigger btrfs check errors. [CAUSE] It's a bug in free space tree implementation of btrfs-progs, which doesn't delete involved fst entries for the to-be-deleted chunk/block group. [ENHANCEMENT] The mostly common fix is to clear the space cache and rebuild it, but that requires a ro->rw remount which may not be possible for rootfs, and also relies on users to use "clear_cache" mount option manually. Here introduce a kernel fix for it, which will delete any entries that is before the first block group automatically at the first RW mount. For filesystems without such problem, the overhead is just a single tree search and no modification to the free space tree, thus the overhead should be minimal. Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: simplify check for zoned NODATASUM writes in btrfs_submit_chunk()Zhen Ni1-2/+1
This function already dereferences 'inode' multiple times earlier, making the additional NULL check at line 840 redundant since the function would have crashed already if inode were NULL. After commit 81cea6cd7041 ("btrfs: remove btrfs_bio::fs_info by extracting it from btrfs_bio::inode"), the btrfs_bio::inode field is mandatory for all btrfs_bio allocations and is guaranteed to be non-NULL. Simplify the condition for allocating dummy checksums for zoned NODATASUM data by removing the unnecessary 'inode &&' check. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Zhen Ni <zhen.ni@easystack.cn> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: avoid transaction commit on error in insert_balance_item()Filipe Manana1-4/+6
There's no point in committing the transaction if we failed to insert the balance item, since we haven't done anything else after we started/joined the transaction. Also stop using two variables for tracking the return value and use only 'ret'. Reviewed-by: Daniel Vacek <neelx@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: move unlikely checks around btrfs_is_shutdown() into the helperFilipe Manana5-13/+13
Instead of surrounding every caller of btrfs_is_shutdown() with unlikely, move the unlikely into the helper itself, like we do in other places in btrfs and is common in the kernel outside btrfs too. Also make the fs_info argument of btrfs_is_shutdown() const. On a x86_84 box using gcc 14.2.0-19 from Debian, this resulted in a slight reduction of the module's text size. Before: $ size fs/btrfs/btrfs.ko text data bss dec hex filename 1939044 172568 15592 2127204 207564 fs/btrfs/btrfs.ko After: $ size fs/btrfs/btrfs.ko text data bss dec hex filename 1938876 172568 15592 2127036 2074bc fs/btrfs/btrfs.ko Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: tag as unlikely error conditions in the transaction commit pathFilipe Manana1-22/+22
Errors are unexpected during the transaction commit path, and when they happen we abort the transaction (by calling cleanup_transaction() under the label 'cleanup_transaction' in btrfs_commit_transaction()). So mark every error check in the transaction commit path as unlikely, to hint the compiler so that it can possibly generate better code, and make it clear for a reader about being unexpected. On a x86_84 box using gcc 14.2.0-19 from Debian, this resulted in a slight reduction of the module's text size. Before: $ size fs/btrfs/btrfs.ko text data bss dec hex filename 1939476 172568 15592 2127636 207714 fs/btrfs/btrfs.ko After: $ size fs/btrfs/btrfs.ko text data bss dec hex filename 1939044 172568 15592 2127204 207564 fs/btrfs/btrfs.ko Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: remove unreachable return after btrfs_backref_panic() in ↵Zhen Ni1-3/+1
btrfs_backref_finish_upper_links() The return statement after btrfs_backref_panic() is unreachable since btrfs_backref_panic() calls BUG() which never returns. Remove the return to unify it with the other calls to btrfs_backref_panic(). Signed-off-by: Zhen Ni <zhen.ni@easystack.cn> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: refactor the main loop of cow_file_range()Qu Wenruo1-103/+142
Currently inside the main loop of cow_file_range(), we do the following sequence: - Reserve an extent - Lock the IO tree range - Create an IO extent map - Create an ordered extent Every step will need extra steps to do cleanup in the following order: - Drop the newly created extent map - Unlock extent range and cleanup the involved folios - Free the reserved extent However currently the error handling is done inconsistently: - Extent map drop is handled in a dedicated tag Out of the main loop, make it much harder to track. - The extent unlock and folios cleanup is done separately The extent is unlocked through btrfs_unlock_extent(), then extent_clear_unlock_delalloc() again in a dedicated tag. Meanwhile all other callsites (compression/encoded/nocow) all just call extent_clear_unlock_delalloc() to handle unlock and folio clean up in one go. - Reserved extent freeing is handled in a dedicated tag Out of the main loop, make it much harder to track. - Error handling of btrfs_reloc_clone_csums() is relying out-of-loop tags This is due to the special requirement to finish ordered extents to handle the metadata reserved space. Enhance the error handling and align the behavior by: - Introduce a dedicated cow_one_range() helper Which do the reserve/lock/allocation in the helper. And also handle the errors inside the helper. No more dedicated tags out of the main loop. - Use a single extent_clear_unlock_delalloc() to unlock and cleanup folios - Move the btrfs_reloc_clone_csums() error handling into the new helper Thankfully it's not that complex compared to other cases. And since we're here, also reduce the width of the following local variables to u32: - cur_alloc_size - min_alloc_size Each allocation won't go beyond 128M, thus u32 is more than enough. - blocksize The maximum is 64K, no need for u64. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: zoned: print block-group type for zoned statisticsJohannes Thumshirn1-2/+3
When printing the zoned statistics, also include the block-group type in the block-group listing output. The updated output looks as follows: device /dev/vda mounted on /mnt with fstype btrfs zoned statistics: active block-groups: 9 reclaimable: 0 unused: 2 need reclaim: false data relocation block-group: 3221225472 active zones: start: 1073741824, wp: 268419072 used: 268419072, reserved: 0, unusable: 0 (DATA) start: 1342177280, wp: 0 used: 0, reserved: 0, unusable: 0 (DATA) start: 1610612736, wp: 81920 used: 16384, reserved: 16384, unusable: 49152 (SYSTEM) start: 1879048192, wp: 2031616 used: 1458176, reserved: 65536, unusable: 507904 (METADATA) start: 2147483648, wp: 268419072 used: 268419072, reserved: 0, unusable: 0 (DATA) start: 2415919104, wp: 268419072 used: 268419072, reserved: 0, unusable: 0 (DATA) start: 2684354560, wp: 268419072 used: 268419072, reserved: 0, unusable: 0 (DATA) start: 2952790016, wp: 65536 used: 65536, reserved: 0, unusable: 0 (DATA) start: 3221225472, wp: 0 used: 0, reserved: 0, unusable: 0 (DATA) Reviewed-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: move space_info_flag_to_str() to space-info.hJohannes Thumshirn2-17/+17
Move space_info_flag_to_str() to space-info.h and as it now isn't static to space-info.c any more prefix it with 'btrfs_'. This way it can be re-used in other places. Reviewed-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: zoned: show statistics about zoned filesystems in mountstatsJohannes Thumshirn3-0/+75
Add statistics output to /proc/<pid>/mountstats for zoned BTRFS, similar to the zoned statistics from XFS in mountstats. The output for /proc/<pid>/mountstats on an example filesystem will be as follows: device /dev/vda mounted on /mnt with fstype btrfs zoned statistics: active block-groups: 7 reclaimable: 0 unused: 5 need reclaim: false data relocation block-group: 1342177280 active zones: start: 1073741824, wp: 268419072 used: 0, reserved: 268419072, unusable: 0 start: 1342177280, wp: 0 used: 0, reserved: 0, unusable: 0 start: 1610612736, wp: 49152 used: 16384, reserved: 16384, unusable: 16384 start: 1879048192, wp: 950272 used: 131072, reserved: 622592, unusable: 196608 start: 2147483648, wp: 212238336 used: 0, reserved: 212238336, unusable: 0 start: 2415919104, wp: 0 used: 0, reserved: 0, unusable: 0 start: 2684354560, wp: 0 used: 0, reserved: 0, unusable: 0 Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com> Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: don't call btrfs_handle_fs_error() in btrfs_commit_transaction()Filipe Manana1-3/+2
There's no need to call btrfs_handle_fs_error() as we are inside a transaction and if we get an error we jump to the 'scrub_continue' label and end up calling cleanup_transaction(), which aborts the transaction. This is odd given that we have a transaction handle and that in the transaction commit path any error makes us abort the transaction and it's the only place that calls btrfs_handle_fs_error(). Remove the btrfs_handle_fs_error() call and replace it with an error message so that if it happens we know what went wrong during the transaction commit. Also annotate the condition in the if statement with 'unlikely' since this is not expected to happen. We've been wanting to remove btrfs_handle_fs_error(), so this removes one user that does not even needs it. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: don't call btrfs_handle_fs_error() in qgroup_account_snapshot()Filipe Manana1-3/+3
There's no need to call btrfs_handle_fs_error() as we are inside a transaction and we propagate the error returned from btrfs_write_and_wait_transaction() to the caller and it ends going up the call chain to btrfs_commit_transaction() (returned by the call to create_pending_snapshots()), where we jump to the 'unlock_reloc' label and end up calling cleanup_transaction(), which aborts the transaction. This is odd given that we have a transaction handle and that in the transaction commit path any error makes us abort the transaction and, besides another place inside btrfs_commit_transaction(), it's the only place that calls btrfs_handle_fs_error(). Remove the btrfs_handle_fs_error() call and replace it with an error message so that if it happens we know what went wrong during the transaction commit. Also annotate the condition in the if statement with 'unlikely' since this is not expected to happen. We've been wanting to remove btrfs_handle_fs_error(), so this removes one user that does not even need it. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: don't call btrfs_handle_fs_error() after failure to delete orphan itemFilipe Manana1-2/+2
In btrfs_find_orphan_roots() we don't need to call btrfs_handle_fs_error() if we fail to delete the orphan item for the current root. This is because we haven't done anything yet regarding the current root and previous iterations of the loop dealt with other roots, so there's nothing we need to undo. Instead log an error message and return the error to the caller, which will result either in a mount failure or remount failure (the only contexts it's called from). Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: don't call btrfs_handle_fs_error() after failure to join transactionFilipe Manana1-2/+3
In btrfs_find_orphan_roots() we don't need to call btrfs_handle_fs_error() if we fail to join a transaction. This is because we haven't done anything yet regarding the current root and previous iterations of the loop dealt with other roots, so there's nothing we need to undo. Instead log an error message and return the error to the caller, which will result either in a mount failure or remount failure (the only contexts it's called from). Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: remove redundant path release in btrfs_find_orphan_roots()Filipe Manana1-2/+0
There's no need to release the path in the if branch used when the root does not exists since we released the path before the call to btrfs_get_fs_root(). So remove that redundant btrfs_release_path() call. Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: use single return variable in btrfs_find_orphan_roots()Filipe Manana1-22/+18
We use both 'ret' and 'err' which is a pattern that generates confusion and resulted in subtle bugs in the past. Remove 'err' and use only 'ret'. Also move simplify the error flow by directly returning from the function instead of breaking of the loop, since there are no resources to cleanup after the loop. Reviewed-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: avoid transaction commit on error in del_balance_item()Filipe Manana1-4/+6
There's no point in committing the transaction if we failed to delete the item, since we haven't done anything before. Also stop using two variables for tracking the return value and use only 'ret'. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: update stale comment in __cow_file_range_inline()Filipe Manana1-2/+2
We mention that the reserved data space is page size aligned but that's not true anymore, as it's sector size aligned instead. In commit 0bb067ca64e3 ("btrfs: fix the qgroup data free range for inline data extents") we updated the amount passed to btrfs_qgroup_free_data() from page size to sector size, but forgot to update the comment. Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: remove duplicated root key setup in btrfs_create_tree()Filipe Manana1-5/+1
There's no need for an on stack key to define the root's key as we have already defined the key in the root itself. So remove the stack variable and use the key in the root. Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: zoned: re-flow prepare_allocation_zoned()Johannes Thumshirn1-17/+24
Re-flow prepare allocation zoned to make it a bit more readable by returning early and removing unnecessary indentations. This patch does not change any functionality. Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: shrink the size of btrfs_bioQu Wenruo1-7/+8
This is done by: - Shrink the size of btrfs_bio::mirror_num From 32 bits unsigned int to u16. Normally btrfs mirror number is either 0 (all profiles), 1 (all profiles), 2 (DUP/RAID1/RAID10/RAID5), 3 (RAID1C3) or 4 (RAID1C4). But for RAID6 the mirror number can go as large as the number of devices of that chunk. Currently the limit for number of devices for a data chunk is BTRFS_MAX_DEVS(), which is around 500 for the default 16K nodesize. And if going the max 64K nodesize, we can have a little over 2000 devices for a chunk. Although I'd argue it's way overkilled, we don't reject such cases yet thus u8 is not going to cut it, and have to use u16 (max out at 64K). - Use bit fields for boolean members Although it's not always safe for racy call sites, those members are safe. * csum_search_commit_root * is_scrub Those two are set immediately after bbio allocation and no more writes after allocation, thus they are very safe. * async_csum * can_use_append Those two are set for each split range, and after that there is no writes into those two members in different threads, thus they are also safe. And there are spaces for 4 more bits before increasing the size of btrfs_bio again, which should be future proof enough. - Reorder the structure members Now we always put the largest member first (after the huge 120 bytes union), making it easier to fill any holes. This reduce the size of btrfs_bio by 8 bytes, from 312 bytes to 304 bytes. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: remove ASSERT compatibility for gcc < 8.xDavid Sterba1-17/+0
The minimum gcc version is 8 since 118c40b7b50340 ("kbuild: require gcc-8 and binutils-2.30"), the workaround for missing __VA_OPT__ support is not needed. Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: pass level to _btrfs_printk() to avoid parsing level from stringDavid Sterba2-45/+30
There's code in _btrfs_printk() to parse the message level from the input string so we can augment the message with the level description for better visibility in the logs. The parsing code has evolved over time, see commits: - 40f7828b36e3b9 ("btrfs: better handle btrfs_printk() defaults") - 262c5e86fec7cf ("printk/btrfs: handle more message headers") - 533574c6bc30cf ("btrfs: use printk_get_level and printk_skip_level, add __printf, fix fallout") - 4da35113426d16 ("btrfs: add varargs to btrfs_error") As we are using the specific level helpers everywhere we can simply pass the message level so we don't have to parse it. The proper printk() message header is created as KERN_SOH + "level". Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: simplify internal btrfs_printk helpersDavid Sterba1-5/+13
The printk() can be compiled out depending on CONFIG_PRINTK, this is reflected in our helpers. The indirection is provided by btrfs_printk() used in the ratelimited and RCU wrapper macros. Drop the btrfs_printk() helper and define the ratelimit and RCU helpers directly when CONFIG_PRINTK is undefined. This will allow further changes to the _btrfs_printk() interface (which is internal), any message in other code should use the level-specific helpers. Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: rename btrfs_create_block_group_cache to btrfs_create_block_groupJohannes Thumshirn1-4/+4
struct btrfs_block_group used to be called struct btrfs_block_group_cache but got renamed to btrfs_block_group with commit 32da5386d9a4 ("btrfs: rename btrfs_block_group_cache"). Rename btrfs_create_block_group_cache() to btrfs_create_block_group() to reflect that change. Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: merge setting ret and return retDavid Sterba13-63/+32
In many places we have pattern: ret = ...; return ret; This can be simplified to a direct return, removing 'ret' if not otherwise needed. The places in self tests are not converted so we can add more test cases without changing surrounding code (extent-map-tests.c:test_case_4()). Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: remove dead assignment in prepare_one_folio()Massimiliano Pellizzer1-4/+2
In prepare_one_folio(), ret is initialized to 0 at declaration, and in an error path we assign ret = 0 before jumping to the again label to retry the operation. However, ret is immediately overwritten by ret = set_folio_extent_mapped(folio) after the again label. Both assignments are never observed by any code path, therefore they can be safely removed. Signed-off-by: Massimiliano Pellizzer <mpellizzer.dev@gmail.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: replace for_each_set_bit() with for_each_set_bitmap()Qu Wenruo1-10/+16
Inside extent_io.c, there are several simple call sites doing things like: for_each_set_bit(bit, bitmap, bitmap_size) { /* handle one fs block */ } The workload includes: - set_bit() Inside extent_writepage_io(). This can be replaced with a bitmap_set(). - btrfs_folio_set_lock() - btrfs_mark_ordered_io_finished() Inside writepage_delalloc(). Instead of calling it multiple times, we can pass a range into the function with one call. Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: concentrate the error handling of submit_one_sector()Qu Wenruo1-14/+15
Currently submit_one_sector() has only one failure path from btrfs_get_extent(). However the error handling is split into two parts, one inside submit_one_sector(), which clears the dirty flag and finishes the writeback for the fs block. The other part is to submit any remaining bio inside bio_ctrl and mark the ordered extent finished for the fs block. There is no special reason that we must split the error handling, let's just concentrate all the error handling into submit_one_sector(). Reviewed-by: Boris Burkov <boris@bur.io> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
9 daysbtrfs: search for larger extent maps inside btrfs_do_readpage()Qu Wenruo1-1/+14
[CORNER CASE] If we have the following file extents layout, btrfs_get_extent() can return a smaller hole during read, and cause unnecessary extra tree searches: item 6 key (257 EXTENT_DATA 0) itemoff 15810 itemsize 53 generation 9 type 1 (regular) extent data disk byte 13631488 nr 4096 extent data offset 0 nr 4096 ram 4096 extent compression 0 (none) item 7 key (257 EXTENT_DATA 32768) itemoff 15757 itemsize 53 generation 9 type 1 (regular) extent data disk byte 13635584 nr 4096 extent data offset 0 nr 4096 ram 4096 extent compression 0 (none) In above case, range [0, 4K) and [32K, 36K) are regular extents, and there is a hole in range [4K, 32K), and the fs has "no-holes" feature, meaning the hole will not have a file extent item. [INEFFICIENCY] Assume the system has 4K page size, and we're doing readahead for range [4K, 32K), no large folio yet. btrfs_readahead() for range [4K, 32K) |- btrfs_do_readpage() for folio 4K | |- get_extent_map() for range [4K, 8K) | |- btrfs_get_extent() for range [4K, 8K) | We hit item 6, then for the next item 7. | At this stage we know range [4K, 32K) is a hole. | But our search range is only [4K, 8K), not reaching 32K, thus | we go into not_found: tag, returning a hole em for [4K, 8K). | |- btrfs_do_readpage() for folio 8K | |- get_extent_map() for range [8K, 12K) | |- btrfs_get_extent() for range [8K, 12K) | We hit the same item 6, and then item 7. | But still we goto not_found tag, inserting a new hole