Skip to content

Commit 5a087a6

Browse files
committed
Merge tag 'for-6.13-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few more fixes. Apart from the one liners and updated bio splitting error handling there's a fix for subvolume mount with different flags. This was known and fixed for some time but I've delayed it to give it more testing. - fix unbalanced locking when swapfile activation fails when the subvolume gets deleted in the meantime - add btrfs error handling after bio_split() calls that got error handling recently - during unmount, flush delalloc workers at the right time before the cleaner thread is shut down - fix regression in buffered write folio conversion, explicitly wait for writeback as FGP_STABLE flag is currently a no-op on btrfs - handle race in subvolume mount with different flags, the conversion to the new mount API did not handle the case where multiple subvolumes get mounted in parallel, which is a distro use case" * tag 'for-6.13-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: flush delalloc workers queue before stopping cleaner kthread during unmount btrfs: handle bio_split() errors btrfs: properly wait for writeback before buffered write btrfs: fix missing snapshot drew unlock when root is dead during swap activation btrfs: fix mount failure due to remount races
2 parents 1594c49 + f10bef7 commit 5a087a6

File tree

5 files changed

+53
-41
lines changed

5 files changed

+53
-41
lines changed

fs/btrfs/bio.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ static struct btrfs_bio *btrfs_split_bio(struct btrfs_fs_info *fs_info,
8181

8282
bio = bio_split(&orig_bbio->bio, map_length >> SECTOR_SHIFT, GFP_NOFS,
8383
&btrfs_clone_bioset);
84+
if (IS_ERR(bio))
85+
return ERR_CAST(bio);
86+
8487
bbio = btrfs_bio(bio);
8588
btrfs_bio_init(bbio, fs_info, NULL, orig_bbio);
8689
bbio->inode = orig_bbio->inode;
@@ -678,15 +681,24 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
678681
&bioc, &smap, &mirror_num);
679682
if (error) {
680683
ret = errno_to_blk_status(error);
681-
goto fail;
684+
btrfs_bio_counter_dec(fs_info);
685+
goto end_bbio;
682686
}
683687

684688
map_length = min(map_length, length);
685689
if (use_append)
686690
map_length = btrfs_append_map_length(bbio, map_length);
687691

688692
if (map_length < length) {
689-
bbio = btrfs_split_bio(fs_info, bbio, map_length);
693+
struct btrfs_bio *split;
694+
695+
split = btrfs_split_bio(fs_info, bbio, map_length);
696+
if (IS_ERR(split)) {
697+
ret = errno_to_blk_status(PTR_ERR(split));
698+
btrfs_bio_counter_dec(fs_info);
699+
goto end_bbio;
700+
}
701+
bbio = split;
690702
bio = &bbio->bio;
691703
}
692704

@@ -760,6 +772,7 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
760772

761773
btrfs_bio_end_io(remaining, ret);
762774
}
775+
end_bbio:
763776
btrfs_bio_end_io(bbio, ret);
764777
/* Do not submit another chunk */
765778
return true;

fs/btrfs/disk-io.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4262,6 +4262,15 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
42624262
* already the cleaner, but below we run all pending delayed iputs.
42634263
*/
42644264
btrfs_flush_workqueue(fs_info->fixup_workers);
4265+
/*
4266+
* Similar case here, we have to wait for delalloc workers before we
4267+
* proceed below and stop the cleaner kthread, otherwise we trigger a
4268+
* use-after-tree on the cleaner kthread task_struct when a delalloc
4269+
* worker running submit_compressed_extents() adds a delayed iput, which
4270+
* does a wake up on the cleaner kthread, which was already freed below
4271+
* when we call kthread_stop().
4272+
*/
4273+
btrfs_flush_workqueue(fs_info->delalloc_workers);
42654274

42664275
/*
42674276
* After we parked the cleaner kthread, ordered extents may have

fs/btrfs/file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,7 @@ static noinline int prepare_one_folio(struct inode *inode, struct folio **folio_
911911
ret = PTR_ERR(folio);
912912
return ret;
913913
}
914+
folio_wait_writeback(folio);
914915
/* Only support page sized folio yet. */
915916
ASSERT(folio_order(folio) == 0);
916917
ret = set_folio_extent_mapped(folio);

