diff --git a/[refs] b/[refs] index 31ad66bf7422..5ccf1b52f63b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 2115133f8b9a8dbdb217d14080814df07ce90479 +refs/heads/master: a90e8b6fb80db43b029e1e76205452afa8bdc77a diff --git a/trunk/fs/btrfs/delayed-inode.c b/trunk/fs/btrfs/delayed-inode.c index 6a1a6800776c..313ee14cf3b7 100644 --- a/trunk/fs/btrfs/delayed-inode.c +++ b/trunk/fs/btrfs/delayed-inode.c @@ -692,6 +692,11 @@ static int btrfs_delayed_inode_reserve_metadata( migrate: ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); + if (unlikely(ret)) { + /* This shouldn't happen */ + BUG_ON(release); + return ret; + } out: /* @@ -707,11 +712,9 @@ static int btrfs_delayed_inode_reserve_metadata( * reservation here. I think it may be time for a documentation page on * how block rsvs. work. */ - if (!ret) - node->bytes_reserved = num_bytes; - if (release) btrfs_block_rsv_release(root, src_rsv, num_bytes); + node->bytes_reserved = num_bytes; return ret; } diff --git a/trunk/fs/btrfs/inode.c b/trunk/fs/btrfs/inode.c index 7d394335bcb5..2b920596c126 100644 --- a/trunk/fs/btrfs/inode.c +++ b/trunk/fs/btrfs/inode.c @@ -93,8 +93,6 @@ static noinline int cow_file_range(struct inode *inode, struct page *locked_page, u64 start, u64 end, int *page_started, unsigned long *nr_written, int unlock); -static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode); static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir, @@ -1743,7 +1741,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) trans = btrfs_join_transaction(root); BUG_ON(IS_ERR(trans)); trans->block_rsv = &root->fs_info->delalloc_block_rsv; - ret = btrfs_update_inode_fallback(trans, root, inode); + ret = btrfs_update_inode(trans, root, inode); BUG_ON(ret); } goto out; @@ -1793,7 +1791,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { - ret = btrfs_update_inode_fallback(trans, root, inode); + ret = btrfs_update_inode(trans, root, inode); BUG_ON(ret); } ret = 0; @@ -2428,7 +2426,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, /* * copy everything in the in-memory inode into the btree. */ -static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans, +noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode) { struct btrfs_inode_item *inode_item; @@ -2436,6 +2434,21 @@ static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans, struct extent_buffer *leaf; int ret; + /* + * If the inode is a free space inode, we can deadlock during commit + * if we put it into the delayed code. + * + * The data relocation inode should also be directly updated + * without delay + */ + if (!btrfs_is_free_space_inode(root, inode) + && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { + ret = btrfs_delayed_update_inode(trans, root, inode); + if (!ret) + btrfs_set_inode_last_trans(trans, inode); + return ret; + } + path = btrfs_alloc_path(); if (!path) return -ENOMEM; @@ -2463,43 +2476,6 @@ static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans, return ret; } -/* - * copy everything in the in-memory inode into the btree. - */ -noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode) -{ - int ret; - - /* - * If the inode is a free space inode, we can deadlock during commit - * if we put it into the delayed code. - * - * The data relocation inode should also be directly updated - * without delay - */ - if (!btrfs_is_free_space_inode(root, inode) - && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { - ret = btrfs_delayed_update_inode(trans, root, inode); - if (!ret) - btrfs_set_inode_last_trans(trans, inode); - return ret; - } - - return btrfs_update_inode_item(trans, root, inode); -} - -static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode) -{ - int ret; - - ret = btrfs_update_inode(trans, root, inode); - if (ret == -ENOSPC) - return btrfs_update_inode_item(trans, root, inode); - return ret; -} - /* * unlink helper that gets used here in inode.c and in the tree logging * recovery code. It remove a link in a directory with a given name, and @@ -5656,7 +5632,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { ret = btrfs_ordered_update_i_size(inode, 0, ordered); if (!ret) - err = btrfs_update_inode_fallback(trans, root, inode); + err = btrfs_update_inode(trans, root, inode); goto out; } @@ -5694,7 +5670,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); ret = btrfs_ordered_update_i_size(inode, 0, ordered); if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) - btrfs_update_inode_fallback(trans, root, inode); + btrfs_update_inode(trans, root, inode); ret = 0; out_unlock: unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, diff --git a/trunk/fs/btrfs/super.c b/trunk/fs/btrfs/super.c index dcd5aef6b614..6befcaf253bd 100644 --- a/trunk/fs/btrfs/super.c +++ b/trunk/fs/btrfs/super.c @@ -448,6 +448,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, token = match_token(p, tokens, args); switch (token) { case Opt_subvol: + kfree(*subvol_name); *subvol_name = match_strdup(&args[0]); break; case Opt_subvolid: