Skip to content

Commit e4fc196

Browse files
committed
Merge tag 'for-6.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: - fix regression in extent map rework when handling insertion of overlapping compressed extent - fix unexpected file length when appending to a file using direct io and buffer not faulted in - in zoned mode, fix accounting of unusable space when flipping read-only block group back to read-write - fix page locking when COWing an inline range, assertion failure found by syzbot - fix calculation of space info in debugging print - tree-checker, add validation of data reference item - fix a few -Wmaybe-uninitialized build warnings * tag 'for-6.11-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: initialize location to fix -Wmaybe-uninitialized in btrfs_lookup_dentry() btrfs: fix corruption after buffer fault in during direct IO append write btrfs: zoned: fix zone_unusable accounting on making block group read-write again btrfs: do not subtract delalloc from avail bytes btrfs: make cow_file_range_inline() honor locked_page on error btrfs: fix corrupt read due to bad offset of a compressed extent map btrfs: tree-checker: validate dref root and objectid
2 parents e254e0c + b8e947e commit e4fc196

File tree

13 files changed

+225
-31
lines changed

13 files changed

+225
-31
lines changed

fs/btrfs/block-group.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,8 +1223,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
12231223
block_group->space_info->total_bytes -= block_group->length;
12241224
block_group->space_info->bytes_readonly -=
12251225
(block_group->length - block_group->zone_unusable);
1226-
block_group->space_info->bytes_zone_unusable -=
1227-
block_group->zone_unusable;
1226+
btrfs_space_info_update_bytes_zone_unusable(fs_info, block_group->space_info,
1227+
-block_group->zone_unusable);
12281228
block_group->space_info->disk_total -= block_group->length * factor;
12291229

12301230
spin_unlock(&block_group->space_info->lock);
@@ -1396,7 +1396,8 @@ static int inc_block_group_ro(struct btrfs_block_group *cache, int force)
13961396
if (btrfs_is_zoned(cache->fs_info)) {
13971397
/* Migrate zone_unusable bytes to readonly */
13981398
sinfo->bytes_readonly += cache->zone_unusable;
1399-
sinfo->bytes_zone_unusable -= cache->zone_unusable;
1399+
btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo,
1400+
-cache->zone_unusable);
14001401
cache->zone_unusable = 0;
14011402
}
14021403
cache->ro++;
@@ -3056,9 +3057,11 @@ void btrfs_dec_block_group_ro(struct btrfs_block_group *cache)
30563057
if (btrfs_is_zoned(cache->fs_info)) {
30573058
/* Migrate zone_unusable bytes back */
30583059
cache->zone_unusable =
3059-
(cache->alloc_offset - cache->used) +
3060+
(cache->alloc_offset - cache->used - cache->pinned -
3061+
cache->reserved) +
30603062
(cache->length - cache->zone_capacity);
3061-
sinfo->bytes_zone_unusable += cache->zone_unusable;
3063+
btrfs_space_info_update_bytes_zone_unusable(cache->fs_info, sinfo,
3064+
cache->zone_unusable);
30623065
sinfo->bytes_readonly -= cache->zone_unusable;
30633066
}
30643067
num_bytes = cache->length - cache->reserved -

fs/btrfs/ctree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ struct btrfs_file_private {
459459
void *filldir_buf;
460460
u64 last_index;
461461
struct extent_state *llseek_cached_state;
462+
bool fsync_skip_inode_lock;
462463
};
463464

464465
static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info)

fs/btrfs/direct-io.c

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -856,21 +856,37 @@ ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
856856
* So here we disable page faults in the iov_iter and then retry if we
857857
* got -EFAULT, faulting in the pages before the retry.
858858
*/
859+
again:
859860
from->nofault = true;
860861
dio = btrfs_dio_write(iocb, from, written);
861862
from->nofault = false;
862863

