Merge tag 'for-5.2-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 31 May 2019 03:52:40 +0000 (20:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 31 May 2019 03:52:40 +0000 (20:52 -0700)
Pull btrfs fixes from David Sterba:
 "A few more fixes for bugs reported by users, fuzzing tools and
  regressions:

   - fix crashes in relocation:
       + resuming interrupted balance operation does not properly clean
         up orphan trees
       + with enabled qgroups, resuming needs to be more careful about
         block groups due to limited context when updating qgroups

   - fsync and logging fixes found by fuzzing

   - incremental send fixes for no-holes and clone

   - fix spin lock type used in timer function for zstd"

* tag 'for-5.2-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  Btrfs: fix race updating log root item during fsync
  Btrfs: fix wrong ctime and mtime of a directory after log replay
  Btrfs: fix fsync not persisting changed attributes of a directory
  btrfs: qgroup: Check bg while resuming relocation to avoid NULL pointer dereference
  btrfs: reloc: Also queue orphan reloc tree for cleanup to avoid BUG_ON()
  Btrfs: incremental send, fix emission of invalid clone operations
  Btrfs: incremental send, fix file corruption when no-holes feature is enabled
  btrfs: correct zstd workspace manager lock to use spin_lock_bh()
  btrfs: Ensure replaced device doesn't have pending chunk allocation

1  2 
fs/btrfs/inode.c

diff --combined fs/btrfs/inode.c
@@@ -6433,8 -6433,18 +6433,18 @@@ int btrfs_add_link(struct btrfs_trans_h
        btrfs_i_size_write(parent_inode, parent_inode->vfs_inode.i_size +
                           name_len * 2);
        inode_inc_iversion(&parent_inode->vfs_inode);
-       parent_inode->vfs_inode.i_mtime = parent_inode->vfs_inode.i_ctime =
-               current_time(&parent_inode->vfs_inode);
+       /*
+        * If we are replaying a log tree, we do not want to update the mtime
+        * and ctime of the parent directory with the current time, since the
+        * log replay procedure is responsible for setting them to their correct
+        * values (the ones it had when the fsync was done).
+        */
+       if (!test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags)) {
+               struct timespec64 now = current_time(&parent_inode->vfs_inode);
+               parent_inode->vfs_inode.i_mtime = now;
+               parent_inode->vfs_inode.i_ctime = now;
+       }
        ret = btrfs_update_inode(trans, root, &parent_inode->vfs_inode);
        if (ret)
                btrfs_abort_transaction(trans, ret);
@@@ -6819,7 -6829,7 +6829,7 @@@ struct extent_map *btrfs_get_extent(str
        u64 extent_start = 0;
        u64 extent_end = 0;
        u64 objectid = btrfs_ino(inode);
 -      u8 extent_type;
 +      int extent_type = -1;
        struct btrfs_path *path = NULL;
        struct btrfs_root *root = inode->root;
        struct btrfs_file_extent_item *item;
@@@ -7872,6 -7882,7 +7882,6 @@@ static void btrfs_retry_endio_nocsum(st
        struct inode *inode = done->inode;
        struct bio_vec *bvec;
        struct extent_io_tree *io_tree, *failure_tree;
 -      int i;
        struct bvec_iter_all iter_all;
  
        if (bio->bi_status)
  
        done->uptodate = 1;
        ASSERT(!bio_flagged(bio, BIO_CLONED));
 -      bio_for_each_segment_all(bvec, bio, i, iter_all)
 +      bio_for_each_segment_all(bvec, bio, iter_all)
                clean_io_failure(BTRFS_I(inode)->root->fs_info, failure_tree,
                                 io_tree, done->start, bvec->bv_page,
                                 btrfs_ino(BTRFS_I(inode)), 0);
@@@ -7962,7 -7973,7 +7972,7 @@@ static void btrfs_retry_endio(struct bi
        struct bio_vec *bvec;
        int uptodate;
        int ret;
 -      int i;
 +      int i = 0;
        struct bvec_iter_all iter_all;
  
        if (bio->bi_status)
        failure_tree = &BTRFS_I(inode)->io_failure_tree;
  
        ASSERT(!bio_flagged(bio, BIO_CLONED));
 -      bio_for_each_segment_all(bvec, bio, i, iter_all) {
 +      bio_for_each_segment_all(bvec, bio, iter_all) {
                ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page,
                                             bvec->bv_offset, done->start,
                                             bvec->bv_len);
                                         bvec->bv_offset);
                else
                        uptodate = 0;
 +              i++;
        }
  
        done->uptodate = uptodate;
@@@ -9250,8 -9260,9 +9260,8 @@@ void btrfs_test_destroy_inode(struct in
  }
  #endif
  
 -static void btrfs_i_callback(struct rcu_head *head)
 +void btrfs_free_inode(struct inode *inode)
  {
 -      struct inode *inode = container_of(head, struct inode, i_rcu);
        kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
  }
  
@@@ -9277,7 -9288,7 +9287,7 @@@ void btrfs_destroy_inode(struct inode *
         * created.
         */
        if (!root)
 -              goto free;
 +              return;
  
        while (1) {
                ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1);
        btrfs_qgroup_check_reserved_leak(inode);
        inode_tree_del(inode);
        btrfs_drop_extent_cache(BTRFS_I(inode), 0, (u64)-1, 0);
 -free:
 -      call_rcu(&inode->i_rcu, btrfs_i_callback);
  }
  
  int btrfs_drop_inode(struct inode *inode)