mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-28 16:53:49 +00:00
for-6.13-rc2-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmdYzmoACgkQxWXV+ddt WDv5GxAAnCsGctNax89x/VpCDZynRghrkxlzu/4kG/pqxsJyzlgXDFtzHAEewSMs MYL+WCZLYpeKB5FpZq98mDJVLGNMG+9wqkx1bH/xy2ajBGZTeQe5pnkXMNlv9U1O SX34t8nzOdTCENDnQeRc5I2vTcsQRhgHoVjJkAYdWdhcD9fs6xHKZRe+himlstSn 46ioKzEKSR3ztEUW4ycPF379g7d4kTR0hkk3pu5Nxe7ER8iq+jNSWXj0mzKg7mpJ KxP56VgY0OrsiUcJr2qFZ1hQIp810puaAuM4C1lLgRplECHxtLbP9JvL9Rr7a8Ox 68tuThyLEpQtR59078jIX3RK6CwVi15rKb/ZkLZkW19TNSAAfM5qrB146hLBUM4T 16WaiJ0x9lVkH2oYQv8zbNZiqDxPhPUdS/JArNAcQYk9ma+C1hCsxPQ/N5yoWH/C OABJddNR83sm4VTXu3Nci1EB8QuEoOuihYO6CdRkJ3PPNDuQiG6gwnoA2zqSihhy L5fQaLSWAUsLczarHZrvAi9Y0rfG66QzqGR+A1K/8qMTQ8pSCupd+LfqVa21QpI1 Awx/wVFzsAm7z9CrnPTRJe+JSlBDQdeXWX7pDhhkXgwbCsMVSf3dbBweCD3o1EiM BVI7SfEgImlbatd0QvDp9FcsnEqp90SCi+99U+zZCmQ1SW8CEC0= =+DUB -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
5a087a6b17
@ -81,6 +81,9 @@ static struct btrfs_bio *btrfs_split_bio(struct btrfs_fs_info *fs_info,
|
||||
|
||||
bio = bio_split(&orig_bbio->bio, map_length >> SECTOR_SHIFT, GFP_NOFS,
|
||||
&btrfs_clone_bioset);
|
||||
if (IS_ERR(bio))
|
||||
return ERR_CAST(bio);
|
||||
|
||||
bbio = btrfs_bio(bio);
|
||||
btrfs_bio_init(bbio, fs_info, NULL, orig_bbio);
|
||||
bbio->inode = orig_bbio->inode;
|
||||
@ -678,7 +681,8 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
|
||||
&bioc, &smap, &mirror_num);
|
||||
if (error) {
|
||||
ret = errno_to_blk_status(error);
|
||||
goto fail;
|
||||
btrfs_bio_counter_dec(fs_info);
|
||||
goto end_bbio;
|
||||
}
|
||||
|
||||
map_length = min(map_length, length);
|
||||
@ -686,7 +690,15 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
|
||||
map_length = btrfs_append_map_length(bbio, map_length);
|
||||
|
||||
if (map_length < length) {
|
||||
bbio = btrfs_split_bio(fs_info, bbio, map_length);
|
||||
struct btrfs_bio *split;
|
||||
|
||||
split = btrfs_split_bio(fs_info, bbio, map_length);
|
||||
if (IS_ERR(split)) {
|
||||
ret = errno_to_blk_status(PTR_ERR(split));
|
||||
btrfs_bio_counter_dec(fs_info);
|
||||
goto end_bbio;
|
||||
}
|
||||
bbio = split;
|
||||
bio = &bbio->bio;
|
||||
}
|
||||
|
||||
@ -760,6 +772,7 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
|
||||
|
||||
btrfs_bio_end_io(remaining, ret);
|
||||
}
|
||||
end_bbio:
|
||||
btrfs_bio_end_io(bbio, ret);
|
||||
/* Do not submit another chunk */
|
||||
return true;
|
||||
|
@ -4262,6 +4262,15 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
|
||||
* already the cleaner, but below we run all pending delayed iputs.
|
||||
*/
|
||||
btrfs_flush_workqueue(fs_info->fixup_workers);
|
||||
/*
|
||||
* Similar case here, we have to wait for delalloc workers before we
|
||||
* proceed below and stop the cleaner kthread, otherwise we trigger a
|
||||
* use-after-tree on the cleaner kthread task_struct when a delalloc
|
||||
* worker running submit_compressed_extents() adds a delayed iput, which
|
||||
* does a wake up on the cleaner kthread, which was already freed below
|
||||
* when we call kthread_stop().
|
||||
*/
|
||||
btrfs_flush_workqueue(fs_info->delalloc_workers);
|
||||
|
||||
/*
|
||||
* After we parked the cleaner kthread, ordered extents may have
|
||||
|
@ -911,6 +911,7 @@ static noinline int prepare_one_folio(struct inode *inode, struct folio **folio_
|
||||
ret = PTR_ERR(folio);
|
||||
return ret;
|
||||
}
|
||||
folio_wait_writeback(folio);
|
||||
/* Only support page sized folio yet. */
|
||||
ASSERT(folio_order(folio) == 0);
|
||||
ret = set_folio_extent_mapped(folio);
|
||||
|
@ -9876,6 +9876,7 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
|
||||
if (btrfs_root_dead(root)) {
|
||||
spin_unlock(&root->root_item_lock);
|
||||
|
||||
btrfs_drew_write_unlock(&root->snapshot_lock);
|
||||
btrfs_exclop_finish(fs_info);
|
||||
btrfs_warn(fs_info,
|
||||
"cannot activate swapfile because subvolume %llu is being deleted",
|
||||
|
@ -1885,18 +1885,21 @@ static int btrfs_get_tree_super(struct fs_context *fc)
|
||||
|
||||
if (sb->s_root) {
|
||||
btrfs_close_devices(fs_devices);
|
||||
if ((fc->sb_flags ^ sb->s_flags) & SB_RDONLY)
|
||||
ret = -EBUSY;
|
||||
/*
|
||||
* At this stage we may have RO flag mismatch between
|
||||
* fc->sb_flags and sb->s_flags. Caller should detect such
|
||||
* mismatch and reconfigure with sb->s_umount rwsem held if
|
||||
* needed.
|
||||
*/
|
||||
} else {
|
||||
snprintf(sb->s_id, sizeof(sb->s_id), "%pg", bdev);
|
||||
shrinker_debugfs_rename(sb->s_shrink, "sb-btrfs:%s", sb->s_id);
|
||||
btrfs_sb(sb)->bdev_holder = &btrfs_fs_type;
|
||||
ret = btrfs_fill_super(sb, fs_devices);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
deactivate_locked_super(sb);
|
||||
return ret;
|
||||
if (ret) {
|
||||
deactivate_locked_super(sb);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
btrfs_clear_oneshot_options(fs_info);
|
||||
@ -1982,39 +1985,18 @@ static int btrfs_get_tree_super(struct fs_context *fc)
|
||||
* btrfs or not, setting the whole super block RO. To make per-subvolume mounting
|
||||
* work with different options work we need to keep backward compatibility.
|
||||
*/
|
||||
static struct vfsmount *btrfs_reconfigure_for_mount(struct fs_context *fc)
|
||||
static int btrfs_reconfigure_for_mount(struct fs_context *fc, struct vfsmount *mnt)
|
||||
{
|
||||
struct vfsmount *mnt;
|
||||
int ret;
|
||||
const bool ro2rw = !(fc->sb_flags & SB_RDONLY);
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* We got an EBUSY because our SB_RDONLY flag didn't match the existing
|
||||
* super block, so invert our setting here and retry the mount so we
|
||||
* can get our vfsmount.
|
||||
*/
|
||||
if (ro2rw)
|
||||
fc->sb_flags |= SB_RDONLY;
|
||||
else
|
||||
fc->sb_flags &= ~SB_RDONLY;
|
||||
if (fc->sb_flags & SB_RDONLY)
|
||||
return ret;
|
||||
|
||||
mnt = fc_mount(fc);
|
||||
if (IS_ERR(mnt))
|
||||
return mnt;
|
||||
|
||||
if (!ro2rw)
|
||||
return mnt;
|
||||
|
||||
/* We need to convert to rw, call reconfigure. */
|
||||
fc->sb_flags &= ~SB_RDONLY;
|
||||
down_write(&mnt->mnt_sb->s_umount);
|
||||
ret = btrfs_reconfigure(fc);
|
||||
if (!(fc->sb_flags & SB_RDONLY) && (mnt->mnt_sb->s_flags & SB_RDONLY))
|
||||
ret = btrfs_reconfigure(fc);
|
||||
up_write(&mnt->mnt_sb->s_umount);
|
||||
if (ret) {
|
||||
mntput(mnt);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
return mnt;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btrfs_get_tree_subvol(struct fs_context *fc)
|
||||
@ -2024,6 +2006,7 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)
|
||||
struct fs_context *dup_fc;
|
||||
struct dentry *dentry;
|
||||
struct vfsmount *mnt;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
fc->security = NULL;
|
||||
|
||||
mnt = fc_mount(dup_fc);
|
||||
if (PTR_ERR_OR_ZERO(mnt) == -EBUSY)
|
||||
mnt = btrfs_reconfigure_for_mount(dup_fc);
|
||||
put_fs_context(dup_fc);
|
||||
if (IS_ERR(mnt))
|
||||
if (IS_ERR(mnt)) {
|
||||
put_fs_context(dup_fc);
|
||||
return PTR_ERR(mnt);
|
||||
}
|
||||
ret = btrfs_reconfigure_for_mount(dup_fc, mnt);
|
||||
put_fs_context(dup_fc);
|
||||
if (ret) {
|
||||
mntput(mnt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This free's ->subvol_name, because if it isn't set we have to
|
||||
|
Loading…
Reference in New Issue
Block a user