863-
/*
864-
* iomap_dio_complete() will call btrfs_sync_file() if we have a dsync
865-
* iocb, and that needs to lock the inode. So unlock it before calling
866-
* iomap_dio_complete() to avoid a deadlock.
867-
*/
868-
btrfs_inode_unlock(BTRFS_I(inode), ilock_flags);
869-
870-
if (IS_ERR_OR_NULL(dio))
864+
if (IS_ERR_OR_NULL(dio)) {
871865
ret = PTR_ERR_OR_ZERO(dio);
872-
else
866+
} else {
867+
struct btrfs_file_private stack_private = { 0 };
868+
struct btrfs_file_private *private;
869+
const bool have_private = (file->private_data != NULL);
870+
871+
if (!have_private)
872+
file->private_data = &stack_private;
873+
874+
/*
875+
* If we have a synchronous write, we must make sure the fsync
876+
* triggered by the iomap_dio_complete() call below doesn't
877+
* deadlock on the inode lock - we are already holding it and we
878+
* can't call it after unlocking because we may need to complete
879+
* partial writes due to the input buffer (or parts of it) not
880+
* being already faulted in.
881+
*/
882+
private = file->private_data;
883+
private->fsync_skip_inode_lock = true;
873884
ret = iomap_dio_complete(dio);
885+
private->fsync_skip_inode_lock = false;
886+
887+
if (!have_private)
888+
file->private_data = NULL;
889+
}
874890

875891
/* No increment (+=) because iomap returns a cumulative value. */
876892
if (ret > 0)
@@ -897,10 +913,12 @@ ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
897913
} else {
898914
fault_in_iov_iter_readable(from, left);
899915
prev_left = left;
900-
goto relock;
916+
goto again;
901917
}
902918
}
903919

920+
btrfs_inode_unlock(BTRFS_I(inode), ilock_flags);
921+
904922
/*
905923
* If 'ret' is -ENOTBLK or we have not written all data, then it means
906924
* we must fallback to buffered IO.

fs/btrfs/extent-tree.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2793,7 +2793,8 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
27932793
readonly = true;
27942794
} else if (btrfs_is_zoned(fs_info)) {
27952795
/* Need reset before reusing in a zoned block group */
2796-
space_info->bytes_zone_unusable += len;
2796+
btrfs_space_info_update_bytes_zone_unusable(fs_info, space_info,
2797+
len);
27972798
readonly = true;
27982799
}
27992800
spin_unlock(&cache->lock);

fs/btrfs/extent_map.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ static noinline int merge_extent_mapping(struct btrfs_inode *inode,
664664
start_diff = start - em->start;
665665
em->start = start;
666666
em->len = end - start;
667-
if (em->disk_bytenr < EXTENT_MAP_LAST_BYTE && !extent_map_is_compressed(em))
667+
if (em->disk_bytenr < EXTENT_MAP_LAST_BYTE)
668668
em->offset += start_diff;
669669
return add_extent_mapping(inode, em, 0);
670670
}

fs/btrfs/file.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,7 @@ static inline bool skip_inode_logging(const struct btrfs_log_ctx *ctx)
16031603
*/
16041604
int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
16051605
{
1606+
struct btrfs_file_private *private = file->private_data;
16061607
struct dentry *dentry = file_dentry(file);
16071608
struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));
16081609
struct btrfs_root *root = inode->root;
@@ -1612,6 +1613,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
16121613
int ret = 0, err;
16131614
u64 len;
16141615
bool full_sync;
1616+
const bool skip_ilock = (private ? private->fsync_skip_inode_lock : false);
16151617

16161618
trace_btrfs_sync_file(file, datasync);
16171619

@@ -1639,7 +1641,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
16391641
if (ret)
16401642
goto out;
16411643

1642-
btrfs_inode_lock(inode, BTRFS_ILOCK_MMAP);
1644+
if (skip_ilock)
1645+
down_write(&inode->i_mmap_lock);
1646+
else
1647+
btrfs_inode_lock(inode, BTRFS_ILOCK_MMAP);
16431648

16441649
atomic_inc(&root->log_batch);
16451650

@@ -1663,7 +1668,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
16631668
*/
16641669
ret = start_ordered_ops(inode, start, end);
16651670
if (ret) {
1666-
btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP);
1671+
if (skip_ilock)
1672+
up_write(&inode->i_mmap_lock);
1673+
else
1674+
btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP);
16671675
goto out;
16681676
}
16691677

@@ -1788,7 +1796,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
17881796
* file again, but that will end up using the synchronization
17891797
* inside btrfs_sync_log to keep things safe.
17901798
*/
1791-
btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP);
1799+
if (skip_ilock)
1800+
up_write(&inode->i_mmap_lock);
1801+
else
1802+
btrfs_inode_unlock(inode, BTRFS_ILOCK_MMAP);
17921803

