]> Git Repo - J-linux.git/commitdiff
Merge tag 'for-6.13-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <[email protected]>
Wed, 11 Dec 2024 02:18:01 +0000 (18:18 -0800)
committerLinus Torvalds <[email protected]>
Wed, 11 Dec 2024 02:18:01 +0000 (18:18 -0800)
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

1  2 
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/super.c

diff --combined fs/btrfs/file.c
index 588c353d296935d6cc100e5d48d1a1d8671b3d8c,8734f5fc681f14c004aebaa2075d7b38f16c83ff..14e27473c5bcea8d1959ac1814babe022c7f5cf0
@@@ -911,6 -911,7 +911,7 @@@ again
                        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);
@@@ -1067,6 -1068,26 +1068,6 @@@ void btrfs_check_nocow_unlock(struct bt
        btrfs_drew_write_unlock(&inode->root->snapshot_lock);
  }
  
 -static void update_time_for_write(struct inode *inode)
 -{
 -      struct timespec64 now, ts;
 -
 -      if (IS_NOCMTIME(inode))
 -              return;
 -
 -      now = current_time(inode);
 -      ts = inode_get_mtime(inode);
 -      if (!timespec64_equal(&ts, &now))
 -              inode_set_mtime_to_ts(inode, now);
 -
 -      ts = inode_get_ctime(inode);
 -      if (!timespec64_equal(&ts, &now))
 -              inode_set_ctime_to_ts(inode, now);
 -
 -      if (IS_I_VERSION(inode))
 -              inode_inc_iversion(inode);
 -}
 -
  int btrfs_write_check(struct kiocb *iocb, size_t count)
  {
        struct file *file = iocb->ki_filp;
         * need to start yet another transaction to update the inode as we will
         * update the inode when we finish writing whatever data we write.
         */
 -      update_time_for_write(inode);
 +      if (!IS_NOCMTIME(inode)) {
 +              inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
 +              inode_inc_iversion(inode);
 +      }
  
        start_pos = round_down(pos, fs_info->sectorsize);
        oldsize = i_size_read(inode);
diff --combined fs/btrfs/inode.c
index fa648ab6fe80664212fb27db58a7a89e567a7519,94c8809e817057eed7b6a9362c8cd481ca9cea17..488edca8333aadc43c3fe0f8924d4479dd8194f5
@@@ -1481,7 -1481,7 +1481,7 @@@ static noinline int cow_file_range(stru
                 * (which the caller expects to stay locked), don't clear any
                 * dirty bits and don't set any writeback bits
                 *
 -               * Do set the Ordered (Private2) bit so we know this page was
 +               * Do set the Ordered flag so we know this page was
                 * properly setup for writepage.
                 */
                page_ops = (keep_locked ? 0 : PAGE_UNLOCK);
@@@ -1698,7 -1698,7 +1698,7 @@@ static bool run_delalloc_compressed(str
                         * need full accuracy.  Just account the whole thing
                         * against the first page.
                         */
 -                      wbc_account_cgroup_owner(wbc, &locked_folio->page,
 +                      wbc_account_cgroup_owner(wbc, locked_folio,
                                                 cur_end - start);
                        async_chunk[i].locked_folio = locked_folio;
                        locked_folio = NULL;
@@@ -7284,7 -7284,7 +7284,7 @@@ static void btrfs_invalidate_folio(stru
         *
         * But already submitted bio can still be finished on this folio.
         * Furthermore, endio function won't skip folio which has Ordered
 -       * (Private2) already cleared, so it's possible for endio and
 +       * already cleared, so it's possible for endio and
         * invalidate_folio to do the same ordered extent accounting twice
         * on one folio.
         *
                range_len = range_end + 1 - cur;
                if (!btrfs_folio_test_ordered(fs_info, folio, cur, range_len)) {
                        /*
 -                       * If Ordered (Private2) is cleared, it means endio has
 +                       * If Ordered is cleared, it means endio has
                         * already been executed for the range.
                         * We can't delete the extent states as
                         * btrfs_finish_ordered_io() may still use some of them.
@@@ -7423,7 -7423,7 +7423,7 @@@ next
        }
        /*
         * We have iterated through all ordered extents of the page, the page
 -       * should not have Ordered (Private2) anymore, or the above iteration
 +       * should not have Ordered anymore, or the above iteration
         * did something wrong.
         */
        ASSERT(!folio_test_ordered(folio));
@@@ -9876,6 -9876,7 +9876,7 @@@ static int btrfs_swap_activate(struct s
        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",
diff --combined fs/btrfs/super.c
index 97a85d180b61ab9b0c709b5548cbfb42322811b2,387e4cf8b53df6965d5716fb6f6493eb866ea2a8..7dfe5005129a1dd554a2271cf012a0b200b40b73
@@@ -1885,18 -1885,21 +1885,21 @@@ static int btrfs_get_tree_super(struct 
  
        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 +1985,18 @@@ error
   * 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);
-       /*
-        * 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;
-       mnt = fc_mount(fc);
-       if (IS_ERR(mnt))
-               return mnt;
+       int ret = 0;
  
-       if (!ro2rw)
-               return mnt;
+       if (fc->sb_flags & SB_RDONLY)
+               return ret;
  
-       /* 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)
        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
        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
@@@ -2189,8 -2177,7 +2177,8 @@@ static struct file_system_type btrfs_fs
        .init_fs_context        = btrfs_init_fs_context,
        .parameters             = btrfs_fs_parameters,
        .kill_sb                = btrfs_kill_super,
 -      .fs_flags               = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA | FS_ALLOW_IDMAP,
 +      .fs_flags               = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA |
 +                                FS_ALLOW_IDMAP | FS_MGTIME,
   };
  
  MODULE_ALIAS_FS("btrfs");
This page took 0.10644 seconds and 4 git commands to generate.