fs/btrfs/inode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9876,6 +9876,7 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
98769876
if (btrfs_root_dead(root)) {
98779877
spin_unlock(&root->root_item_lock);
98789878

9879+
btrfs_drew_write_unlock(&root->snapshot_lock);
98799880
btrfs_exclop_finish(fs_info);
98809881
btrfs_warn(fs_info,
98819882
"cannot activate swapfile because subvolume %llu is being deleted",

fs/btrfs/super.c

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,18 +1885,21 @@ static int btrfs_get_tree_super(struct fs_context *fc)
18851885

18861886
if (sb->s_root) {
18871887
btrfs_close_devices(fs_devices);
1888-
if ((fc->sb_flags ^ sb->s_flags) & SB_RDONLY)
1889-
ret = -EBUSY;
1888+
/*
1889+
* At this stage we may have RO flag mismatch between
1890+
* fc->sb_flags and sb->s_flags. Caller should detect such
1891+
* mismatch and reconfigure with sb->s_umount rwsem held if
1892+
* needed.
1893+
*/
18901894
} else {
18911895
snprintf(sb->s_id, sizeof(sb->s_id), "%pg", bdev);
18921896
shrinker_debugfs_rename(sb->s_shrink, "sb-btrfs:%s", sb->s_id);
18931897
btrfs_sb(sb)->bdev_holder = &btrfs_fs_type;
18941898
ret = btrfs_fill_super(sb, fs_devices);
1895-
}
1896-
1897-
if (ret) {
1898-
deactivate_locked_super(sb);
1899-
return ret;
1899+
if (ret) {
1900+
deactivate_locked_super(sb);
1901+
return ret;
1902+
}
19001903
}
19011904

19021905
btrfs_clear_oneshot_options(fs_info);
@@ -1982,39 +1985,18 @@ static int btrfs_get_tree_super(struct fs_context *fc)
19821985
* btrfs or not, setting the whole super block RO. To make per-subvolume mounting
19831986
* work with different options work we need to keep backward compatibility.
19841987
*/
1985-
static struct vfsmount *btrfs_reconfigure_for_mount(struct fs_context *fc)
1988+
static int btrfs_reconfigure_for_mount(struct fs_context *fc, struct vfsmount *mnt)
19861989
{
1987-
struct vfsmount *mnt;
1988-
int ret;
1989-
const bool ro2rw = !(fc->sb_flags & SB_RDONLY);
1990-
1991-
/*
1992-
* We got an EBUSY because our SB_RDONLY flag didn't match the existing
1993-
* super block, so invert our setting here and retry the mount so we
1994-
* can get our vfsmount.
1995-
*/
1996-
if (ro2rw)
1997-
fc->sb_flags |= SB_RDONLY;
1998-
else
1999-
fc->sb_flags &= ~SB_RDONLY;
2000-
2001-
mnt = fc_mount(fc);
2002-
if (IS_ERR(mnt))
2003-
return mnt;
1990+
int ret = 0;
20041991

2005-
if (!ro2rw)
2006-
return mnt;
1992+
if (fc->sb_flags & SB_RDONLY)
1993+
return ret;
20071994

2008-
/* We need to convert to rw, call reconfigure. */
2009-
fc->sb_flags &= ~SB_RDONLY;
20101995
down_write(&mnt->mnt_sb->s_umount);
2011-
ret = btrfs_reconfigure(fc);
1996+
if (!(fc->sb_flags & SB_RDONLY) && (mnt->mnt_sb->s_flags & SB_RDONLY))
1997+
ret = btrfs_reconfigure(fc);
20121998
up_write(&mnt->mnt_sb->s_umount);
2013-
if (ret) {
2014-
mntput(mnt);
2015-
return ERR_PTR(ret);
2016-
}
2017-
return mnt;
1999+
return ret;
20182000
}
20192001

20202002
static int btrfs_get_tree_subvol(struct fs_context *fc)
@@ -2024,6 +2006,7 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)
20242006
struct fs_context *dup_fc;
20252007
struct dentry *dentry;
20262008
struct vfsmount *mnt;
2009+
int ret = 0;
20272010

20282011
/*
20292012
* Setup a dummy root and fs_info for test/set super. This is because
@@ -2066,11 +2049,16 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)
20662049
fc->security = NULL;
20672050

20682051
mnt = fc_mount(dup_fc);
2069-
if (PTR_ERR_OR_ZERO(mnt) == -EBUSY)
2070-
mnt = btrfs_reconfigure_for_mount(dup_fc);
2071-
put_fs_context(dup_fc);
2072-
if (IS_ERR(mnt))
2052+
if (IS_ERR(mnt)) {
2053+
put_fs_context(dup_fc);
20732054
return PTR_ERR(mnt);
2055+
}
2056+
ret = btrfs_reconfigure_for_mount(dup_fc, mnt);
2057+
put_fs_context(dup_fc);
2058+
if (ret) {
2059+
mntput(mnt);
2060+
return ret;
2061+
}
20742062

20752063
/*
20762064
* This free's ->subvol_name, because if it isn't set we have to

0 commit comments

Comments
 (0)