Skip to content

Commit cac405a

Browse files
committed
Merge tag 'for-6.6-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: - delayed refs fixes: - fix race when refilling delayed refs block reserve - prevent transaction block reserve underflow when starting transaction - error message and value adjustments - fix build warnings with CONFIG_CC_OPTIMIZE_FOR_SIZE and -Wmaybe-uninitialized - fix for smatch report where uninitialized data from invalid extent buffer range could be returned to the caller - fix numeric overflow in statfs when calculating lower threshold for a full filesystem * tag 'for-6.6-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: initialize start_slot in btrfs_log_prealloc_extents btrfs: make sure to initialize start and len in find_free_dev_extent btrfs: reset destination buffer when read_extent_buffer() gets invalid range btrfs: properly report 0 avail for very full file systems btrfs: log message if extent item not found when running delayed extent op btrfs: remove redundant BUG_ON() from __btrfs_inc_extent_ref() btrfs: return -EUCLEAN for delayed tree ref with a ref count not equals to 1 btrfs: prevent transaction block reserve underflow when starting transaction btrfs: fix race when refilling delayed refs block reserve
2 parents 50768a4 + b4c639f commit cac405a

File tree

8 files changed

+63
-33
lines changed

8 files changed

+63
-33
lines changed

fs/btrfs/delayed-ref.c

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,24 +103,17 @@ void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans)
103103
* Transfer bytes to our delayed refs rsv.
104104
*
105105
* @fs_info: the filesystem
106-
* @src: source block rsv to transfer from
107106
* @num_bytes: number of bytes to transfer
108107
*
109-
* This transfers up to the num_bytes amount from the src rsv to the
108+
* This transfers up to the num_bytes amount, previously reserved, to the
110109
* delayed_refs_rsv. Any extra bytes are returned to the space info.
111110
*/
112111
void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info,
113-
struct btrfs_block_rsv *src,
114112
u64 num_bytes)
115113
{
116114
struct btrfs_block_rsv *delayed_refs_rsv = &fs_info->delayed_refs_rsv;
117115
u64 to_free = 0;
118116

119-
spin_lock(&src->lock);
120-
src->reserved -= num_bytes;
121-
src->size -= num_bytes;
122-
spin_unlock(&src->lock);
123-
124117
spin_lock(&delayed_refs_rsv->lock);
125118
if (delayed_refs_rsv->size > delayed_refs_rsv->reserved) {
126119
u64 delta = delayed_refs_rsv->size -
@@ -163,6 +156,8 @@ int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info,
163156
struct btrfs_block_rsv *block_rsv = &fs_info->delayed_refs_rsv;
164157
u64 limit = btrfs_calc_delayed_ref_bytes(fs_info, 1);
165158
u64 num_bytes = 0;
159+
u64 refilled_bytes;
160+
u64 to_free;
166161
int ret = -ENOSPC;
167162

168163
spin_lock(&block_rsv->lock);
@@ -178,9 +173,38 @@ int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info,
178173
ret = btrfs_reserve_metadata_bytes(fs_info, block_rsv, num_bytes, flush);
179174
if (ret)
180175
return ret;
181-
btrfs_block_rsv_add_bytes(block_rsv, num_bytes, false);
182-
trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv",
183-
0, num_bytes, 1);
176+
177+
/*
178+
* We may have raced with someone else, so check again if we the block
179+
* reserve is still not full and release any excess space.
180+
*/
181+
spin_lock(&block_rsv->lock);
182+
if (block_rsv->reserved < block_rsv->size) {
183+
u64 needed = block_rsv->size - block_rsv->reserved;
184+
185+
if (num_bytes >= needed) {
186+
block_rsv->reserved += needed;
187+
block_rsv->full = true;
188+
to_free = num_bytes - needed;
189+
refilled_bytes = needed;
190+
} else {
191+
block_rsv->reserved += num_bytes;
192+
to_free = 0;
193+
refilled_bytes = num_bytes;
194+
}
195+
} else {
196+
to_free = num_bytes;
197+
refilled_bytes = 0;
198+
}
199+
spin_unlock(&block_rsv->lock);
200+
201+
if (to_free > 0)
202+
btrfs_space_info_free_bytes_may_use(fs_info, block_rsv->space_info,
203+
to_free);
204+
205+
if (refilled_bytes > 0)
206+
trace_btrfs_space_reservation(fs_info, "delayed_refs_rsv", 0,
207+
refilled_bytes, 1);
184208
return 0;
185209
}
186210

fs/btrfs/delayed-ref.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,6 @@ void btrfs_update_delayed_refs_rsv(struct btrfs_trans_handle *trans);
407407
int btrfs_delayed_refs_rsv_refill(struct btrfs_fs_info *fs_info,
408408
enum btrfs_reserve_flush_enum flush);
409409
void btrfs_migrate_to_delayed_refs_rsv(struct btrfs_fs_info *fs_info,
410-
struct btrfs_block_rsv *src,
411410
u64 num_bytes);
412411
bool btrfs_check_space_for_delayed_refs(struct btrfs_fs_info *fs_info);
413412

fs/btrfs/extent-tree.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,15 +1514,14 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
15141514
btrfs_release_path(path);
15151515

