diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/backref.c | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 1 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 3 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 2 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 8 |
5 files changed, 14 insertions, 1 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index 0cc02577577b..ae5cb94ef191 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -1465,6 +1465,7 @@ static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans, if (ret < 0 && ret != -ENOENT) { ulist_free(tmp); ulist_free(*roots); + *roots = NULL; return ret; } node = ulist_next(tmp, &uiter); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index f71e4dbe1d8a..f00e64fee5dd 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1998,6 +1998,7 @@ void btrfs_put_root(struct btrfs_root *root) if (refcount_dec_and_test(&root->refs)) { WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree)); + WARN_ON(test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state)); if (root->anon_dev) free_anon_bdev(root->anon_dev); btrfs_drew_lock_destroy(&root->snapshot_lock); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 6e17a92869ad..79196eb1a1b3 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1999,7 +1999,8 @@ static int __process_pages_contig(struct address_space *mapping, if (!PageDirty(pages[i]) || pages[i]->mapping != mapping) { unlock_page(pages[i]); - put_page(pages[i]); + for (; i < ret; i++) + put_page(pages[i]); err = -EAGAIN; goto out; } diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 157452a5e110..f67d736c27a1 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2642,6 +2642,8 @@ again: root->reloc_root = NULL; btrfs_put_root(reloc_root); } + clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, + &root->state); btrfs_put_root(root); } diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 21c7d3d87827..45cf455f906d 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -7056,6 +7056,14 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) mutex_lock(&fs_info->chunk_mutex); /* + * It is possible for mount and umount to race in such a way that + * we execute this code path, but open_fs_devices failed to clear + * total_rw_bytes. We certainly want it cleared before reading the + * device items, so clear it here. + */ + fs_info->fs_devices->total_rw_bytes = 0; + + /* * Read all device items, and then all the chunk items. All * device items are found before any chunk item (their object id * is smaller than the lowest possible object id for a chunk |