Skip to content

Commit 5d9248e

Browse files
committed
Merge tag 'for-6.8-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: - zoned mode fixes: - fix slowdown when writing large file sequentially by looking up block groups with enough space faster - locking fixes when activating a zone - new mount API fixes: - preserve mount options for a ro/rw mount of the same subvolume - scrub fixes: - fix use-after-free in case the chunk length is not aligned to 64K, this does not happen normally but has been reported on images converted from ext4 - similar alignment check was missing with raid-stripe-tree - subvolume deletion fixes: - prevent calling ioctl on already deleted subvolume - properly track flag tracking a deleted subvolume - in subpage mode, fix decompression of an inline extent (zlib, lzo, zstd) - fix crash when starting writeback on a folio, after integration with recent MM changes this needs to be started conditionally - reject unknown flags in defrag ioctl - error handling, API fixes, minor warning fixes * tag 'for-6.8-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: scrub: limit RST scrub to chunk boundary btrfs: scrub: avoid use-after-free when chunk length is not 64K aligned btrfs: don't unconditionally call folio_start_writeback in subpage btrfs: use the original mount's mount options for the legacy reconfigure btrfs: don't warn if discard range is not aligned to sector btrfs: tree-checker: fix inline ref size in error messages btrfs: zstd: fix and simplify the inline extent decompression btrfs: lzo: fix and simplify the inline extent decompression btrfs: zlib: fix and simplify the inline extent decompression btrfs: defrag: reject unknown flags of btrfs_ioctl_defrag_range_args btrfs: avoid copying BTRFS_ROOT_SUBVOL_DEAD flag to snapshot of subvolume being deleted btrfs: don't abort filesystem when attempting to snapshot deleted subvolume btrfs: zoned: fix lock ordering in btrfs_zone_activate() btrfs: fix unbalanced unlock of mapping_tree_lock btrfs: ref-verify: free ref cache before clearing mount opt btrfs: fix kvcalloc() arguments order in btrfs_ioctl_send() btrfs: zoned: optimize hint byte for zoned allocator btrfs: zoned: factor out prepare_allocation_zoned()
2 parents 610347e + 7f2d219 commit 5d9248e

17 files changed

+179
-186
lines changed

fs/btrfs/compression.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,16 @@ static int compression_decompress_bio(struct list_head *ws,
141141
}
142142

143143
static int compression_decompress(int type, struct list_head *ws,
144-
const u8 *data_in, struct page *dest_page,
145-
unsigned long start_byte, size_t srclen, size_t destlen)
144+
const u8 *data_in, struct page *dest_page,
145+
unsigned long dest_pgoff, size_t srclen, size_t destlen)
146146
{
147147
switch (type) {
148148
case BTRFS_COMPRESS_ZLIB: return zlib_decompress(ws, data_in, dest_page,
149-
start_byte, srclen, destlen);
149+
dest_pgoff, srclen, destlen);
150150
case BTRFS_COMPRESS_LZO: return lzo_decompress(ws, data_in, dest_page,
151-
start_byte, srclen, destlen);
151+
dest_pgoff, srclen, destlen);
152152
case BTRFS_COMPRESS_ZSTD: return zstd_decompress(ws, data_in, dest_page,
153-
start_byte, srclen, destlen);
153+
dest_pgoff, srclen, destlen);
154154
case BTRFS_COMPRESS_NONE:
155155
default:
156156
/*
@@ -1037,14 +1037,23 @@ static int btrfs_decompress_bio(struct compressed_bio *cb)
10371037
* start_byte tells us the offset into the compressed data we're interested in
10381038
*/
10391039
int btrfs_decompress(int type, const u8 *data_in, struct page *dest_page,
1040-
unsigned long start_byte, size_t srclen, size_t destlen)
1040+
unsigned long dest_pgoff, size_t srclen, size_t destlen)
10411041
{
1042+
struct btrfs_fs_info *fs_info = btrfs_sb(dest_page->mapping->host->i_sb);
10421043
struct list_head *workspace;
1044+
const u32 sectorsize = fs_info->sectorsize;
10431045
int ret;
10441046

1047+
/*
1048+
* The full destination page range should not exceed the page size.
1049+
* And the @destlen should not exceed sectorsize, as this is only called for
1050+
* inline file extents, which should not exceed sectorsize.
1051+
*/
1052+
ASSERT(dest_pgoff + destlen <= PAGE_SIZE && destlen <= sectorsize);
1053+
10451054
workspace = get_workspace(type, 0);
10461055
ret = compression_decompress(type, workspace, data_in, dest_page,
1047-
start_byte, srclen, destlen);
1056+
dest_pgoff, srclen, destlen);
10481057
put_workspace(type, workspace);
10491058

10501059
return ret;

fs/btrfs/compression.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ int zlib_compress_pages(struct list_head *ws, struct address_space *mapping,
148148
unsigned long *total_in, unsigned long *total_out);
149149
int zlib_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
150150
int zlib_decompress(struct list_head *ws, const u8 *data_in,
151-
struct page *dest_page, unsigned long start_byte, size_t srclen,
151+
struct page *dest_page, unsigned long dest_pgoff, size_t srclen,
152152
size_t destlen);
153153
struct list_head *zlib_alloc_workspace(unsigned int level);
154154
void zlib_free_workspace(struct list_head *ws);
@@ -159,7 +159,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
159159
unsigned long *total_in, unsigned long *total_out);
160160
int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
161161
int lzo_decompress(struct list_head *ws, const u8 *data_in,
162-
struct page *dest_page, unsigned long start_byte, size_t srclen,
162+
struct page *dest_page, unsigned long dest_pgoff, size_t srclen,
163163
size_t destlen);
164164
struct list_head *lzo_alloc_workspace(unsigned int level);
165165
void lzo_free_workspace(struct list_head *ws);
@@ -169,7 +169,7 @@ int zstd_compress_pages(struct list_head *ws, struct address_space *mapping,
169169
unsigned long *total_in, unsigned long *total_out);
170170
int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb);
171171
int zstd_decompress(struct list_head *ws, const u8 *data_in,
172-
struct page *dest_page, unsigned long start_byte, size_t srclen,
172+
struct page *dest_page, unsigned long dest_pgoff, size_t srclen,
173173
size_t destlen);
174174
void zstd_init_workspace_manager(void);
175175
void zstd_cleanup_workspace_manager(void);

fs/btrfs/extent-tree.c

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,8 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
12601260
u64 bytes_left, end;
12611261
u64 aligned_start = ALIGN(start, 1 << SECTOR_SHIFT);
12621262

