Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-6.2-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:

- fix potential out-of-bounds access to leaf data when seeking in an
inline file

- fix potential crash in quota when rescan races with disable

- reimplement super block signature scratching by marking page/folio
dirty and syncing block device, allow removing write_one_page

* tag 'for-6.2-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix race between quota rescan and disable leading to NULL pointer deref
btrfs: fix invalid leaf access due to inline extent during lseek
btrfs: stop using write_one_page in btrfs_scratch_superblock
btrfs: factor out scratching of one regular super block

+52 -36
+10 -3
fs/btrfs/file.c
··· 3541 3541 struct extent_buffer *leaf = path->nodes[0]; 3542 3542 struct btrfs_file_extent_item *extent; 3543 3543 u64 extent_end; 3544 + u8 type; 3544 3545 3545 3546 if (path->slots[0] >= btrfs_header_nritems(leaf)) { 3546 3547 ret = btrfs_next_leaf(root, path); ··· 3597 3596 3598 3597 extent = btrfs_item_ptr(leaf, path->slots[0], 3599 3598 struct btrfs_file_extent_item); 3599 + type = btrfs_file_extent_type(leaf, extent); 3600 3600 3601 - if (btrfs_file_extent_disk_bytenr(leaf, extent) == 0 || 3602 - btrfs_file_extent_type(leaf, extent) == 3603 - BTRFS_FILE_EXTENT_PREALLOC) { 3601 + /* 3602 + * Can't access the extent's disk_bytenr field if this is an 3603 + * inline extent, since at that offset, it's where the extent 3604 + * data starts. 3605 + */ 3606 + if (type == BTRFS_FILE_EXTENT_PREALLOC || 3607 + (type == BTRFS_FILE_EXTENT_REG && 3608 + btrfs_file_extent_disk_bytenr(leaf, extent) == 0)) { 3604 3609 /* 3605 3610 * Explicit hole or prealloc extent, search for delalloc. 3606 3611 * A prealloc extent is treated like a hole.
+17 -8
fs/btrfs/qgroup.c
··· 3367 3367 int err = -ENOMEM; 3368 3368 int ret = 0; 3369 3369 bool stopped = false; 3370 + bool did_leaf_rescans = false; 3370 3371 3371 3372 path = btrfs_alloc_path(); 3372 3373 if (!path) ··· 3388 3387 } 3389 3388 3390 3389 err = qgroup_rescan_leaf(trans, path); 3390 + did_leaf_rescans = true; 3391 3391 3392 3392 if (err > 0) 3393 3393 btrfs_commit_transaction(trans); ··· 3409 3407 mutex_unlock(&fs_info->qgroup_rescan_lock); 3410 3408 3411 3409 /* 3412 - * only update status, since the previous part has already updated the 3413 - * qgroup info. 3410 + * Only update status, since the previous part has already updated the 3411 + * qgroup info, and only if we did any actual work. This also prevents 3412 + * race with a concurrent quota disable, which has already set 3413 + * fs_info->quota_root to NULL and cleared BTRFS_FS_QUOTA_ENABLED at 3414 + * btrfs_quota_disable(). 3414 3415 */ 3415 - trans = btrfs_start_transaction(fs_info->quota_root, 1); 3416 - if (IS_ERR(trans)) { 3417 - err = PTR_ERR(trans); 3416 + if (did_leaf_rescans) { 3417 + trans = btrfs_start_transaction(fs_info->quota_root, 1); 3418 + if (IS_ERR(trans)) { 3419 + err = PTR_ERR(trans); 3420 + trans = NULL; 3421 + btrfs_err(fs_info, 3422 + "fail to start transaction for status update: %d", 3423 + err); 3424 + } 3425 + } else { 3418 3426 trans = NULL; 3419 - btrfs_err(fs_info, 3420 - "fail to start transaction for status update: %d", 3421 - err); 3422 3427 } 3423 3428 3424 3429 mutex_lock(&fs_info->qgroup_rescan_lock);
+25 -25
fs/btrfs/volumes.c
··· 2014 2014 return num_devices; 2015 2015 } 2016 2016 2017 + static void btrfs_scratch_superblock(struct btrfs_fs_info *fs_info, 2018 + struct block_device *bdev, int copy_num) 2019 + { 2020 + struct btrfs_super_block *disk_super; 2021 + const size_t len = sizeof(disk_super->magic); 2022 + const u64 bytenr = btrfs_sb_offset(copy_num); 2023 + int ret; 2024 + 2025 + disk_super = btrfs_read_disk_super(bdev, bytenr, bytenr); 2026 + if (IS_ERR(disk_super)) 2027 + return; 2028 + 2029 + memset(&disk_super->magic, 0, len); 2030 + folio_mark_dirty(virt_to_folio(disk_super)); 2031 + btrfs_release_disk_super(disk_super); 2032 + 2033 + ret = sync_blockdev_range(bdev, bytenr, bytenr + len - 1); 2034 + if (ret) 2035 + btrfs_warn(fs_info, "error clearing superblock number %d (%d)", 2036 + copy_num, ret); 2037 + } 2038 + 2017 2039 void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info, 2018 2040 struct block_device *bdev, 2019 2041 const char *device_path) 2020 2042 { 2021 - struct btrfs_super_block *disk_super; 2022 2043 int copy_num; 2023 2044 2024 2045 if (!bdev) 2025 2046 return; 2026 2047 2027 2048 for (copy_num = 0; copy_num < BTRFS_SUPER_MIRROR_MAX; copy_num++) { 2028 - struct page *page; 2029 - int ret; 2030 - 2031 - disk_super = btrfs_read_dev_one_super(bdev, copy_num, false); 2032 - if (IS_ERR(disk_super)) 2033 - continue; 2034 - 2035 - if (bdev_is_zoned(bdev)) { 2049 + if (bdev_is_zoned(bdev)) 2036 2050 btrfs_reset_sb_log_zones(bdev, copy_num); 2037 - continue; 2038 - } 2039 - 2040 - memset(&disk_super->magic, 0, sizeof(disk_super->magic)); 2041 - 2042 - page = virt_to_page(disk_super); 2043 - set_page_dirty(page); 2044 - lock_page(page); 2045 - /* write_on_page() unlocks the page */ 2046 - ret = write_one_page(page); 2047 - if (ret) 2048 - btrfs_warn(fs_info, 2049 - "error clearing superblock number %d (%d)", 2050 - copy_num, ret); 2051 - btrfs_release_disk_super(disk_super); 2052 - 2051 + else 2052 + btrfs_scratch_superblock(fs_info, bdev, copy_num); 2053 2053 } 2054 2054 2055 2055 /* Notify udev that device has changed */