Skip to content

Commit 66e55ff

Browse files
committed
Merge tag 'for-6.10-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: - fix quota root leak after quota disable failure - fix condition when checking if a zone can be added as free - allocate inode in NOFS context during logging or tree-log replay - handle raid-stripe-tree lookup correctly during scrub * tag 'for-6.10-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: qgroup: fix quota root leak after quota disable failure btrfs: scrub: handle RST lookup error correctly btrfs: zoned: fix initial free space detection btrfs: use NOFS context when getting inodes during logging and log replay
2 parents fd19d4a + a7e4c6a commit 66e55ff

File tree

4 files changed

+45
-28
lines changed

4 files changed

+45
-28
lines changed

fs/btrfs/free-space-cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2697,7 +2697,7 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
26972697
u64 offset = bytenr - block_group->start;
26982698
u64 to_free, to_unusable;
26992699
int bg_reclaim_threshold = 0;
2700-
bool initial = (size == block_group->length);
2700+
bool initial = ((size == block_group->length) && (block_group->alloc_offset == 0));
27012701
u64 reclaimable_unusable;
27022702

27032703
WARN_ON(!initial && offset + size > block_group->zone_capacity);

fs/btrfs/qgroup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,7 +1351,7 @@ static int flush_reservations(struct btrfs_fs_info *fs_info)
13511351

13521352
int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
13531353
{
1354-
struct btrfs_root *quota_root;
1354+
struct btrfs_root *quota_root = NULL;
13551355
struct btrfs_trans_handle *trans = NULL;
13561356
int ret = 0;
13571357

@@ -1449,9 +1449,9 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
14491449
btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
14501450
quota_root->node, 0, 1);
14511451

1452-
btrfs_put_root(quota_root);
14531452

14541453
out:
1454+
btrfs_put_root(quota_root);
14551455
mutex_unlock(&fs_info->qgroup_ioctl_lock);
14561456
if (ret && trans)
14571457
btrfs_end_transaction(trans);

fs/btrfs/scrub.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,20 +1688,24 @@ static void scrub_submit_extent_sector_read(struct scrub_ctx *sctx,
16881688
(i << fs_info->sectorsize_bits);
16891689
int err;
16901690

1691-
bbio = btrfs_bio_alloc(stripe->nr_sectors, REQ_OP_READ,
1692-
fs_info, scrub_read_endio, stripe);
1693-
bbio->bio.bi_iter.bi_sector = logical >> SECTOR_SHIFT;
1694-
16951691
io_stripe.is_scrub = true;
1692+
stripe_len = (nr_sectors - i) << fs_info->sectorsize_bits;
1693+
/*
1694+
* For RST cases, we need to manually split the bbio to
1695+
* follow the RST boundary.
1696+
*/
16961697
err = btrfs_map_block(fs_info, BTRFS_MAP_READ, logical,
1697-
&stripe_len, &bioc, &io_stripe,
1698-
&mirror);
1698+
&stripe_len, &bioc, &io_stripe, &mirror);
16991699
btrfs_put_bioc(bioc);
1700-
if (err) {
1701-
btrfs_bio_end_io(bbio,
1702-
errno_to_blk_status(err));
1703-
return;
1700+
if (err < 0) {
1701+
set_bit(i, &stripe->io_error_bitmap);
1702+
set_bit(i, &stripe->error_bitmap);
1703+
continue;
17041704
}
1705+
1706+
bbio = btrfs_bio_alloc(stripe->nr_sectors, REQ_OP_READ,
1707+
fs_info, scrub_read_endio, stripe);
1708+
bbio->bio.bi_iter.bi_sector = logical >> SECTOR_SHIFT;
17051709
}
17061710

17071711
__bio_add_page(&bbio->bio, page, fs_info->sectorsize, pgoff);

fs/btrfs/tree-log.c

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,25 @@ static void wait_log_commit(struct btrfs_root *root, int transid);
138138
* and once to do all the other items.
139139
*/
140140

