]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
Merge tag 'for-4.20-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 28 Nov 2018 16:38:20 +0000 (08:38 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 28 Nov 2018 16:38:20 +0000 (08:38 -0800)
Pull btrfs fixes from David Sterba:
 "Some of these bugs are being hit during testing so we'd like to get
  them merged, otherwise there are usual stability fixes for stable
  trees"

* tag 'for-4.20-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: relocation: set trans to be NULL after ending transaction
  Btrfs: fix race between enabling quotas and subvolume creation
  Btrfs: send, fix infinite loop due to directory rename dependencies
  Btrfs: ensure path name is null terminated at btrfs_control_ioctl
  Btrfs: fix rare chances for data loss when doing a fast fsync
  btrfs: Always try all copies when reading extent buffers

fs/btrfs/disk-io.c
fs/btrfs/file.c
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/send.c
fs/btrfs/super.c

index 3f0b6d1936e8ecd05dc0bf4957bb6aa691204dd4..6d776717d8b39b566e6ec14f479648ad6f788905 100644 (file)
@@ -477,9 +477,9 @@ static int btree_read_extent_buffer_pages(struct btrfs_fs_info *fs_info,
        int mirror_num = 0;
        int failed_mirror = 0;
 
-       clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
        io_tree = &BTRFS_I(fs_info->btree_inode)->io_tree;
        while (1) {
+               clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
                ret = read_extent_buffer_pages(io_tree, eb, WAIT_COMPLETE,
                                               mirror_num);
                if (!ret) {
@@ -493,15 +493,6 @@ static int btree_read_extent_buffer_pages(struct btrfs_fs_info *fs_info,
                                break;
                }
 
-               /*
-                * This buffer's crc is fine, but its contents are corrupted, so
-                * there is no reason to read the other copies, they won't be
-                * any less wrong.
-                */
-               if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags) ||
-                   ret == -EUCLEAN)
-                       break;
-
                num_copies = btrfs_num_copies(fs_info,
                                              eb->start, eb->len);
                if (num_copies == 1)
index a3c22e16509b3067e65e86f1b98d2d9e9e84d99a..58e93bce30362dc0584c212ba18822ed13fde723 100644 (file)
@@ -2088,6 +2088,30 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        atomic_inc(&root->log_batch);
 
+       /*
+        * Before we acquired the inode's lock, someone may have dirtied more
+        * pages in the target range. We need to make sure that writeback for
+        * any such pages does not start while we are logging the inode, because
+        * if it does, any of the following might happen when we are not doing a
+        * full inode sync:
+        *
+        * 1) We log an extent after its writeback finishes but before its
+        *    checksums are added to the csum tree, leading to -EIO errors
+        *    when attempting to read the extent after a log replay.
+        *
+        * 2) We can end up logging an extent before its writeback finishes.
+        *    Therefore after the log replay we will have a file extent item
+        *    pointing to an unwritten extent (and no data checksums as well).
+        *
+        * So trigger writeback for any eventual new dirty pages and then we
+        * wait for all ordered extents to complete below.
+        */
+       ret = start_ordered_ops(inode, start, end);
+       if (ret) {
+               inode_unlock(inode);
+               goto out;
+       }
+
        /*
         * We have to do this here to avoid the priority inversion of waiting on
         * IO of a lower priority task while holding a transaciton open.
index 45868fd76209024dc2cfc790801ffac9133a3ef1..f70825af6438e9c48ebe782f6b8049d27ae807fc 100644 (file)
@@ -2659,7 +2659,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
        int i;
        u64 *i_qgroups;
        struct btrfs_fs_info *fs_info = trans->fs_info;
-       struct btrfs_root *quota_root = fs_info->quota_root;
+       struct btrfs_root *quota_root;
        struct btrfs_qgroup *srcgroup;
        struct btrfs_qgroup *dstgroup;
        u32 level_size = 0;
@@ -2669,6 +2669,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
        if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
                goto out;
 
+       quota_root = fs_info->quota_root;
        if (!quota_root) {
                ret = -EINVAL;
                goto out;
index 924116f654a110cb9e23a878002bed0ae967029e..a3f75b8926d4474aa1093ffdd852d422b853e2d2 100644 (file)
@@ -3959,6 +3959,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
 restart:
                if (update_backref_cache(trans, &rc->backref_cache)) {
                        btrfs_end_transaction(trans);
+                       trans = NULL;
                        continue;
                }
 
index 094cc1444a90caaf0a597bd6c4a16ae265462701..5be83b5a1b43121234c6d0edda9e1c0566f30132 100644 (file)
@@ -3340,7 +3340,8 @@ static void free_pending_move(struct send_ctx *sctx, struct pending_dir_move *m)
        kfree(m);
 }
 
-static void tail_append_pending_moves(struct pending_dir_move *moves,
+static void tail_append_pending_moves(struct send_ctx *sctx,
+                                     struct pending_dir_move *moves,
                                      struct list_head *stack)
 {
        if (list_empty(&moves->list)) {
@@ -3351,6 +3352,10 @@ static void tail_append_pending_moves(struct pending_dir_move *moves,
                list_add_tail(&moves->list, stack);
                list_splice_tail(&list, stack);
        }
+       if (!RB_EMPTY_NODE(&moves->node)) {
+               rb_erase(&moves->node, &sctx->pending_dir_moves);
+               RB_CLEAR_NODE(&moves->node);
+       }
 }
 
 static int apply_children_dir_moves(struct send_ctx *sctx)
@@ -3365,7 +3370,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
                return 0;
 
        INIT_LIST_HEAD(&stack);
-       tail_append_pending_moves(pm, &stack);
+       tail_append_pending_moves(sctx, pm, &stack);
 
        while (!list_empty(&stack)) {
                pm = list_first_entry(&stack, struct pending_dir_move, list);
@@ -3376,7 +3381,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
                        goto out;
                pm = get_pending_dir_moves(sctx, parent_ino);
                if (pm)
-                       tail_append_pending_moves(pm, &stack);
+                       tail_append_pending_moves(sctx, pm, &stack);
        }
        return 0;
 
index cbc9d0d2c12de42786da57c41ebbc9f0364ffabd..645fc81e2a948eab03431a08c0c4b062ce7fd25e 100644 (file)
@@ -2237,6 +2237,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
        vol = memdup_user((void __user *)arg, sizeof(*vol));
        if (IS_ERR(vol))
                return PTR_ERR(vol);
+       vol->name[BTRFS_PATH_NAME_MAX] = '\0';
 
        switch (cmd) {
        case BTRFS_IOC_SCAN_DEV: