Merge tag 'for-5.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 30 Sep 2019 17:25:24 +0000 (10:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 30 Sep 2019 17:25:24 +0000 (10:25 -0700)
Pull btrfs fixes from David Sterba:
 "A bunch of fixes that accumulated in recent weeks, mostly material for
  stable.

  Summary:

   - fix for regression from 5.3 that prevents to use balance convert
     with single profile

   - qgroup fixes: rescan race, accounting leak with multiple writers,
     potential leak after io failure recovery

   - fix for use after free in relocation (reported by KASAN)

   - other error handling fixups"

* tag 'for-5.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: qgroup: Fix reserved data space leak if we have multiple reserve calls
  btrfs: qgroup: Fix the wrong target io_tree when freeing reserved data space
  btrfs: Fix a regression which we can't convert to SINGLE profile
  btrfs: relocation: fix use-after-free on dead relocation roots
  Btrfs: fix race setting up and completing qgroup rescan workers
  Btrfs: fix missing error return if writeback for extent buffer never started
  btrfs: adjust dirty_metadata_bytes after writeback failure of extent buffer
  Btrfs: fix selftests failure due to uninitialized i_mode in test inodes

1  2 
fs/btrfs/extent_io.c

diff --combined fs/btrfs/extent_io.c
index 7b32b6af322d6ca2b9a4bb8e77b1f8c7daf579ef,380ced84d4b1a3d0e32d6fa361a664b6f759008a..cceaf05aada269ef659cba385a984459f2e5f911
@@@ -3628,13 -3628,6 +3628,13 @@@ void wait_on_extent_buffer_writeback(st
                       TASK_UNINTERRUPTIBLE);
  }
  
 +static void end_extent_buffer_writeback(struct extent_buffer *eb)
 +{
 +      clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
 +      smp_mb__after_atomic();
 +      wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
 +}
 +
  /*
   * Lock eb pages and flush the bio if we can't the locks
   *
@@@ -3706,11 -3699,8 +3706,11 @@@ static noinline_for_stack int lock_exte
  
                if (!trylock_page(p)) {
                        if (!flush) {
 -                              ret = flush_write_bio(epd);
 -                              if (ret < 0) {
 +                              int err;
 +
 +                              err = flush_write_bio(epd);
 +                              if (err < 0) {
 +                                      ret = err;
                                        failed_page_nr = i;
                                        goto err_unlock;
                                }
@@@ -3725,31 -3715,33 +3725,40 @@@ err_unlock
        /* Unlock already locked pages */
        for (i = 0; i < failed_page_nr; i++)
                unlock_page(eb->pages[i]);
 +      /*
 +       * Clear EXTENT_BUFFER_WRITEBACK and wake up anyone waiting on it.
 +       * Also set back EXTENT_BUFFER_DIRTY so future attempts to this eb can
 +       * be made and undo everything done before.
 +       */
 +      btrfs_tree_lock(eb);
 +      spin_lock(&eb->refs_lock);
 +      set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
 +      end_extent_buffer_writeback(eb);
 +      spin_unlock(&eb->refs_lock);
 +      percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, eb->len,
 +                               fs_info->dirty_metadata_batch);
 +      btrfs_clear_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
 +      btrfs_tree_unlock(eb);
        return ret;
  }
  
 -static void end_extent_buffer_writeback(struct extent_buffer *eb)
 -{
 -      clear_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
 -      smp_mb__after_atomic();
 -      wake_up_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK);
 -}
 -
  static void set_btree_ioerr(struct page *page)
  {
        struct extent_buffer *eb = (struct extent_buffer *)page->private;
+       struct btrfs_fs_info *fs_info;
  
        SetPageError(page);
        if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))
                return;
  
+       /*
+        * If we error out, we should add back the dirty_metadata_bytes
+        * to make it consistent.
+        */
+       fs_info = eb->fs_info;
+       percpu_counter_add_batch(&fs_info->dirty_metadata_bytes,
+                                eb->len, fs_info->dirty_metadata_batch);
        /*
         * If writeback for a btree extent that doesn't belong to a log tree
         * failed, increment the counter transaction->eb_write_errors.
@@@ -3986,6 -3978,10 +3995,10 @@@ retry
                        if (!ret) {
                                free_extent_buffer(eb);
                                continue;
+                       } else if (ret < 0) {
+                               done = 1;
+                               free_extent_buffer(eb);
+                               break;
                        }
  
                        ret = write_one_eb(eb, wbc, &epd);