Skip to content

Commit b6c1f1e

Browse files
committed
Merge tag 'for-6.8-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A more fixes for recently reported or discovered problems: - fix corner case of send that would generate potentially large stream of zeros if there's a hole at the end of the file - fix chunk validation in zoned mode on conventional zones, it was possible to create chunks that would not be allowed on sequential zones - fix validation of dev-replace ioctl filenames - fix KCSAN warnings about access to block reserve struct members" * tag 'for-6.8-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: fix data race at btrfs_use_block_rsv() when accessing block reserve btrfs: fix data races when accessing the reserved amount of block reserves btrfs: send: don't issue unnecessary zero writes for trailing hole btrfs: dev-replace: properly validate device names btrfs: zoned: don't skip block group profile checks on conventional zones
2 parents c8e3146 + c7bb26b commit b6c1f1e

File tree

6 files changed

+88
-22
lines changed

6 files changed

+88
-22
lines changed

fs/btrfs/block-rsv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ struct btrfs_block_rsv *btrfs_use_block_rsv(struct btrfs_trans_handle *trans,
494494

495495
block_rsv = get_block_rsv(trans, root);
496496

497-
if (unlikely(block_rsv->size == 0))
497+
if (unlikely(btrfs_block_rsv_size(block_rsv) == 0))
498498
goto try_reserve;
499499
again:
500500
ret = btrfs_block_rsv_use_bytes(block_rsv, blocksize);

fs/btrfs/block-rsv.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,36 @@ static inline bool btrfs_block_rsv_full(const struct btrfs_block_rsv *rsv)
101101
return data_race(rsv->full);
102102
}
103103

104+
/*
105+
* Get the reserved mount of a block reserve in a context where getting a stale
106+
* value is acceptable, instead of accessing it directly and trigger data race
107+
* warning from KCSAN.
108+
*/
109+
static inline u64 btrfs_block_rsv_reserved(struct btrfs_block_rsv *rsv)
110+
{
111+
u64 ret;
112+
113+
spin_lock(&rsv->lock);
114+
ret = rsv->reserved;
115+
spin_unlock(&rsv->lock);
116+
117+
return ret;
118+
}
119+
120+
/*
121+
* Get the size of a block reserve in a context where getting a stale value is
122+
* acceptable, instead of accessing it directly and trigger data race warning
123+
* from KCSAN.
124+
*/
125+
static inline u64 btrfs_block_rsv_size(struct btrfs_block_rsv *rsv)
126+
{
127+
u64 ret;
128+
129+
spin_lock(&rsv->lock);
130+
ret = rsv->size;
131+
spin_unlock(&rsv->lock);
132+
133+
return ret;
134+
}
135+
104136
#endif /* BTRFS_BLOCK_RSV_H */

fs/btrfs/dev-replace.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,23 @@ static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
725725
return ret;
726726
}
727727

728+
static int btrfs_check_replace_dev_names(struct btrfs_ioctl_dev_replace_args *args)
729+
{
730+
if (args->start.srcdevid == 0) {
731+
if (memchr(args->start.srcdev_name, 0,
732+
sizeof(args->start.srcdev_name)) == NULL)
733+
return -ENAMETOOLONG;
734+
} else {
735+
args->start.srcdev_name[0] = 0;
736+
}
737+
738+
if (memchr(args->start.tgtdev_name, 0,
739+
sizeof(args->start.tgtdev_name)) == NULL)
740+
return -ENAMETOOLONG;
741+
742+
return 0;
743+
}
744+
728745
int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info,
729746
struct btrfs_ioctl_dev_replace_args *args)
730747
{
@@ -737,10 +754,9 @@ int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info,
737754
default:
738755
return -EINVAL;
739756
}
740-
741-
if ((args->start.srcdevid == 0 && args->start.srcdev_name[0] == '\0') ||
742-
args->start.tgtdev_name[0] == '\0')
743-
return -EINVAL;
757+
ret = btrfs_check_replace_dev_names(args);
758+
if (ret < 0)
759+
return ret;
744760