1263-
if (WARN_ON(start != aligned_start)) {
1263+
/* Adjust the range to be aligned to 512B sectors if necessary. */
1264+
if (start != aligned_start) {
12641265
len -= aligned_start - start;
12651266
len = round_down(len, 1 << SECTOR_SHIFT);
12661267
start = aligned_start;
@@ -4298,6 +4299,42 @@ static int prepare_allocation_clustered(struct btrfs_fs_info *fs_info,
42984299
return 0;
42994300
}
43004301

4302+
static int prepare_allocation_zoned(struct btrfs_fs_info *fs_info,
4303+
struct find_free_extent_ctl *ffe_ctl)
4304+
{
4305+
if (ffe_ctl->for_treelog) {
4306+
spin_lock(&fs_info->treelog_bg_lock);
4307+
if (fs_info->treelog_bg)
4308+
ffe_ctl->hint_byte = fs_info->treelog_bg;
4309+
spin_unlock(&fs_info->treelog_bg_lock);
4310+
} else if (ffe_ctl->for_data_reloc) {
4311+
spin_lock(&fs_info->relocation_bg_lock);
4312+
if (fs_info->data_reloc_bg)
4313+
ffe_ctl->hint_byte = fs_info->data_reloc_bg;
4314+
spin_unlock(&fs_info->relocation_bg_lock);
4315+
} else if (ffe_ctl->flags & BTRFS_BLOCK_GROUP_DATA) {
4316+
struct btrfs_block_group *block_group;
4317+
4318+
spin_lock(&fs_info->zone_active_bgs_lock);
4319+
list_for_each_entry(block_group, &fs_info->zone_active_bgs, active_bg_list) {
4320+
/*
4321+
* No lock is OK here because avail is monotinically
4322+
* decreasing, and this is just a hint.
4323+
*/
4324+
u64 avail = block_group->zone_capacity - block_group->alloc_offset;
4325+
4326+
if (block_group_bits(block_group, ffe_ctl->flags) &&
4327+
avail >= ffe_ctl->num_bytes) {
4328+
ffe_ctl->hint_byte = block_group->start;
4329+
break;
4330+
}
4331+
}
4332+
spin_unlock(&fs_info->zone_active_bgs_lock);
4333+
}
4334+
4335+
return 0;
4336+
}
4337+
43014338
static int prepare_allocation(struct btrfs_fs_info *fs_info,
43024339
struct find_free_extent_ctl *ffe_ctl,
43034340
struct btrfs_space_info *space_info,
@@ -4308,19 +4345,7 @@ static int prepare_allocation(struct btrfs_fs_info *fs_info,
43084345
return prepare_allocation_clustered(fs_info, ffe_ctl,
43094346
space_info, ins);
43104347
case BTRFS_EXTENT_ALLOC_ZONED:
4311-
if (ffe_ctl->for_treelog) {
4312-
spin_lock(&fs_info->treelog_bg_lock);
4313-
if (fs_info->treelog_bg)
4314-
ffe_ctl->hint_byte = fs_info->treelog_bg;
4315-
spin_unlock(&fs_info->treelog_bg_lock);
4316-
}
4317-
if (ffe_ctl->for_data_reloc) {
4318-
spin_lock(&fs_info->relocation_bg_lock);
4319-
if (fs_info->data_reloc_bg)
4320-
ffe_ctl->hint_byte = fs_info->data_reloc_bg;
4321-
spin_unlock(&fs_info->relocation_bg_lock);
4322-
}
4323-
return 0;
4348+
return prepare_allocation_zoned(fs_info, ffe_ctl);
43244349
default:
43254350
BUG();
43264351
}

fs/btrfs/inode.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4458,6 +4458,8 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
44584458
u64 root_flags;
44594459
int ret;
44604460

4461+
down_write(&fs_info->subvol_sem);
4462+
44614463
/*
44624464
* Don't allow to delete a subvolume with send in progress. This is
44634465
* inside the inode lock so the error handling that has to drop the bit
@@ -4469,25 +4471,25 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
44694471
btrfs_warn(fs_info,
44704472
"attempt to delete subvolume %llu during send",
44714473
dest->root_key.objectid);
4472-
return -EPERM;
4474+
ret = -EPERM;
4475+
goto out_up_write;
44734476
}
44744477
if (atomic_read(&dest->nr_swapfiles)) {
44754478
spin_unlock(&dest->root_item_lock);
44764479
btrfs_warn(fs_info,
44774480
"attempt to delete subvolume %llu with active swapfile",
44784481
root->root_key.objectid);
4479-
return -EPERM;
4482+
ret = -EPERM;
4483+
goto out_up_write;
44804484
}
44814485
root_flags = btrfs_root_flags(&dest->root_item);
44824486
btrfs_set_root_flags(&dest->root_item,
44834487
root_flags | BTRFS_ROOT_SUBVOL_DEAD);
44844488
spin_unlock(&dest->root_item_lock);
44854489

4486-
down_write(&fs_info->subvol_sem);
4487-
44884490
ret = may_destroy_subvol(dest);
44894491
if (ret)
4490-
goto out_up_write;
4492+
goto out_undead;
44914493

44924494
btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
44934495
/*
@@ -4497,7 +4499,7 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
44974499
*/
44984500
ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 5, true);
44994501
if (ret)
4500-
goto out_up_write;
4502+
goto out_undead;
45014503

45024504
trans = btrfs_start_transaction(root, 0);
45034505
if (IS_ERR(trans)) {
@@ -4563,15 +4565,17 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
45634565
inode->i_flags |= S_DEAD;
45644566
out_release:
45654567
btrfs_subvolume_release_metadata(root, &block_rsv);
4566-
out_up_write:
4567-
up_write(&fs_info->subvol_sem);
4568+
out_undead:
45684569
if (ret) {
45694570
spin_lock(&dest->root_item_lock);
45704571
root_flags = btrfs_root_flags(&dest->root_item);
45714572
btrfs_set_root_flags(&dest->root_item,
45724573
root_flags & ~BTRFS_ROOT_SUBVOL_DEAD);
45734574
spin_unlock(&dest->root_item_lock);
4574-
} else {
4575+
}
4576+
out_up_write:
4577+
up_write(&fs_info->subvol_sem);
4578+
if (!ret) {
45754579
d_invalidate(dentry);
45764580
btrfs_prune_dentries(dest);
45774581
ASSERT(dest->send_in_progress == 0);

fs/btrfs/ioctl.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,9 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
790790
return -EOPNOTSUPP;
791791
}
792792

793+
if (btrfs_root_refs(&root->root_item) == 0)
794+
return -ENOENT;
795+
793796
if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))
794797
return -EINVAL;
795798

@@ -2608,6 +2611,10 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
26082611
ret = -EFAULT;
26092612
goto out;
26102613
}
2614+
if (range.flags & ~BTRFS_DEFRAG_RANGE_FLAGS_SUPP) {
2615+
ret = -EOPNOTSUPP;
2616+
goto out;
2617+
}
26112618
/* compression requires us to start the IO */
26122619
if ((range.flags & BTRFS_DEFRAG_RANGE_COMPRESS)) {
26132620
range.flags |= BTRFS_DEFRAG_RANGE_START_IO;

fs/btrfs/lzo.c

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -425,16 +425,16 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
425425
}
426426

