Skip to content

Commit 372800c

Browse files
committed
Merge tag 'for-6.19-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: - fix potential NULL pointer dereference when replaying tree log after an error - release path before initializing extent tree to avoid potential deadlock when allocating new inode - on filesystems with block size > page size - fix potential read out of bounds during encoded read of an inline extent - only enforce free space tree if v1 cache is required - print correct tree id in error message * tag 'for-6.19-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: show correct warning if can't read data reloc tree btrfs: fix NULL pointer dereference in do_abort_log_replay() btrfs: force free space tree for bs > ps cases btrfs: only enforce free space tree if v1 cache is required for bs < ps cases btrfs: release path before initializing extent tree in btrfs_read_locked_inode() btrfs: avoid access-beyond-folio for bs > ps encoded writes
2 parents 4d6fe1d + 2bb83bc commit 372800c

4 files changed

Lines changed: 39 additions & 17 deletions

File tree

fs/btrfs/disk-io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,6 +2255,7 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
22552255
BTRFS_DATA_RELOC_TREE_OBJECTID, true);
22562256
if (IS_ERR(root)) {
22572257
if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
2258+
location.objectid = BTRFS_DATA_RELOC_TREE_OBJECTID;
22582259
ret = PTR_ERR(root);
22592260
goto out;
22602261
}

fs/btrfs/inode.c

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -481,13 +481,15 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
481481
ASSERT(size <= sectorsize);
482482

483483
/*
484-
* The compressed size also needs to be no larger than a sector.
485-
* That's also why we only need one page as the parameter.
484+
* The compressed size also needs to be no larger than a page.
485+
* That's also why we only need one folio as the parameter.
486486
*/
487-
if (compressed_folio)
487+
if (compressed_folio) {
488488
ASSERT(compressed_size <= sectorsize);
489-
else
489+
ASSERT(compressed_size <= PAGE_SIZE);
490+
} else {
490491
ASSERT(compressed_size == 0);
492+
}
491493

492494
if (compressed_size && compressed_folio)
493495
cur_size = compressed_size;
@@ -574,6 +576,18 @@ static bool can_cow_file_range_inline(struct btrfs_inode *inode,
574576
if (offset != 0)
575577
return false;
576578

579+
/*
580+
* Even for bs > ps cases, cow_file_range_inline() can only accept a
581+
* single folio.
582+
*
583+
* This can be problematic and cause access beyond page boundary if a
584+
* page sized folio is passed into that function.
585+
* And encoded write is doing exactly that.
586+
* So here limits the inlined extent size to PAGE_SIZE.
587+
*/
588+
if (size > PAGE_SIZE || compressed_size > PAGE_SIZE)
589+
return false;
590+
577591
/* Inline extents are limited to sectorsize. */
578592
if (size > fs_info->sectorsize)
579593
return false;
@@ -4034,11 +4048,6 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path
40344048
btrfs_set_inode_mapping_order(inode);
40354049

40364050
cache_index:
4037-
ret = btrfs_init_file_extent_tree(inode);
4038-
if (ret)
4039-
goto out;
4040-
btrfs_inode_set_file_extent_range(inode, 0,
4041-
round_up(i_size_read(vfs_inode), fs_info->sectorsize));
40424051
/*
40434052
* If we were modified in the current generation and evicted from memory
40444053
* and then re-read we need to do a full sync since we don't have any
@@ -4125,6 +4134,20 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path
41254134
btrfs_ino(inode), btrfs_root_id(root), ret);
41264135
}
41274136

4137+
/*
4138+
* We don't need the path anymore, so release it to avoid holding a read
4139+
* lock on a leaf while calling btrfs_init_file_extent_tree(), which can
4140+
* allocate memory that triggers reclaim (GFP_KERNEL) and cause a locking
4141+
* dependency.
4142+
*/
4143+
btrfs_release_path(path);
4144+
4145+
ret = btrfs_init_file_extent_tree(inode);
4146+
if (ret)
4147+
goto out;
4148+
btrfs_inode_set_file_extent_range(inode, 0,
4149+
round_up(i_size_read(vfs_inode), fs_info->sectorsize));
4150+
41284151
if (!maybe_acls)
41294152
cache_no_acl(vfs_inode);
41304153

fs/btrfs/super.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -736,14 +736,12 @@ bool btrfs_check_options(const struct btrfs_fs_info *info,
736736
*/
737737
void btrfs_set_free_space_cache_settings(struct btrfs_fs_info *fs_info)
738738
{
739-
if (fs_info->sectorsize < PAGE_SIZE) {
739+
if (fs_info->sectorsize != PAGE_SIZE && btrfs_test_opt(fs_info, SPACE_CACHE)) {
740+
btrfs_info(fs_info,
741+
"forcing free space tree for sector size %u with page size %lu",
742+
fs_info->sectorsize, PAGE_SIZE);
740743
btrfs_clear_opt(fs_info->mount_opt, SPACE_CACHE);
741-
if (!btrfs_test_opt(fs_info, FREE_SPACE_TREE)) {
742-
btrfs_info(fs_info,
743-
"forcing free space tree for sector size %u with page size %lu",
744-
fs_info->sectorsize, PAGE_SIZE);
745-
btrfs_set_opt(fs_info->mount_opt, FREE_SPACE_TREE);
746-
}
744+
btrfs_set_opt(fs_info->mount_opt, FREE_SPACE_TREE);
747745
}
748746

749747
/*

fs/btrfs/tree-log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ static void do_abort_log_replay(struct walk_control *wc, const char *function,
190190

191191
btrfs_abort_transaction(wc->trans, error);
192192

193-
if (wc->subvol_path->nodes[0]) {
193+
if (wc->subvol_path && wc->subvol_path->nodes[0]) {
194194
btrfs_crit(fs_info,
195195
"subvolume (root %llu) leaf currently being processed:",
196196
btrfs_root_id(wc->root));

0 commit comments

Comments
 (0)