745761
ret = btrfs_dev_replace_start(fs_info, args->start.tgtdev_name,
746762
args->start.srcdevid,

fs/btrfs/send.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6705,11 +6705,20 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
67056705
if (ret)
67066706
goto out;
67076707
}
6708-
if (sctx->cur_inode_last_extent <
6709-
sctx->cur_inode_size) {
6710-
ret = send_hole(sctx, sctx->cur_inode_size);
6711-
if (ret)
6708+
if (sctx->cur_inode_last_extent < sctx->cur_inode_size) {
6709+
ret = range_is_hole_in_parent(sctx,
6710+
sctx->cur_inode_last_extent,
6711+
sctx->cur_inode_size);
6712+
if (ret < 0) {
67126713
goto out;
6714+
} else if (ret == 0) {
6715+
ret = send_hole(sctx, sctx->cur_inode_size);
6716+
if (ret < 0)
6717+
goto out;
6718+
} else {
6719+
/* Range is already a hole, skip. */
6720+
ret = 0;
6721+
}
67136722
}
67146723
}
67156724
if (need_truncate) {

fs/btrfs/space-info.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
856856
static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info,
857857
struct btrfs_space_info *space_info)
858858
{
859-
u64 global_rsv_size = fs_info->global_block_rsv.reserved;
859+
const u64 global_rsv_size = btrfs_block_rsv_reserved(&fs_info->global_block_rsv);
860860
u64 ordered, delalloc;
861861
u64 thresh;
862862
u64 used;
@@ -956,8 +956,8 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info,
956956
ordered = percpu_counter_read_positive(&fs_info->ordered_bytes) >> 1;
957957
delalloc = percpu_counter_read_positive(&fs_info->delalloc_bytes);
958958
if (ordered >= delalloc)
959-
used += fs_info->delayed_refs_rsv.reserved +
960-
fs_info->delayed_block_rsv.reserved;
959+
used += btrfs_block_rsv_reserved(&fs_info->delayed_refs_rsv) +
960+
btrfs_block_rsv_reserved(&fs_info->delayed_block_rsv);
961961
else
962962
used += space_info->bytes_may_use - global_rsv_size;
963963

@@ -1173,7 +1173,7 @@ static void btrfs_preempt_reclaim_metadata_space(struct work_struct *work)
11731173
enum btrfs_flush_state flush;
11741174
u64 delalloc_size = 0;
11751175
u64 to_reclaim, block_rsv_size;
1176-
u64 global_rsv_size = global_rsv->reserved;
1176+
const u64 global_rsv_size = btrfs_block_rsv_reserved(global_rsv);
11771177

11781178
loops++;
11791179

@@ -1185,9 +1185,9 @@ static void btrfs_preempt_reclaim_metadata_space(struct work_struct *work)
11851185
* assume it's tied up in delalloc reservations.
11861186
*/
11871187
block_rsv_size = global_rsv_size +
1188-
delayed_block_rsv->reserved +
1189-
delayed_refs_rsv->reserved +
1190-
trans_rsv->reserved;
1188+
btrfs_block_rsv_reserved(delayed_block_rsv) +
1189+
btrfs_block_rsv_reserved(delayed_refs_rsv) +
1190+
btrfs_block_rsv_reserved(trans_rsv);
11911191
if (block_rsv_size < space_info->bytes_may_use)
11921192
delalloc_size = space_info->bytes_may_use - block_rsv_size;
11931193

@@ -1207,16 +1207,16 @@ static void btrfs_preempt_reclaim_metadata_space(struct work_struct *work)
12071207
to_reclaim = delalloc_size;
12081208
flush = FLUSH_DELALLOC;
12091209
} else if (space_info->bytes_pinned >
1210-
(delayed_block_rsv->reserved +
1211-
delayed_refs_rsv->reserved)) {
1210+
(btrfs_block_rsv_reserved(delayed_block_rsv) +
1211+
btrfs_block_rsv_reserved(delayed_refs_rsv))) {
12121212
to_reclaim = space_info->bytes_pinned;
12131213
flush = COMMIT_TRANS;
1214-
} else if (delayed_block_rsv->reserved >
1215-
delayed_refs_rsv->reserved) {
1216-
to_reclaim = delayed_block_rsv->reserved;
1214+
} else if (btrfs_block_rsv_reserved(delayed_block_rsv) >
1215+
btrfs_block_rsv_reserved(delayed_refs_rsv)) {
1216+
to_reclaim = btrfs_block_rsv_reserved(delayed_block_rsv);
12171217
flush = FLUSH_DELAYED_ITEMS_NR;
12181218
} else {
1219-
to_reclaim = delayed_refs_rsv->reserved;
1219+
to_reclaim = btrfs_block_rsv_reserved(delayed_refs_rsv);
12201220
flush = FLUSH_DELAYED_REFS_NR;
12211221
}
12221222

fs/btrfs/zoned.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,15 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
16391639
}
16401640

16411641
out:
1642+
/* Reject non SINGLE data profiles without RST */
1643+
if ((map->type & BTRFS_BLOCK_GROUP_DATA) &&
1644+
(map->type & BTRFS_BLOCK_GROUP_PROFILE_MASK) &&
1645+
!fs_info->stripe_root) {
1646+
btrfs_err(fs_info, "zoned: data %s needs raid-stripe-tree",
1647+
btrfs_bg_type_to_raid_name(map->type));
1648+
return -EINVAL;
1649+
}
1650+
16421651
if (cache->alloc_offset > cache->zone_capacity) {
16431652
btrfs_err(fs_info,
16441653
"zoned: invalid write pointer %llu (larger than zone capacity %llu) in block group %llu",

0 commit comments

Comments
 (0)