Merge tag 'for-6.0-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 28 Aug 2022 17:44:04 +0000 (10:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 28 Aug 2022 17:44:04 +0000 (10:44 -0700)
Pull btrfs fixes from David Sterba:
 "Fixes:

   - check that subvolume is writable when changing xattrs from security
     namespace

   - fix memory leak in device lookup helper

   - update generation of hole file extent item when merging holes

   - fix space cache corruption and potential double allocations; this
     is a rare bug but can be serious once it happens, stable backports
     and analysis tool will be provided

   - fix error handling when deleting root references

   - fix crash due to assert when attempting to cancel suspended device
     replace, add message what to do if mount fails due to missing
     replace item

  Regressions:

   - don't merge pages into bio if their page offset is not contiguous

   - don't allow large NOWAIT direct reads, this could lead to short
     reads eg. in io_uring"

* tag 'for-6.0-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: add info when mount fails due to stale replace target
  btrfs: replace: drop assert for suspended replace
  btrfs: fix silent failure when deleting root reference
  btrfs: fix space cache corruption and potential double allocations
  btrfs: don't allow large NOWAIT direct reads
  btrfs: don't merge pages into bio if their page offset is not contiguous
  btrfs: update generation of hole file extent item when merging holes
  btrfs: fix possible memory leak in btrfs_get_dev_args_from_path()
  btrfs: check if root is readonly while setting security xattr

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