15161516
/* now insert the actual backref */
1517-
if (owner < BTRFS_FIRST_FREE_OBJECTID) {
1518-
BUG_ON(refs_to_add != 1);
1517+
if (owner < BTRFS_FIRST_FREE_OBJECTID)
15191518
ret = insert_tree_block_ref(trans, path, bytenr, parent,
15201519
root_objectid);
1521-
} else {
1520+
else
15221521
ret = insert_extent_data_ref(trans, path, bytenr, parent,
15231522
root_objectid, owner, offset,
15241523
refs_to_add);
1525-
}
1524+
15261525
if (ret)
15271526
btrfs_abort_transaction(trans, ret);
15281527
out:
@@ -1656,7 +1655,10 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
16561655
goto again;
16571656
}
16581657
} else {
1659-
err = -EIO;
1658+
err = -EUCLEAN;
1659+
btrfs_err(fs_info,
1660+
"missing extent item for extent %llu num_bytes %llu level %d",
1661+
head->bytenr, head->num_bytes, extent_op->level);
16601662
goto out;
16611663
}
16621664
}
@@ -1699,12 +1701,12 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
16991701
parent = ref->parent;
17001702
ref_root = ref->root;
17011703

1702-
if (node->ref_mod != 1) {
1704+
if (unlikely(node->ref_mod != 1)) {
17031705
btrfs_err(trans->fs_info,
1704-
"btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu",
1706+
"btree block %llu has %d references rather than 1: action %d ref_root %llu parent %llu",
17051707
node->bytenr, node->ref_mod, node->action, ref_root,
17061708
parent);
1707-
return -EIO;
1709+
return -EUCLEAN;
17081710
}
17091711
if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) {
17101712
BUG_ON(!extent_op || !extent_op->update_flags);

fs/btrfs/extent_io.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3995,8 +3995,14 @@ void read_extent_buffer(const struct extent_buffer *eb, void *dstv,
39953995
char *dst = (char *)dstv;
39963996
unsigned long i = get_eb_page_index(start);
39973997

3998-
if (check_eb_range(eb, start, len))
3998+
if (check_eb_range(eb, start, len)) {
3999+
/*
4000+
* Invalid range hit, reset the memory, so callers won't get
4001+
* some random garbage for their uninitialzed memory.
4002+
*/
4003+
memset(dstv, 0, len);
39994004
return;
4005+
}
40004006

40014007
offset = get_eb_offset_in_page(eb, start);
40024008

fs/btrfs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2117,7 +2117,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
21172117
* calculated f_bavail.
21182118
*/
21192119
if (!mixed && block_rsv->space_info->full &&
2120-
total_free_meta - thresh < block_rsv->size)
2120+
(total_free_meta < thresh || total_free_meta - thresh < block_rsv->size))
21212121
buf->f_bavail = 0;
21222122

21232123
buf->f_type = BTRFS_SUPER_MAGIC;

fs/btrfs/transaction.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,14 +631,14 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
631631
reloc_reserved = true;
632632
}
633633

634-
ret = btrfs_block_rsv_add(fs_info, rsv, num_bytes, flush);
634+
ret = btrfs_reserve_metadata_bytes(fs_info, rsv, num_bytes, flush);
635635
if (ret)
636636
goto reserve_fail;
637637
if (delayed_refs_bytes) {
638-
btrfs_migrate_to_delayed_refs_rsv(fs_info, rsv,
639-
delayed_refs_bytes);
638+
btrfs_migrate_to_delayed_refs_rsv(fs_info, delayed_refs_bytes);
640639
num_bytes -= delayed_refs_bytes;
641640
}
641+
btrfs_block_rsv_add_bytes(rsv, num_bytes, true);
642642

643643
if (rsv->space_info->force_alloc)
644644
do_chunk_alloc = true;

fs/btrfs/tree-log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4722,7 +4722,7 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans,
47224722
struct extent_buffer *leaf;
47234723
int slot;
47244724
int ins_nr = 0;
4725-
int start_slot;
4725+
int start_slot = 0;
47264726
int ret;
47274727

47284728
if (!(inode->flags & BTRFS_INODE_PREALLOC))

fs/btrfs/volumes.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,25 +1594,24 @@ static int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
15941594
u64 search_start;
15951595
u64 hole_size;
15961596
u64 max_hole_start;
1597-
u64 max_hole_size;
1597+
u64 max_hole_size = 0;
15981598
u64 extent_end;
15991599
u64 search_end = device->total_bytes;
16001600
int ret;
16011601
int slot;
16021602
struct extent_buffer *l;
16031603

16041604
search_start = dev_extent_search_start(device);
1605+
max_hole_start = search_start;
16051606

16061607
WARN_ON(device->zone_info &&
16071608
!IS_ALIGNED(num_bytes, device->zone_info->zone_size));
16081609

16091610
path = btrfs_alloc_path();
1610-
if (!path)
1611-
return -ENOMEM;
1612-
1613-
max_hole_start = search_start;
1614-
max_hole_size = 0;
1615-
1611+
if (!path) {
1612+
ret = -ENOMEM;
1613+
goto out;
1614+
}
16161615
again:
16171616
if (search_start >= search_end ||
16181617
test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state)) {

0 commit comments

Comments
 (0)