141+
static struct inode *btrfs_iget_logging(u64 objectid, struct btrfs_root *root)
142+
{
143+
unsigned int nofs_flag;
144+
struct inode *inode;
145+
146+
/*
147+
* We're holding a transaction handle whether we are logging or
148+
* replaying a log tree, so we must make sure NOFS semantics apply
149+
* because btrfs_alloc_inode() may be triggered and it uses GFP_KERNEL
150+
* to allocate an inode, which can recurse back into the filesystem and
151+
* attempt a transaction commit, resulting in a deadlock.
152+
*/
153+
nofs_flag = memalloc_nofs_save();
154+
inode = btrfs_iget(root->fs_info->sb, objectid, root);
155+
memalloc_nofs_restore(nofs_flag);
156+
157+
return inode;
158+
}
159+
141160
/*
142161
* start a sub transaction and setup the log tree
143162
* this increments the log tree writer count to make the people
@@ -600,7 +619,7 @@ static noinline struct inode *read_one_inode(struct btrfs_root *root,
600619
{
601620
struct inode *inode;
602621

603-
inode = btrfs_iget(root->fs_info->sb, objectid, root);
622+
inode = btrfs_iget_logging(objectid, root);
604623
if (IS_ERR(inode))
605624
inode = NULL;
606625
return inode;
@@ -5438,7 +5457,6 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
54385457
struct btrfs_log_ctx *ctx)
54395458
{
54405459
struct btrfs_root *root = start_inode->root;
5441-
struct btrfs_fs_info *fs_info = root->fs_info;
54425460
struct btrfs_path *path;
54435461
LIST_HEAD(dir_list);
54445462
struct btrfs_dir_list *dir_elem;
@@ -5499,7 +5517,7 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
54995517
continue;
55005518

55015519
btrfs_release_path(path);
5502-
di_inode = btrfs_iget(fs_info->sb, di_key.objectid, root);
5520+
di_inode = btrfs_iget_logging(di_key.objectid, root);
55035521
if (IS_ERR(di_inode)) {
55045522
ret = PTR_ERR(di_inode);
55055523
goto out;
@@ -5559,7 +5577,7 @@ static int log_new_dir_dentries(struct btrfs_trans_handle *trans,
55595577
btrfs_add_delayed_iput(curr_inode);
55605578
curr_inode = NULL;
55615579

5562-
vfs_inode = btrfs_iget(fs_info->sb, ino, root);
5580+
vfs_inode = btrfs_iget_logging(ino, root);
55635581
if (IS_ERR(vfs_inode)) {
55645582
ret = PTR_ERR(vfs_inode);
55655583
break;
@@ -5654,7 +5672,7 @@ static int add_conflicting_inode(struct btrfs_trans_handle *trans,
56545672
if (ctx->num_conflict_inodes >= MAX_CONFLICT_INODES)
56555673
return BTRFS_LOG_FORCE_COMMIT;
56565674

5657-
inode = btrfs_iget(root->fs_info->sb, ino, root);
5675+
inode = btrfs_iget_logging(ino, root);
56585676
/*
56595677
* If the other inode that had a conflicting dir entry was deleted in
56605678
* the current transaction then we either:
@@ -5755,7 +5773,6 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
57555773
struct btrfs_root *root,
57565774
struct btrfs_log_ctx *ctx)
57575775
{
5758-
struct btrfs_fs_info *fs_info = root->fs_info;
57595776
int ret = 0;
57605777

57615778
/*
@@ -5786,7 +5803,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
57865803
list_del(&curr->list);
57875804
kfree(curr);
57885805

5789-
inode = btrfs_iget(fs_info->sb, ino, root);
5806+
inode = btrfs_iget_logging(ino, root);
57905807
/*
57915808
* If the other inode that had a conflicting dir entry was
57925809
* deleted in the current transaction, we need to log its parent
@@ -5797,7 +5814,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
57975814
if (ret != -ENOENT)
57985815
break;
57995816

5800-
inode = btrfs_iget(fs_info->sb, parent, root);
5817+
inode = btrfs_iget_logging(parent, root);
58015818
if (IS_ERR(inode)) {
58025819
ret = PTR_ERR(inode);
58035820
break;
@@ -6319,7 +6336,6 @@ static int log_new_delayed_dentries(struct btrfs_trans_handle *trans,
63196336
struct btrfs_log_ctx *ctx)
63206337
{
63216338
const bool orig_log_new_dentries = ctx->log_new_dentries;
6322-
struct btrfs_fs_info *fs_info = trans->fs_info;
63236339
struct btrfs_delayed_item *item;
63246340
int ret = 0;
63256341

@@ -6345,7 +6361,7 @@ static int log_new_delayed_dentries(struct btrfs_trans_handle *trans,
63456361
if (key.type == BTRFS_ROOT_ITEM_KEY)
63466362
continue;
63476363

6348-
di_inode = btrfs_iget(fs_info->sb, key.objectid, inode->root);
6364+
di_inode = btrfs_iget_logging(key.objectid, inode->root);
63496365
if (IS_ERR(di_inode)) {
63506366
ret = PTR_ERR(di_inode);
63516367
break;
@@ -6729,7 +6745,6 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,
67296745
struct btrfs_inode *inode,
67306746
struct btrfs_log_ctx *ctx)
67316747
{
6732-
struct btrfs_fs_info *fs_info = trans->fs_info;
67336748
int ret;
67346749
struct btrfs_path *path;
67356750
struct btrfs_key key;
@@ -6794,8 +6809,7 @@ static int btrfs_log_all_parents(struct btrfs_trans_handle *trans,
67946809
cur_offset = item_size;
67956810
}
67966811

6797-
dir_inode = btrfs_iget(fs_info->sb, inode_key.objectid,
6798-
root);
6812+
dir_inode = btrfs_iget_logging(inode_key.objectid, root);
67996813
/*
68006814
* If the parent inode was deleted, return an error to
68016815
* fallback to a transaction commit. This is to prevent
@@ -6857,7 +6871,6 @@ static int log_new_ancestors(struct btrfs_trans_handle *trans,
68576871
btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]);
68586872

68596873
while (true) {
6860-
struct btrfs_fs_info *fs_info = root->fs_info;
68616874
struct extent_buffer *leaf;
68626875
int slot;
68636876
struct btrfs_key search_key;
@@ -6872,7 +6885,7 @@ static int log_new_ancestors(struct btrfs_trans_handle *trans,
68726885
search_key.objectid = found_key.offset;
68736886
search_key.type = BTRFS_INODE_ITEM_KEY;
68746887
search_key.offset = 0;
6875-
inode = btrfs_iget(fs_info->sb, ino, root);
6888+
inode = btrfs_iget_logging(ino, root);
68766889
if (IS_ERR(inode))
68776890
return PTR_ERR(inode);
68786891

0 commit comments

Comments
 (0)