diff --combined fs/btrfs/extent_io.c
@@@ -3233,7 -3233,7 +3233,7 @@@ static int btrfs_bio_add_page(struct bt
        u32 bio_size = bio->bi_iter.bi_size;
        u32 real_size;
        const sector_t sector = disk_bytenr >> SECTOR_SHIFT;
-       bool contig;
+       bool contig = false;
        int ret;
  
        ASSERT(bio);
        if (bio_ctrl->compress_type != compress_type)
                return 0;
  
-       if (bio_ctrl->compress_type != BTRFS_COMPRESS_NONE)
+       if (bio->bi_iter.bi_size == 0) {
+               /* We can always add a page into an empty bio. */
+               contig = true;
+       } else if (bio_ctrl->compress_type == BTRFS_COMPRESS_NONE) {
+               struct bio_vec *bvec = bio_last_bvec_all(bio);
+               /*
+                * The contig check requires the following conditions to be met:
+                * 1) The pages are belonging to the same inode
+                *    This is implied by the call chain.
+                *
+                * 2) The range has adjacent logical bytenr
+                *
+                * 3) The range has adjacent file offset
+                *    This is required for the usage of btrfs_bio->file_offset.
+                */
+               if (bio_end_sector(bio) == sector &&
+                   page_offset(bvec->bv_page) + bvec->bv_offset +
+                   bvec->bv_len == page_offset(page) + pg_offset)
+                       contig = true;
+       } else {
+               /*
+                * For compression, all IO should have its logical bytenr
+                * set to the starting bytenr of the compressed extent.
+                */
                contig = bio->bi_iter.bi_sector == sector;
-       else
-               contig = bio_end_sector(bio) == sector;
+       }
        if (!contig)
                return 0;
  
@@@ -3325,7 -3350,7 +3350,7 @@@ static int calc_bio_boundaries(struct b
  static int alloc_new_bio(struct btrfs_inode *inode,
                         struct btrfs_bio_ctrl *bio_ctrl,
                         struct writeback_control *wbc,
 -                       unsigned int opf,
 +                       blk_opf_t opf,
                         bio_end_io_t end_io_func,
                         u64 disk_bytenr, u32 offset, u64 file_offset,
                         enum btrfs_compression_type compress_type)
@@@ -3404,7 -3429,7 +3429,7 @@@ error
   * @prev_bio_flags:  flags of previous bio to see if we can merge the current one
   * @compress_type:   compress type for current bio
   */
 -static int submit_extent_page(unsigned int opf,
 +static int submit_extent_page(blk_opf_t opf,
                              struct writeback_control *wbc,
                              struct btrfs_bio_ctrl *bio_ctrl,
                              struct page *page, u64 disk_bytenr,
@@@ -3578,7 -3603,7 +3603,7 @@@ __get_extent_map(struct inode *inode, s
   */
  static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
                      struct btrfs_bio_ctrl *bio_ctrl,
 -                    unsigned int read_flags, u64 *prev_em_start)
 +                    blk_opf_t read_flags, u64 *prev_em_start)
  {
        struct inode *inode = page->mapping->host;
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
@@@ -3940,8 -3965,8 +3965,8 @@@ static noinline_for_stack int __extent_
        int saved_ret = 0;
        int ret = 0;
        int nr = 0;
 -      u32 opf = REQ_OP_WRITE;
 -      const unsigned int write_flags = wbc_to_write_flags(wbc);
 +      enum req_op op = REQ_OP_WRITE;
 +      const blk_opf_t write_flags = wbc_to_write_flags(wbc);
        bool has_error = false;
        bool compressed;
  
                iosize = min(min(em_end, end + 1), dirty_range_end) - cur;
  
                if (btrfs_use_zone_append(inode, em->block_start))
 -                      opf = REQ_OP_ZONE_APPEND;
 +                      op = REQ_OP_ZONE_APPEND;
  
                free_extent_map(em);
                em = NULL;
                 */
                btrfs_page_clear_dirty(fs_info, page, cur, iosize);
  
 -              ret = submit_extent_page(opf | write_flags, wbc,
 +              ret = submit_extent_page(op | write_flags, wbc,
                                         &epd->bio_ctrl, page,
                                         disk_bytenr, iosize,
                                         cur - page_offset(page),
@@@ -4530,7 -4555,7 +4555,7 @@@ static int write_one_subpage_eb(struct 
  {
        struct btrfs_fs_info *fs_info = eb->fs_info;
        struct page *page = eb->pages[0];
 -      unsigned int write_flags = wbc_to_write_flags(wbc);
 +      blk_opf_t write_flags = wbc_to_write_flags(wbc);
        bool no_dirty_ebs = false;
        int ret;
  
@@@ -4575,7 -4600,7 +4600,7 @@@ static noinline_for_stack int write_one
  {
        u64 disk_bytenr = eb->start;
        int i, num_pages;
 -      unsigned int write_flags = wbc_to_write_flags(wbc);
 +      blk_opf_t write_flags = wbc_to_write_flags(wbc);
        int ret = 0;
  
        prepare_eb_write(eb);
diff --combined fs/btrfs/file.c
@@@ -1848,6 -1848,7 +1848,6 @@@ static ssize_t check_direct_IO(struct b
  
  static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
  {
 -      const bool is_sync_write = (iocb->ki_flags & IOCB_DSYNC);
        struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
@@@ -1901,6 -1902,15 +1901,6 @@@ relock
        }
  
        /*
 -       * We remove IOCB_DSYNC so that we don't deadlock when iomap_dio_rw()
 -       * calls generic_write_sync() (through iomap_dio_complete()), because
 -       * that results in calling fsync (btrfs_sync_file()) which will try to
 -       * lock the inode in exclusive/write mode.
 -       */
 -      if (is_sync_write)
 -              iocb->ki_flags &= ~IOCB_DSYNC;
 -
 -      /*
         * The iov_iter can be mapped to the same file range we are writing to.
         * If that's the case, then we will deadlock in the iomap code, because
         * it first calls our callback btrfs_dio_iomap_begin(), which will create
@@@ -1955,6 -1965,13 +1955,6 @@@ again
        btrfs_inode_unlock(inode, ilock_flags);
  
        /*
 -       * Add back IOCB_DSYNC. Our caller, btrfs_file_write_iter(), will do
 -       * the fsync (call generic_write_sync()).
 -       */
 -      if (is_sync_write)
 -              iocb->ki_flags |= IOCB_DSYNC;
 -
 -      /*
         * If 'err' is -ENOTBLK or we have not written all data, then it means
         * we must fallback to buffered IO.
         */
@@@ -2035,7 -2052,7 +2035,7 @@@ ssize_t btrfs_do_write_iter(struct kioc
        struct file *file = iocb->ki_filp;
        struct btrfs_inode *inode = BTRFS_I(file_inode(file));
        ssize_t num_written, num_sync;
 -      const bool sync = iocb->ki_flags & IOCB_DSYNC;
 +      const bool sync = iocb_is_dsync(iocb);
  
        /*
         * If the fs flips readonly due to some impossible error, although we
@@@ -2482,6 -2499,7 +2482,7 @@@ static int fill_holes(struct btrfs_tran
                btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_offset(leaf, fi, 0);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_mark_buffer_dirty(leaf);
                goto out;
        }
                btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_offset(leaf, fi, 0);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_mark_buffer_dirty(leaf);
                goto out;
        }
diff --combined fs/btrfs/inode.c
@@@ -487,7 -487,7 +487,7 @@@ struct async_chunk 
        struct page *locked_page;
        u64 start;
        u64 end;
 -      unsigned int write_flags;
 +      blk_opf_t write_flags;
        struct list_head extents;
        struct cgroup_subsys_state *blkcg_css;
        struct btrfs_work work;
@@@ -1522,7 -1522,7 +1522,7 @@@ static int cow_file_range_async(struct 
        int i;
        bool should_compress;
        unsigned nofs_flag;
 -      const unsigned int write_flags = wbc_to_write_flags(wbc);
 +      const blk_opf_t write_flags = wbc_to_write_flags(wbc);
  
        unlock_extent(&inode->io_tree, start, end);
  
@@@ -7694,6 -7694,20 +7694,20 @@@ static int btrfs_dio_iomap_begin(struc
        bool unlock_extents = false;
  
        /*
+        * We could potentially fault if we have a buffer > PAGE_SIZE, and if
+        * we're NOWAIT we may submit a bio for a partial range and return
+        * EIOCBQUEUED, which would result in an errant short read.
+        *
+        * The best way to handle this would be to allow for partial completions
+        * of iocb's, so we could submit the partial bio, return and fault in
+        * the rest of the pages, and then submit the io for the rest of the
+        * range.  However we don't have that currently, so simply return
+        * -EAGAIN at this point so that the normal path is used.
+        */
+       if (!write && (flags & IOMAP_NOWAIT) && length > PAGE_SIZE)
+               return -EAGAIN;
+       /*
         * Cap the size of reads to that usually seen in buffered I/O as we need
         * to allocate a contiguous array for the checksums.
         */
@@@ -8233,8 -8247,7 +8247,8 @@@ ssize_t btrfs_dio_rw(struct kiocb *iocb
        struct btrfs_dio_data data;
  
        return iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
 -                          IOMAP_DIO_PARTIAL, &data, done_before);
 +                          IOMAP_DIO_PARTIAL | IOMAP_DIO_NOSYNC,
 +                          &data, done_before);
  }
  
  static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
@@@ -8312,24 -8325,30 +8326,24 @@@ static bool btrfs_release_folio(struct 
  }
  
  #ifdef CONFIG_MIGRATION
 -static int btrfs_migratepage(struct address_space *mapping,
 -                           struct page *newpage, struct page *page,
 +static int btrfs_migrate_folio(struct address_space *mapping,
 +                           struct folio *dst, struct folio *src,
                             enum migrate_mode mode)
  {
 -      int ret;
 +      int ret = filemap_migrate_folio(mapping, dst, src, mode);
  
 -      ret = migrate_page_move_mapping(mapping, newpage, page, 0);
        if (ret != MIGRATEPAGE_SUCCESS)
                return ret;
  
 -      if (page_has_private(page))
 -              attach_page_private(newpage, detach_page_private(page));
 -
 -      if (PageOrdered(page)) {
 -              ClearPageOrdered(page);
 -              SetPageOrdered(newpage);
 +      if (folio_test_ordered(src)) {
 +              folio_clear_ordered(src);
 +              folio_set_ordered(dst);
        }
  
 -      if (mode != MIGRATE_SYNC_NO_COPY)
 -              migrate_page_copy(newpage, page);
 -      else
 -              migrate_page_states(newpage, page);
        return MIGRATEPAGE_SUCCESS;
  }
 +#else
 +#define btrfs_migrate_folio NULL
  #endif
  
  static void btrfs_invalidate_folio(struct folio *folio, size_t offset,
@@@ -11467,7 -11486,9 +11481,7 @@@ static const struct address_space_opera
        .direct_IO      = noop_direct_IO,
        .invalidate_folio = btrfs_invalidate_folio,
        .release_folio  = btrfs_release_folio,
 -#ifdef CONFIG_MIGRATION
 -      .migratepage    = btrfs_migratepage,
 -#endif
 +      .migrate_folio  = btrfs_migrate_folio,
        .dirty_folio    = filemap_dirty_folio,
        .error_remove_page = generic_error_remove_page,
        .swap_activate  = btrfs_swap_activate,