427427
int lzo_decompress(struct list_head *ws, const u8 *data_in,
428-
struct page *dest_page, unsigned long start_byte, size_t srclen,
428+
struct page *dest_page, unsigned long dest_pgoff, size_t srclen,
429429
size_t destlen)
430430
{
431431
struct workspace *workspace = list_entry(ws, struct workspace, list);
432+
struct btrfs_fs_info *fs_info = btrfs_sb(dest_page->mapping->host->i_sb);
433+
const u32 sectorsize = fs_info->sectorsize;
432434
size_t in_len;
433435
size_t out_len;
434436
size_t max_segment_len = WORKSPACE_BUF_LENGTH;
435437
int ret = 0;
436-
char *kaddr;
437-
unsigned long bytes;
438438

439439
if (srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2)
440440
return -EUCLEAN;
@@ -451,37 +451,21 @@ int lzo_decompress(struct list_head *ws, const u8 *data_in,
451451
}
452452
data_in += LZO_LEN;
453453

454-
out_len = PAGE_SIZE;
454+
out_len = sectorsize;
455455
ret = lzo1x_decompress_safe(data_in, in_len, workspace->buf, &out_len);
456456
if (ret != LZO_E_OK) {
457457
pr_warn("BTRFS: decompress failed!\n");
458458
ret = -EIO;
459459
goto out;
460460
}
461461

462-
if (out_len < start_byte) {
462+
ASSERT(out_len <= sectorsize);
463+
memcpy_to_page(dest_page, dest_pgoff, workspace->buf, out_len);
464+
/* Early end, considered as an error. */
465+
if (unlikely(out_len < destlen)) {
463466
ret = -EIO;
464-
goto out;
467+
memzero_page(dest_page, dest_pgoff + out_len, destlen - out_len);
465468
}
466-
467-
/*
468-
* the caller is already checking against PAGE_SIZE, but lets
469-
* move this check closer to the memcpy/memset
470-
*/
471-
destlen = min_t(unsigned long, destlen, PAGE_SIZE);
472-
bytes = min_t(unsigned long, destlen, out_len - start_byte);
473-
474-
kaddr = kmap_local_page(dest_page);
475-
memcpy(kaddr, workspace->buf + start_byte, bytes);
476-
477-
/*
478-
* btrfs_getblock is doing a zero on the tail of the page too,
479-
* but this will cover anything missing from the decompressed
480-
* data.
481-
*/
482-
if (bytes < destlen)
483-
memset(kaddr+bytes, 0, destlen-bytes);
484-
kunmap_local(kaddr);
485469
out:
486470
return ret;
487471
}

fs/btrfs/ref-verify.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -889,8 +889,10 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
889889
out_unlock:
890890
spin_unlock(&fs_info->ref_verify_lock);
891891
out:
892-
if (ret)
892+
if (ret) {
893+
btrfs_free_ref_cache(fs_info);
893894
btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY);
895+
}
894896
return ret;
895897
}
896898

@@ -1021,8 +1023,8 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info)
10211023
}
10221024
}
10231025
if (ret) {
1024-
btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY);
10251026
btrfs_free_ref_cache(fs_info);
1027+
btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY);
10261028
}
10271029
btrfs_free_path(path);
10281030
return ret;

0 commit comments

Comments
 (0)