| Age | Commit message (Collapse) | Author |
|
https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
|
|
|
|
|
|
Free space inode data was only read when loading the v1 cache, which is
gone, so btrfs_get_extent() and btrfs_lookup_bio_sums() no longer need
to search the commit root for them.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Free space inodes never have delalloc or outstanding extents any more,
so they don't need to be kept off the root's delalloc inode list or out
of the outstanding extents tracepoint.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Free space inodes are never written anymore, so drop the special cases
for them in cow_file_range(), fallback_to_cow(),
can_nocow_file_extent() and btrfs_finish_one_ordered().
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Free space inodes never have ordered extents anymore. Drop the lockdep
exceptions for them and btrfs_join_transaction_spacecache(), which was
only used to finish their ordered extents during a commit.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Free space inodes no longer reserve data or delalloc space, as nothing
writes to them. Remove the flush mode and the special cases that
selected it.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
cache_writeout_mutex and trimming_ranges let the v1 cache writer see
ranges that were unlinked from the free space tree while being
discarded. Nothing consumes the list anymore, and the tree itself is
protected by tree_lock, so remove them.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
The only caller passes active = false. Turn it into
btrfs_cleanup_free_space_cache_v1() and fold the block group loop into
it.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Nothing sets BTRFS_MOUNT_SPACE_CACHE anymore, so every test of it is
false. Remove the flag, the checks rejecting the v1 cache on zoned
filesystems and for sector sizes other than the page size, and the
deprecation warning. Show a read-only filesystem that still has an old
cache as nospace_cache, since that's what's in effect. space_cache and
space_cache=v1 keep falling back to no space cache with a warning.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
With neither the writer nor the loader left, nothing acts on
disk_cache_state. Remove it, the need_clear handling when reading block
groups, and the enum. While at it, drop the unused cache_generation
field from struct btrfs_block_group.
lookup_free_space_inode() converted old style space inodes by clearing
disk_cache_state so the cache would be rewritten with the new inode
flags. Without that it only sets flags on the in-memory inode, which
every remaining caller truncates or deletes right after, so drop the
conversion too.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Nothing writes a v1 space cache any more, and since commit 545e560a5b0f
("btrfs: disable v1 space cache") the mount option can't be enabled to
read one either. Remove load_free_space_cache(), its io_ctl helpers and
struct btrfs_io_ctl. Drop the gfp constraint on the inode mapping as
well, it only covered the cache's page cache allocations.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
The v1 space cache created its inode during the transaction commit, and
btrfs_prealloc_file_range_trans() existed so that preallocation could
reuse the open handle. It was the only caller passing a transaction, so
__btrfs_prealloc_file_range() and insert_prealloc_file_extent() now
always start their own. Fold the wrapper into
btrfs_prealloc_file_range() and drop the parameter.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
The v1 space cache writeout is gone, but the mutex is still needed. It
keeps btrfs_remove_block_group() from deleting a block group item while
btrfs_start_dirty_block_groups() is updating it outside the commit
critical section.
Rename it to reflect what it protects, and update the comments around
the dirty block group writeout that still refer to the space cache.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Nothing writes out a v1 space cache any more. Remove the writers and
their io_ctl helpers, along with create_free_space_inode() and
btrfs_prealloc_file_range_trans(), whose only user was the cache inode
creation. The io_list and io_ctl block group fields were only used by
the writers, so remove them too.
btrfs_truncate_free_space_cache() only needed the block group to wait
for and clear in-flight cache IO, so drop that parameter.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Free space inodes are no longer written to, so nothing queues ordered
extent completion on endio_freespace_worker. Remove it and always use
endio_write_workers in btrfs_queue_ordered_fn().
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Nothing sets SPACE_CACHE anymore, so the dirty block group writers never
have a cache to write out or wait for. Remove cache_save_setup(),
btrfs_setup_space_cache(), the io_list handling, the io_bgs list and
BTRFS_TRANS_CACHE_ENOSPC, and the abort-time cleanup of in-flight cache
IO.
The -ENOENT retry in btrfs_write_dirty_block_groups() handled a free
space endio worker creating a block group during the commit critical
section, so drop it too.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Since commit 545e560a5b0f ("btrfs: disable v1 space cache") the mount
options can no longer request the v1 space cache, but a filesystem with
an active v1 cache and no free space tree still enables it from
cache_generation, and remount does the same. Drop both, so SPACE_CACHE
can never be set.
btrfs_start_pre_rw_mount() then sees the on-disk cache as active but
unwanted and cleans it up, as -o nospace_cache does today. That covers
the read-only to read-write remount as well, so drop the toggle in
btrfs_remount_cleanup(), which would otherwise start a transaction on
remounts of a read-only filesystem with an old cache.
The cleanup is now unconditional, and the first read-write mount fails
if it fails, as it did with -o nospace_cache. This also lets an old
filesystem mount without options when the page size is larger than the
sector size, which btrfs_check_features() rejected once SPACE_CACHE was
set from the superblock.
Assisted-by: Claude:claude-fable-5-1
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Any commits after this one are for testing and evaluation only.
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
[BUG]
There is a syzbot report that a use-after-free bug is triggered after a
failed btrfs_quota_enable():
loop0: detected capacity change from 32768 to 0
==================================================================
BUG: KASAN: slab-use-after-free in __list_add_valid_or_report+0x4e/0x130 lib/list_debug.c:29
Read of size 8 at addr ffff888040e0a528 by task syz.0.0/5324
CPU: 0 UID: 0 PID: 5324 Comm: syz.0.0 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
print_address_description+0x55/0x1e0 mm/kasan/report.c:378
print_report+0x58/0x70 mm/kasan/report.c:482
kasan_report+0x117/0x150 mm/kasan/report.c:595
__list_add_valid_or_report+0x4e/0x130 lib/list_debug.c:29
__list_add_valid include/linux/list.h:104 [inline]
__list_add include/linux/list.h:169 [inline]
list_add include/linux/list.h:192 [inline]
list_move include/linux/list.h:345 [inline]
add_root_to_dirty_list+0x38b/0x470 fs/btrfs/ctree.c:232
btrfs_force_cow_block+0xf09/0x1bf0 fs/btrfs/ctree.c:553
btrfs_cow_block+0x3f1/0xaf0 fs/btrfs/ctree.c:696
btrfs_search_slot+0xd70/0x2d20 fs/btrfs/ctree.c:-1
btrfs_search_prev_slot fs/btrfs/free-space-tree.c:134 [inline]
remove_free_space_extent fs/btrfs/free-space-tree.c:732 [inline]
__btrfs_remove_from_free_space_tree fs/btrfs/free-space-tree.c:837 [inline]
btrfs_remove_from_free_space_tree+0x4d6/0xda0 fs/btrfs/free-space-tree.c:866
alloc_reserved_extent+0x4a/0x2b0 fs/btrfs/extent-tree.c:4976
alloc_reserved_tree_block fs/btrfs/extent-tree.c:5155 [inline]
run_delayed_tree_ref fs/btrfs/extent-tree.c:1815 [inline]
run_one_delayed_ref fs/btrfs/extent-tree.c:1851 [inline]
btrfs_run_delayed_refs_for_head fs/btrfs/extent-tree.c:2058 [inline]
__btrfs_run_delayed_refs+0x18b5/0x43b0 fs/btrfs/extent-tree.c:2134
btrfs_run_delayed_refs+0xdc/0x2a0 fs/btrfs/extent-tree.c:2246
btrfs_commit_transaction+0x28a/0x3170 fs/btrfs/transaction.c:2267
sync_filesystem+0x1d2/0x240 fs/sync.c:66
btrfs_reconfigure+0x2dc/0x2100 fs/btrfs/super.c:1511
reconfigure_super+0x232/0x8f0 fs/super.c:1128
do_remount fs/namespace.c:3410 [inline]
path_mount+0xd4e/0x1050 fs/namespace.c:4160
do_mount fs/namespace.c:4181 [inline]
__do_sys_mount fs/namespace.c:4397 [inline]
__se_sys_mount+0x31d/0x420 fs/namespace.c:4374
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f9c8dd9f3ca
</TASK>
Allocated by task 5323:
kasan_save_stack mm/kasan/common.c:57 [inline]
kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
poison_kmalloc_redzone mm/kasan/common.c:409 [inline]
__kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:426
kasan_kmalloc include/linux/kasan.h:263 [inline]
__kmalloc_cache_noprof+0x321/0x600 mm/slub.c:5563
_kmalloc_noprof include/linux/slab.h:991 [inline]
_kzalloc_noprof include/linux/slab.h:1312 [inline]
btrfs_alloc_root+0x75/0x840 fs/btrfs/disk-io.c:638
btrfs_create_tree+0xa8/0x5c0 fs/btrfs/disk-io.c:832
btrfs_quota_enable+0x3d6/0x1e20 fs/btrfs/qgroup.c:1074
btrfs_ioctl_quota_ctl+0x186/0x1f0 fs/btrfs/ioctl.c:3581
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 5323:
kasan_save_stack mm/kasan/common.c:57 [inline]
kasan_save_track+0x3e/0x80 mm/kasan/common.c:78
kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:584
poison_slab_object mm/kasan/common.c:264 [inline]
__kasan_slab_free+0x5c/0x80 mm/kasan/common.c:296
kasan_slab_free include/linux/kasan.h:235 [inline]
slab_free_hook mm/slub.c:2748 [inline]
slab_free mm/slub.c:6508 [inline]
kfree+0x1c5/0x650 mm/slub.c:6801
btrfs_quota_enable+0x1208/0x1e20 fs/btrfs/qgroup.c:1292
btrfs_ioctl_quota_ctl+0x186/0x1f0 fs/btrfs/ioctl.c:3581
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
[CAUSE]
During btrfs_quota_enable(), a temporary quota_root is created, then
qgroup items are created for each subvolume and inserted into that root.
If there are enough subvolumes, the level of quota_root will be bumped,
and add_root_to_dirty_list() will be called, adding
quota_root->dirty_list into fs_info->dirty_cowonly_roots.
But if a problem is hit during btrfs_quota_enable() later, that
quota_root will be released through btrfs_put_root(), causing the whole
quota_root structure to be released, while leaving
fs_info->dirty_cowonly_roots still pointing to the released
quota_root->dirty_list.
Later access through fs_info->dirty_cowonly_roots will trigger a
use-after-free bug.
[FIX]
We can just call list_del_init(&root->dirty_list) when
btrfs_quota_enable() failed.
Also to follow the existing error handling behavior, abort the
transaction when the memory preallocation failed.
Reported-by: syzbot+947286c775f432b073a8@syzkaller.appspotmail.com
Link: https://lore.kernel.org/linux-btrfs/6ac5a5e1.9ad129c8.3ce5b3.0010.GAE@google.com/
Closes: https://syzkaller.appspot.com/bug?extid=947286c775f432b073a8
Signed-off-by: Yalagada Pavan Kumar <pavankumaryalagada@gmail.com>
Reviewed-by: Boris Burkov <boris@bur.io>
Reviewed-by: Qu Wenruo <wqu@suse.com>
[ Change the commit message to include a proper analysis. ]
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
If a transaction is aborted during committing,
btrfs_transaction::switch_commits can be non-empty, but the
btrfs_transaction structure can be freed at the last
btrfs_put_transaction() inside cleanup_transaction().
The btrfs_root::dirty_list entry still linked into switch_commits will
point to already released memory, causing use-after-free.
Address this problem by manually deleting all entries inside
btrfs_transaction::switch_commits.
And since we're here, also release the dirty_log_pages and qgroup
swapped blocks for that root, which are only released during a
successful switch_commit_roots() call.
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Commit 5ab2b180884c ("btrfs: factor out validation of
btrfs_ioctl_vol_args::name") made btrfs_control_ioctl() store the result
of btrfs_check_ioctl_vol_args_path() in ret before it looks at the
command.
However, ret is initialized to -ENOTTY and the switch has no default
case, so this initial value was what an unknown command returned. As of
now, every unknown ioctl on /dev/btrfs-control returns 0. A tool that
tries a control ioctl which the running kernel does not have is told
that the ioctl succeeded.
The issue can be reproduced with a simple C program, run as root:
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
int main(void)
{
static char buf[4096];
int fd = open("/dev/btrfs-control", O_RDWR);
if (ioctl(fd, TCGETS, buf) < 0)
perror("ioctl");
else
printf("ioctl succeeded\n");
return 0;
}
Before commit 5ab2b180884c ("btrfs: factor out validation of
btrfs_ioctl_vol_args::name"), the result is:
ioctl: Inappropriate ioctl for device
After that commit, the result is:
ioctl succeeded
This patch will add a default case that returns -ENOTTY.
Fixes: 5ab2b180884c ("btrfs: factor out validation of btrfs_ioctl_vol_args::name")
CC: stable@vger.kernel.org
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Hengyu Liang <hengyul@cs.unc.edu>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
We want to check if the next extent is at maximum capacity but we are
passing the current extent map to get_extent_max_capacity() and not
the next extent map. For example if the current extent is compressed (its
maximum capacity is 128K) and the next extent is uncompressed (its
maximum capacity is 128M), then we can bail out and not defrag the next
extent too - when for example the next extent as a size of 128K, is
uncompressed, and the extent threshold is >= 256K.
Fixes: 979b25c300db ("btrfs: defrag: don't defrag extents which are already at max capacity")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
The comparison can not be done in isolation for each key component (type
and offset) after the objectid component. For example if the defrag_max
key is (300 2 0) and the defrag_progress key is (301 1 0), the existing
comparison makes us jump to the 'done' label with 'ret' set to -EAGAIN
because 2 > 1, resulting in continuing to defrag despite having passed
the objectid of 300.
Fix this by doing the comparison correctly with btrfs_comp_cpu_keys().
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
The chunk size of a space_info is always updated with WRITE_ONCE() (see
btrfs_update_space_info_chunk_size()), so when reading it in
calc_effective_data_chunk_size() we should use READ_ONCE() to prevent
load tearing. We are already using READ_ONCE() in every other function
that accesses the chunk size of a space_info.
Reviewed-by: Daniel Vacek <neelx@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
The function never returns any error, so simplify it and its callers by
making it return void.
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
If we fail to allocate a reserved file extent we then call
btrfs_record_squota_delta() and assign its return value to 'ret',
discarding the error from the failed allocation attempt and allowing
log replay to proceed as if no errors happened, resulting in some
replayed file extent item to point to an unallocated extent. At the
moment btrfs_record_squota_delta() always returns 0 (success).
Fixes: cecbb533b5fc ("btrfs: record simple quota deltas in delayed refs")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
qgroup_trace_new_subtree_blocks()
We have maximum of 8 (BTRFS_MAX_LEVEL) levels in a btree, going from 0 to
7, so the upper bound checks should be:
>= BTRFS_MAX_LEVEL
and not:
>= BTRFS_MAX_LEVEL - 1
In practice this will hardly ever be a problem since having a btree with
8 levels would imply a massively huge fs.
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>
|
|
If we get an error when calling one of the qgroup functions, we jump to
the 'fail' label without aborting the transaction. This is not a bug as up
the call chain (transaction commit path), we will end up aborting the
transaction. However having the explicit transaction abort in
create_pending_snapshot() allows us to get a stack trace and log message
that tells us exactly where we failed, useful for troubleshooting, and
also adds consistency since in that function we abort the transaction in
every other error path.
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>
|
|
There is no need to have 3 different labels to which we goto on error.
Simplify this and have a single one, named 'out', where we always free
the path and put the root, as btrfs_free_path() and btrfs_put_root()
accept NULL arguments and do nothing in that case.
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>
|
|
When enabling quotas we add struct btrfs_qroup items to the rbtree
fs_info->qgroup_tree, however if there's an error during the quota enable
operation after adding those items, we exit without removing the items
from the rbtree and freeing them.
Fix this by calling btrfs_free_qgroup_config() on error, which also
deletes all sysfs entries (it calls btrfs_sysfs_del_qgroups()).
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>
|
|
When adding a qgroup relation, if we fail to add the relation item from
"dst" to "src", we attempt to delete the relation item from "src" to "dst"
that we added just before, however we ignore the deletion result and if we
failed to delete we leave an inconsistency in the quota root. So check the
result of the deletion and if it fails, abort the transaction to avoid
persisting an inconsistent state.
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>
|
|
In btrfs_qgroup_trace_subtree_after_cow(), after we erase the swapped
block, iterate over all possible tree levels to check if we sill have
other swapped blocks. However the check is wrong, it considers that there
are other swapped blocks if any rbtree for any level is empty, instead of
not empty. As a consequence we set blocks->swapped to true basically every
time since we always find an empty rbtree at least at level 7, since in
practice it's nearly impossible to find such a huge btree. This makes
every future call to btrfs_qgroup_trace_subtree_after_cow() do an
unnecessary rbtree search instead of returning immediately.
Fix this by updating the condition to set swapped to true if we find an
rbtree that is not empty.
Fixes: f616f5cd9da7 ("btrfs: qgroup: Use delayed subtree rescan for balance")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
Previously we had no way to tell btrfs to use which backup slot, but
always use the newest backup, and retry until all backup roots are
exhausted.
This doesn't give any control to the end user, even if the end user
wants to use a specific backup slot.
To address this problem, allow more fine-control on usebackuproot rescue
option by introducing the following 4 rescue mount options:
- rescue=usebackuproot_0
- rescue=usebackuproot_1
- rescue=usebackuproot_2
- rescue=usebackuproot_3
The number 0 means the newest slot, which should be the same as the one
recorded in the super block and no need to load any backup root.
1/2/3 means the second/third/fourth(oldest) backup slot to use.
The existing "rescue=usebackuproot" is just an alias of
"rescue=usebackuproot_1".
This will allow users to choose which backup root to use, thus can have
a better control than blindly choose any slot that can pass the very
basic root node checks.
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
[RESCUE FAILURE]
There is a bug report that "rescue=usebackuproot" failed to properly
mount the fs, but if using btrfs-mod-sb to use the second newest slot,
then the fs can even pass the full "btrfs check" and be mounted RW.
[CAUSE]
During init_tree_roots(), "rescue=usebackuproot" only makes a difference
if the tree and chunk roots failed to be load.
The loading only requires the root node/leaf to be properly loaded:
- tree root
- extent tree
- block group tree
- device tree
- data reloc tree
- quota tree (optional)
- uuid tree
- raid stripe tree (for RST feature)
And it doesn't really check any child tree blocks, thus for a lot of
cases, "rescue=usebackuproot" won't make a difference.
[ENHANCEMENT]
Instead of trying every slot and settling down on the first passing
backup slot, always use the second newest slot.
The newest slot should always match the root info in the super block,
and if it worked the end user should not even need to bother to use
backup root.
Older backup slots normally have a very low chance to work.
Link: https://github.com/kdave/btrfs-progs/issues/1162#issuecomment-5475477108
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
[BUG]
There is a bug report that fio can fail to sync the data on a degraded
RAID56 mount:
# mkfs.btrfs -m raid1 -d raid5 -f $dev1 $dev2 $dev3
# mount $dev1 $mnt
# btrfs balance start -d $mnt
# umount $mnt
# btrfs dev scan -u $dev2
# wipefs -fa $dev2
# mount -o degraded $dev1 $mnt
# fio --name=degraded-write --directory=$mnt --rw=randwrite --fdatasync=4 \
--bs=4k --size=512M --randrepeat=1
The run will fail at fsync:
fio: io_u error on file /mnt/btrfs/degraded-write.0.0: Input/output error: datasync offset=142254080, buflen=0
fio: pid=2064, err=5/file:io_u.c:2008, func=io_u error, error=Input/output error
[CAUSE]
With extra debug output, it shows the problem pretty well:
rbio=2876243968 faila=0 sectornr=0
rbio=2876243968 error=0-15 csum=2 bio=15
The first line shows the rbio's full stripe logical, and stripe/sector
number when verify_one_sector() failed.
The second line shows more detail about the rbio, the sector range [0, 16)
is corrupted, which indicates the first data stripe is corrupted, matching
the missing device.
The important part is that the csum bitmap shows the data csum is only
for sector number 2, meanwhile the failed verification is at sector
number 0.
This means we did the checksum verification even if no corresponding
checksum is populated.
[FIX]
There is already a similar check at verify_bio_data_sectors(), but
unfortunately there is no such check at verify_one_sector().
Add the missing check to skip the csum verification if there is no
corresponding data checksum.
Reported-by: Bartosz Fenski <bartosz@fenski.pl>
Link: https://lore.kernel.org/linux-btrfs/a72409af-45ef-45df-9970-2e38bcb22ea6@fenski.pl/
Fixes: 7a3150723061 ("btrfs: raid56: do data csum verification during RMW cycle")
CC: stable@vger.kernel.org
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
If btrfs_remove_qgroup() is called on a qgroup that only exists in the
rb-tree, then del_qgroup_item() will return -ENOENT, and we tolerate
that -ENOENT.
However if the to-be-deleted qgroup has no parent qgroups, the @ret will
not be updated, and will leak to user space.
It will make the ioctl() caller incorrectly assume the operation failed.
Fix it by resetting @ret to 0 after a successful or tolerated
del_qgroup_item() call, so the -ENOENT from del_qgroup_item() won't be
leaked.
Assisted-by: LLM (exposing this pre-existing problem)
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
When quick_update_accounting() fails to handle a qgroup which is not
fully exclusive (its exclusive number doesn't match the reference one),
we have to mark the qgroup inconsistent.
Unlike other locations we didn't use qgroup_mark_inconsistent(), thus
when such problem happens no extra error message is shown.
Use the helper in quick_update_accounting(), which does not only show
the reason of marking qgroup inconsistent, but also cancels any running
rescan and skips dirty accounting, avoiding wasting CPU time on already
inconsistent qgroup numbers.
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
[BUG]
There is a bug report that when removing a child qgroup, if removing the
qgroup requires a rescan, it will delete the on-disk relation and qgroup
items but not the in-memory qgroup rb entry.
This makes all later qgroup rescan to fail.
[CAUSE]
The call chain looks like the following:
btrfs_remove_qgroup()
|- __del_qgroup_relation()
| |- quick_update_accounting()
| Which returns 1, showing this operation will require
| a qgroup rescan
|- if (ret) goto out;
Which skips the del_qgroup_rb() call, leaving the in-memory qgroup
rb entry still intact.
Then later qgroup rescan/update will always fail and mark qgroup
inconsistent:
btrfs_run_qgroups()
|- update_qgroup_info_item()
| |- btrfs_search_slot()
| Which returns -ENOENT, as the qgroup info item is already
| deleted.
|- qgroup_mark_inconsistent()
|- return -ENOENT;
[FIX]
Do not treat "ret > 0" as an error.
Reported-by: c.f.a@posteo.de
Link: https://lore.kernel.org/linux-btrfs/14846642-85d3-4afb-ad99-1b74b22f5f90@posteo.de/
Fixes: 9c8b35b1ba21 ("btrfs: quota: Automatically update related qgroups or mark INCONSISTENT flags when assigning/deleting a qgroup relations.")
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
There is no need to forward declare the structures as their definitions
are brought in by the include of the linux/blkdev.h and fs.h files.
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>
|
|
If num_bytes == (u64)-1, there's no point to set qgroup_to_release to
block_rsv->qgroup_rsv_size as later on we will overwrite that value
without ever reading the variable before that. So simplify things and
remove that assignment.
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>
|
|
The fs_info argument is not used, so remove it.
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>
|
|
The fs_info argument is not used, so remove it.
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>
|
|
The addressable range with an extent buffer goes from byte 0 to byte
eb->len - 1, so if a byte address matches eb->len, it's already beyond
the addressable range and we should log that it's bad start address
and not end address.
Fixes: 234fdd2815ce ("btrfs: remove redundant check in up check_setget_bounds")
Reviewed-by: Qu Wenruo <wqu@suse.com>
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>
|
|
If the fs state does not have any errors and is not in some special state
(like emergency shutdown or mounted with rescue options), then in
btrfs_state_to_string() we end up doing a memcpy() into the buffer and
then later just undo that work by setting the buffer's first element to
the NUL terminator, since fs_info->fs_error is 0 and there is no bit set
in fs_info->fs_state.
Improve on this by returning early if there's no error in the fs and the
fs state is clean, which is the expected scenario for a healthy fs that is
not mounted with special options like the rescue options.
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
There's no point in incrementing the local pointer after we set the NUL
terminator, as we don't use the pointer anymore after that.
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>
|
|
Add a letter code for the BTRFS_FS_STATE_NO_DELAYED_IPUT fs state, which
is currently missing and it's useful to have.
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>
|
|
We are using the code 'E' when the fs is in an error state (transaction
aborted) and when it's in the emergency shutdown state, which is confusing
and not intentional. Fix this by using an unused code such as 'H' for the
emergency shutdown state and add a comment over the fs_state_chars array
to warn to not use 'E' as its use is not defined in the array but instead
in the function btrfs_state_to_string(), since the fs state error is not
defined as a bit but as an error code in fs_info->fs_error.
Fixes: 9b2839451dfc ("btrfs: introduce a new shutdown state")
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>
|
|
In btrfs_state_to_string() we iterate over all the bits set in
fs_info->fs_state using for_each_set_bit(), which requires its third
argument to match the number of bits, but we pass it the number of bytes
of the type used by fs_info->fs_state, an unsigned long, which is 8 on
64 bits platforms and 4 on 32 bits platforms. This means we are not
iterating over bits in the ranges [8, 63] or [4, 31].
Fix this by passing BTRFS_FS_STATE_COUNT instead of sizeof(fs_state).
Note that we could pass BITS_PER_TYPE(fs_state), but since
BTRFS_FS_STATE_COUNT is 11 and we have no bits beyond that, it would
cause pointless iterations over fs_state.
This also makes pointless the checks for the bit being inside the limit
of BTRFS_FS_STATE_COUNT inside the loop.
Fixes: c067da878156 ("btrfs: add filesystems state details to error messages")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
|