diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 1 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 4 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 2 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.c | 13 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 20 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 7 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 10 |
8 files changed, 43 insertions, 16 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 2e61fe1b6b8c..8f4b81de3ae2 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -718,7 +718,7 @@ struct btrfs_space_info { u64 total_bytes; /* total bytes in the space, this doesn't take mirrors into account */ u64 bytes_used; /* total bytes used, - this does't take mirrors into account */ + this doesn't take mirrors into account */ u64 bytes_pinned; /* total bytes pinned, will be freed when the transaction finishes */ u64 bytes_reserved; /* total bytes the allocator has reserved for diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 68c84c8c24bd..228cf36ece83 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2824,6 +2824,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, spin_lock(&delayed_refs->lock); if (delayed_refs->num_entries == 0) { + spin_unlock(&delayed_refs->lock); printk(KERN_INFO "delayed_refs has NO entry\n"); return ret; } diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 31f33ba56fe8..cd52f7f556ef 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -8059,6 +8059,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root, u64 group_start = group->key.objectid; new_extents = kmalloc(sizeof(*new_extents), GFP_NOFS); + if (!new_extents) { + ret = -ENOMEM; + goto out; + } nr_extents = 1; ret = get_new_locations(reloc_inode, extent_key, diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 315138605088..ba41da59e31b 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2681,7 +2681,7 @@ int extent_readpages(struct extent_io_tree *tree, prefetchw(&page->flags); list_del(&page->lru); if (!add_to_page_cache_lru(page, mapping, - page->index, GFP_KERNEL)) { + page->index, GFP_NOFS)) { __extent_read_full_page(tree, page, get_extent, &bio, 0, &bio_flags); } diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 11d2e9cea09e..63731a1fb0a1 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1768,10 +1768,13 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group) while ((node = rb_last(&block_group->free_space_offset)) != NULL) { info = rb_entry(node, struct btrfs_free_space, offset_index); - unlink_free_space(block_group, info); - if (info->bitmap) - kfree(info->bitmap); - kmem_cache_free(btrfs_free_space_cachep, info); + if (!info->bitmap) { + unlink_free_space(block_group, info); + kmem_cache_free(btrfs_free_space_cachep, info); + } else { + free_bitmap(block_group, info); + } + if (need_resched()) { spin_unlock(&block_group->tree_lock); cond_resched(); @@ -2301,7 +2304,7 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group, start = entry->offset; bytes = min(entry->bytes, end - start); unlink_free_space(block_group, entry); - kfree(entry); + kmem_cache_free(btrfs_free_space_cachep, entry); } spin_unlock(&block_group->tree_lock); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fcd66b6a8086..7cd8ab0ef04d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -954,6 +954,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, 1, 0, NULL, GFP_NOFS); while (start < end) { async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); + BUG_ON(!async_cow); async_cow->inode = inode; async_cow->root = root; async_cow->locked_page = locked_page; @@ -4731,9 +4732,10 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, dentry->d_name.len, dir->i_ino, objectid, BTRFS_I(dir)->block_group, mode, &index); - err = PTR_ERR(inode); - if (IS_ERR(inode)) + if (IS_ERR(inode)) { + err = PTR_ERR(inode); goto out_unlock; + } err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); if (err) { @@ -4792,9 +4794,10 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, dentry->d_name.len, dir->i_ino, objectid, BTRFS_I(dir)->block_group, mode, &index); - err = PTR_ERR(inode); - if (IS_ERR(inode)) + if (IS_ERR(inode)) { + err = PTR_ERR(inode); goto out_unlock; + } err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); if (err) { @@ -4999,6 +5002,8 @@ static noinline int uncompress_inline(struct btrfs_path *path, inline_size = btrfs_file_extent_inline_item_len(leaf, btrfs_item_nr(leaf, path->slots[0])); tmp = kmalloc(inline_size, GFP_NOFS); + if (!tmp) + return -ENOMEM; ptr = btrfs_file_extent_inline_start(item); read_extent_buffer(leaf, tmp, ptr, inline_size); @@ -6036,7 +6041,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, ret = btrfs_map_block(map_tree, READ, start_sector << 9, &map_length, NULL, 0); if (ret) { - bio_put(bio); + bio_put(orig_bio); return -EIO; } @@ -7273,9 +7278,10 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, dentry->d_name.len, dir->i_ino, objectid, BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, &index); - err = PTR_ERR(inode); - if (IS_ERR(inode)) + if (IS_ERR(inode)) { + err = PTR_ERR(inode); goto out_unlock; + } err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); if (err) { diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c50271ad3157..f997ec0c1ba4 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -2209,8 +2209,10 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, log = root->log_root; path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + if (!path) { + err = -ENOMEM; + goto out_unlock; + } di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino, name, name_len, -1); @@ -2271,6 +2273,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans, } fail: btrfs_free_path(path); +out_unlock: mutex_unlock(&BTRFS_I(dir)->log_mutex); if (ret == -ENOSPC) { root->fs_info->last_trans_log_full_commit = trans->transid; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 309a57b9fc85..c7367ae5a3e6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -155,6 +155,15 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) unsigned long limit; unsigned long last_waited = 0; int force_reg = 0; + struct blk_plug plug; + + /* + * this function runs all the bios we've collected for + * a particular device. We don't want to wander off to + * another device without first sending all of these down. + * So, setup a plug here and finish it off before we return + */ + blk_start_plug(&plug); bdi = blk_get_backing_dev_info(device->bdev); fs_info = device->dev_root->fs_info; @@ -294,6 +303,7 @@ loop_lock: spin_unlock(&device->io_lock); done: + blk_finish_plug(&plug); return 0; } |