17931804
if (ret == BTRFS_NO_LOG_SYNC) {
17941805
ret = btrfs_end_transaction(trans);

fs/btrfs/free-space-cache.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2723,8 +2723,10 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
27232723
* If the block group is read-only, we should account freed space into
27242724
* bytes_readonly.
27252725
*/
2726-
if (!block_group->ro)
2726+
if (!block_group->ro) {
27272727
block_group->zone_unusable += to_unusable;
2728+
WARN_ON(block_group->zone_unusable > block_group->length);
2729+
}
27282730
spin_unlock(&ctl->tree_lock);
27292731
if (!used) {
27302732
spin_lock(&block_group->lock);

fs/btrfs/inode.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -714,8 +714,9 @@ static noinline int __cow_file_range_inline(struct btrfs_inode *inode, u64 offse
714714
return ret;
715715
}
716716

717-
static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
718-
u64 end,
717+
static noinline int cow_file_range_inline(struct btrfs_inode *inode,
718+
struct page *locked_page,
719+
u64 offset, u64 end,
719720
size_t compressed_size,
720721
int compress_type,
721722
struct folio *compressed_folio,
@@ -739,7 +740,10 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 offset,
739740
return ret;
740741
}
741742

742-
extent_clear_unlock_delalloc(inode, offset, end, NULL, &cached,
743+
if (ret == 0)
744+
locked_page = NULL;
745+
746+
extent_clear_unlock_delalloc(inode, offset, end, locked_page, &cached,
743747
clear_flags,
744748
PAGE_UNLOCK | PAGE_START_WRITEBACK |
745749
PAGE_END_WRITEBACK);
@@ -1043,10 +1047,10 @@ static void compress_file_range(struct btrfs_work *work)
10431047
* extent for the subpage case.
10441048
*/
10451049
if (total_in < actual_end)
1046-
ret = cow_file_range_inline(inode, start, end, 0,
1050+
ret = cow_file_range_inline(inode, NULL, start, end, 0,
10471051
BTRFS_COMPRESS_NONE, NULL, false);
10481052
else
1049-
ret = cow_file_range_inline(inode, start, end, total_compressed,
1053+
ret = cow_file_range_inline(inode, NULL, start, end, total_compressed,
10501054
compress_type, folios[0], false);
10511055
if (ret <= 0) {
10521056
if (ret < 0)
@@ -1359,7 +1363,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
13591363

13601364
if (!no_inline) {
13611365
/* lets try to make an inline extent */
1362-
ret = cow_file_range_inline(inode, start, end, 0,
1366+
ret = cow_file_range_inline(inode, locked_page, start, end, 0,
13631367
BTRFS_COMPRESS_NONE, NULL, false);
13641368
if (ret <= 0) {
13651369
/*
@@ -5660,7 +5664,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
56605664
struct inode *inode;
56615665
struct btrfs_root *root = BTRFS_I(dir)->root;
56625666
struct btrfs_root *sub_root = root;
5663-
struct btrfs_key location;
5667+
struct btrfs_key location = { 0 };
56645668
u8 di_type = 0;
56655669
int ret = 0;
56665670

fs/btrfs/space-info.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info,
316316
found->bytes_used += block_group->used;
317317
found->disk_used += block_group->used * factor;
318318
found->bytes_readonly += block_group->bytes_super;
319-
found->bytes_zone_unusable += block_group->zone_unusable;
319+
btrfs_space_info_update_bytes_zone_unusable(info, found, block_group->zone_unusable);
320320
if (block_group->length > 0)
321321
found->full = 0;
322322
btrfs_try_granting_tickets(info, found);
@@ -583,8 +583,7 @@ void btrfs_dump_space_info(struct btrfs_fs_info *fs_info,
583583

584584
spin_lock(&cache->lock);
585585
avail = cache->length - cache->used - cache->pinned -
586-
cache->reserved - cache->delalloc_bytes -
587-
cache->bytes_super - cache->zone_unusable;
586+
cache->reserved - cache->bytes_super - cache->zone_unusable;
588587
btrfs_info(fs_info,
589588
"block group %llu has %llu bytes, %llu used %llu pinned %llu reserved %llu delalloc %llu super %llu zone_unusable (%llu bytes available) %s",
590589
cache->start, cache->length, cache->used, cache->pinned,

fs/btrfs/space-info.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ btrfs_space_info_update_##name(struct btrfs_fs_info *fs_info, \
249249

250250
DECLARE_SPACE_INFO_UPDATE(bytes_may_use, "space_info");
251251
DECLARE_SPACE_INFO_UPDATE(bytes_pinned, "pinned");
252+
DECLARE_SPACE_INFO_UPDATE(bytes_zone_unusable, "zone_unusable");
252253

253254
int btrfs_init_space_info(struct btrfs_fs_info *fs_info);
254255
void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info,

0 commit comments

Comments
 (0)