diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 183 |
1 files changed, 132 insertions, 51 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a0d1dd492a58..90c23eb28829 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -70,7 +70,6 @@ static struct extent_io_ops btrfs_extent_io_ops; | |||
70 | static struct kmem_cache *btrfs_inode_cachep; | 70 | static struct kmem_cache *btrfs_inode_cachep; |
71 | struct kmem_cache *btrfs_trans_handle_cachep; | 71 | struct kmem_cache *btrfs_trans_handle_cachep; |
72 | struct kmem_cache *btrfs_transaction_cachep; | 72 | struct kmem_cache *btrfs_transaction_cachep; |
73 | struct kmem_cache *btrfs_bit_radix_cachep; | ||
74 | struct kmem_cache *btrfs_path_cachep; | 73 | struct kmem_cache *btrfs_path_cachep; |
75 | 74 | ||
76 | #define S_SHIFT 12 | 75 | #define S_SHIFT 12 |
@@ -234,7 +233,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | |||
234 | } | 233 | } |
235 | 234 | ||
236 | ret = btrfs_drop_extents(trans, root, inode, start, | 235 | ret = btrfs_drop_extents(trans, root, inode, start, |
237 | aligned_end, start, &hint_byte); | 236 | aligned_end, aligned_end, start, &hint_byte); |
238 | BUG_ON(ret); | 237 | BUG_ON(ret); |
239 | 238 | ||
240 | if (isize > actual_end) | 239 | if (isize > actual_end) |
@@ -1439,6 +1438,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
1439 | struct inode *inode, u64 file_pos, | 1438 | struct inode *inode, u64 file_pos, |
1440 | u64 disk_bytenr, u64 disk_num_bytes, | 1439 | u64 disk_bytenr, u64 disk_num_bytes, |
1441 | u64 num_bytes, u64 ram_bytes, | 1440 | u64 num_bytes, u64 ram_bytes, |
1441 | u64 locked_end, | ||
1442 | u8 compression, u8 encryption, | 1442 | u8 compression, u8 encryption, |
1443 | u16 other_encoding, int extent_type) | 1443 | u16 other_encoding, int extent_type) |
1444 | { | 1444 | { |
@@ -1455,7 +1455,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
1455 | 1455 | ||
1456 | path->leave_spinning = 1; | 1456 | path->leave_spinning = 1; |
1457 | ret = btrfs_drop_extents(trans, root, inode, file_pos, | 1457 | ret = btrfs_drop_extents(trans, root, inode, file_pos, |
1458 | file_pos + num_bytes, file_pos, &hint); | 1458 | file_pos + num_bytes, locked_end, |
1459 | file_pos, &hint); | ||
1459 | BUG_ON(ret); | 1460 | BUG_ON(ret); |
1460 | 1461 | ||
1461 | ins.objectid = inode->i_ino; | 1462 | ins.objectid = inode->i_ino; |
@@ -1590,6 +1591,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1590 | ordered_extent->disk_len, | 1591 | ordered_extent->disk_len, |
1591 | ordered_extent->len, | 1592 | ordered_extent->len, |
1592 | ordered_extent->len, | 1593 | ordered_extent->len, |
1594 | ordered_extent->file_offset + | ||
1595 | ordered_extent->len, | ||
1593 | compressed, 0, 0, | 1596 | compressed, 0, 0, |
1594 | BTRFS_FILE_EXTENT_REG); | 1597 | BTRFS_FILE_EXTENT_REG); |
1595 | BUG_ON(ret); | 1598 | BUG_ON(ret); |
@@ -1819,10 +1822,12 @@ good: | |||
1819 | return 0; | 1822 | return 0; |
1820 | 1823 | ||
1821 | zeroit: | 1824 | zeroit: |
1822 | printk(KERN_INFO "btrfs csum failed ino %lu off %llu csum %u " | 1825 | if (printk_ratelimit()) { |
1823 | "private %llu\n", page->mapping->host->i_ino, | 1826 | printk(KERN_INFO "btrfs csum failed ino %lu off %llu csum %u " |
1824 | (unsigned long long)start, csum, | 1827 | "private %llu\n", page->mapping->host->i_ino, |
1825 | (unsigned long long)private); | 1828 | (unsigned long long)start, csum, |
1829 | (unsigned long long)private); | ||
1830 | } | ||
1826 | memset(kaddr + offset, 1, end - start + 1); | 1831 | memset(kaddr + offset, 1, end - start + 1); |
1827 | flush_dcache_page(page); | 1832 | flush_dcache_page(page); |
1828 | kunmap_atomic(kaddr, KM_USER0); | 1833 | kunmap_atomic(kaddr, KM_USER0); |
@@ -2011,6 +2016,57 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2011 | } | 2016 | } |
2012 | 2017 | ||
2013 | /* | 2018 | /* |
2019 | * very simple check to peek ahead in the leaf looking for xattrs. If we | ||
2020 | * don't find any xattrs, we know there can't be any acls. | ||
2021 | * | ||
2022 | * slot is the slot the inode is in, objectid is the objectid of the inode | ||
2023 | */ | ||
2024 | static noinline int acls_after_inode_item(struct extent_buffer *leaf, | ||
2025 | int slot, u64 objectid) | ||
2026 | { | ||
2027 | u32 nritems = btrfs_header_nritems(leaf); | ||
2028 | struct btrfs_key found_key; | ||
2029 | int scanned = 0; | ||
2030 | |||
2031 | slot++; | ||
2032 | while (slot < nritems) { | ||
2033 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
2034 | |||
2035 | /* we found a different objectid, there must not be acls */ | ||
2036 | if (found_key.objectid != objectid) | ||
2037 | return 0; | ||
2038 | |||
2039 | /* we found an xattr, assume we've got an acl */ | ||
2040 | if (found_key.type == BTRFS_XATTR_ITEM_KEY) | ||
2041 | return 1; | ||
2042 | |||
2043 | /* | ||
2044 | * we found a key greater than an xattr key, there can't | ||
2045 | * be any acls later on | ||
2046 | */ | ||
2047 | if (found_key.type > BTRFS_XATTR_ITEM_KEY) | ||
2048 | return 0; | ||
2049 | |||
2050 | slot++; | ||
2051 | scanned++; | ||
2052 | |||
2053 | /* | ||
2054 | * it goes inode, inode backrefs, xattrs, extents, | ||
2055 | * so if there are a ton of hard links to an inode there can | ||
2056 | * be a lot of backrefs. Don't waste time searching too hard, | ||
2057 | * this is just an optimization | ||
2058 | */ | ||
2059 | if (scanned >= 8) | ||
2060 | break; | ||
2061 | } | ||
2062 | /* we hit the end of the leaf before we found an xattr or | ||
2063 | * something larger than an xattr. We have to assume the inode | ||
2064 | * has acls | ||
2065 | */ | ||
2066 | return 1; | ||
2067 | } | ||
2068 | |||
2069 | /* | ||
2014 | * read an inode from the btree into the in-memory inode | 2070 | * read an inode from the btree into the in-memory inode |
2015 | */ | 2071 | */ |
2016 | void btrfs_read_locked_inode(struct inode *inode) | 2072 | void btrfs_read_locked_inode(struct inode *inode) |
@@ -2021,6 +2077,7 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
2021 | struct btrfs_timespec *tspec; | 2077 | struct btrfs_timespec *tspec; |
2022 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2078 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2023 | struct btrfs_key location; | 2079 | struct btrfs_key location; |
2080 | int maybe_acls; | ||
2024 | u64 alloc_group_block; | 2081 | u64 alloc_group_block; |
2025 | u32 rdev; | 2082 | u32 rdev; |
2026 | int ret; | 2083 | int ret; |
@@ -2067,6 +2124,16 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
2067 | 2124 | ||
2068 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); | 2125 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); |
2069 | 2126 | ||
2127 | /* | ||
2128 | * try to precache a NULL acl entry for files that don't have | ||
2129 | * any xattrs or acls | ||
2130 | */ | ||
2131 | maybe_acls = acls_after_inode_item(leaf, path->slots[0], inode->i_ino); | ||
2132 | if (!maybe_acls) { | ||
2133 | BTRFS_I(inode)->i_acl = NULL; | ||
2134 | BTRFS_I(inode)->i_default_acl = NULL; | ||
2135 | } | ||
2136 | |||
2070 | BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, | 2137 | BTRFS_I(inode)->block_group = btrfs_find_block_group(root, 0, |
2071 | alloc_group_block, 0); | 2138 | alloc_group_block, 0); |
2072 | btrfs_free_path(path); | 2139 | btrfs_free_path(path); |
@@ -2877,6 +2944,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) | |||
2877 | err = btrfs_drop_extents(trans, root, inode, | 2944 | err = btrfs_drop_extents(trans, root, inode, |
2878 | cur_offset, | 2945 | cur_offset, |
2879 | cur_offset + hole_size, | 2946 | cur_offset + hole_size, |
2947 | block_end, | ||
2880 | cur_offset, &hint_byte); | 2948 | cur_offset, &hint_byte); |
2881 | if (err) | 2949 | if (err) |
2882 | break; | 2950 | break; |
@@ -3041,8 +3109,8 @@ static noinline void init_btrfs_i(struct inode *inode) | |||
3041 | { | 3109 | { |
3042 | struct btrfs_inode *bi = BTRFS_I(inode); | 3110 | struct btrfs_inode *bi = BTRFS_I(inode); |
3043 | 3111 | ||
3044 | bi->i_acl = NULL; | 3112 | bi->i_acl = BTRFS_ACL_NOT_CACHED; |
3045 | bi->i_default_acl = NULL; | 3113 | bi->i_default_acl = BTRFS_ACL_NOT_CACHED; |
3046 | 3114 | ||
3047 | bi->generation = 0; | 3115 | bi->generation = 0; |
3048 | bi->sequence = 0; | 3116 | bi->sequence = 0; |
@@ -4634,47 +4702,36 @@ void btrfs_destroy_cachep(void) | |||
4634 | kmem_cache_destroy(btrfs_trans_handle_cachep); | 4702 | kmem_cache_destroy(btrfs_trans_handle_cachep); |
4635 | if (btrfs_transaction_cachep) | 4703 | if (btrfs_transaction_cachep) |
4636 | kmem_cache_destroy(btrfs_transaction_cachep); | 4704 | kmem_cache_destroy(btrfs_transaction_cachep); |
4637 | if (btrfs_bit_radix_cachep) | ||
4638 | kmem_cache_destroy(btrfs_bit_radix_cachep); | ||
4639 | if (btrfs_path_cachep) | 4705 | if (btrfs_path_cachep) |
4640 | kmem_cache_destroy(btrfs_path_cachep); | 4706 | kmem_cache_destroy(btrfs_path_cachep); |
4641 | } | 4707 | } |
4642 | 4708 | ||
4643 | struct kmem_cache *btrfs_cache_create(const char *name, size_t size, | ||
4644 | unsigned long extra_flags, | ||
4645 | void (*ctor)(void *)) | ||
4646 | { | ||
4647 | return kmem_cache_create(name, size, 0, (SLAB_RECLAIM_ACCOUNT | | ||
4648 | SLAB_MEM_SPREAD | extra_flags), ctor); | ||
4649 | } | ||
4650 | |||
4651 | int btrfs_init_cachep(void) | 4709 | int btrfs_init_cachep(void) |
4652 | { | 4710 | { |
4653 | btrfs_inode_cachep = btrfs_cache_create("btrfs_inode_cache", | 4711 | btrfs_inode_cachep = kmem_cache_create("btrfs_inode_cache", |
4654 | sizeof(struct btrfs_inode), | 4712 | sizeof(struct btrfs_inode), 0, |
4655 | 0, init_once); | 4713 | SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, init_once); |
4656 | if (!btrfs_inode_cachep) | 4714 | if (!btrfs_inode_cachep) |
4657 | goto fail; | 4715 | goto fail; |
4658 | btrfs_trans_handle_cachep = | 4716 | |
4659 | btrfs_cache_create("btrfs_trans_handle_cache", | 4717 | btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle_cache", |
4660 | sizeof(struct btrfs_trans_handle), | 4718 | sizeof(struct btrfs_trans_handle), 0, |
4661 | 0, NULL); | 4719 | SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL); |
4662 | if (!btrfs_trans_handle_cachep) | 4720 | if (!btrfs_trans_handle_cachep) |
4663 | goto fail; | 4721 | goto fail; |
4664 | btrfs_transaction_cachep = btrfs_cache_create("btrfs_transaction_cache", | 4722 | |
4665 | sizeof(struct btrfs_transaction), | 4723 | btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction_cache", |
4666 | 0, NULL); | 4724 | sizeof(struct btrfs_transaction), 0, |
4725 | SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL); | ||
4667 | if (!btrfs_transaction_cachep) | 4726 | if (!btrfs_transaction_cachep) |
4668 | goto fail; | 4727 | goto fail; |
4669 | btrfs_path_cachep = btrfs_cache_create("btrfs_path_cache", | 4728 | |
4670 | sizeof(struct btrfs_path), | 4729 | btrfs_path_cachep = kmem_cache_create("btrfs_path_cache", |
4671 | 0, NULL); | 4730 | sizeof(struct btrfs_path), 0, |
4731 | SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL); | ||
4672 | if (!btrfs_path_cachep) | 4732 | if (!btrfs_path_cachep) |
4673 | goto fail; | 4733 | goto fail; |
4674 | btrfs_bit_radix_cachep = btrfs_cache_create("btrfs_radix", 256, | 4734 | |
4675 | SLAB_DESTROY_BY_RCU, NULL); | ||
4676 | if (!btrfs_bit_radix_cachep) | ||
4677 | goto fail; | ||
4678 | return 0; | 4735 | return 0; |
4679 | fail: | 4736 | fail: |
4680 | btrfs_destroy_cachep(); | 4737 | btrfs_destroy_cachep(); |
@@ -4970,10 +5027,10 @@ out_fail: | |||
4970 | return err; | 5027 | return err; |
4971 | } | 5028 | } |
4972 | 5029 | ||
4973 | static int prealloc_file_range(struct inode *inode, u64 start, u64 end, | 5030 | static int prealloc_file_range(struct btrfs_trans_handle *trans, |
4974 | u64 alloc_hint, int mode) | 5031 | struct inode *inode, u64 start, u64 end, |
5032 | u64 locked_end, u64 alloc_hint, int mode) | ||
4975 | { | 5033 | { |
4976 | struct btrfs_trans_handle *trans; | ||
4977 | struct btrfs_root *root = BTRFS_I(inode)->root; | 5034 | struct btrfs_root *root = BTRFS_I(inode)->root; |
4978 | struct btrfs_key ins; | 5035 | struct btrfs_key ins; |
4979 | u64 alloc_size; | 5036 | u64 alloc_size; |
@@ -4981,10 +5038,6 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end, | |||
4981 | u64 num_bytes = end - start; | 5038 | u64 num_bytes = end - start; |
4982 | int ret = 0; | 5039 | int ret = 0; |
4983 | 5040 | ||
4984 | trans = btrfs_join_transaction(root, 1); | ||
4985 | BUG_ON(!trans); | ||
4986 | btrfs_set_trans_block_group(trans, inode); | ||
4987 | |||
4988 | while (num_bytes > 0) { | 5041 | while (num_bytes > 0) { |
4989 | alloc_size = min(num_bytes, root->fs_info->max_extent); | 5042 | alloc_size = min(num_bytes, root->fs_info->max_extent); |
4990 | ret = btrfs_reserve_extent(trans, root, alloc_size, | 5043 | ret = btrfs_reserve_extent(trans, root, alloc_size, |
@@ -4997,7 +5050,8 @@ static int prealloc_file_range(struct inode *inode, u64 start, u64 end, | |||
4997 | ret = insert_reserved_file_extent(trans, inode, | 5050 | ret = insert_reserved_file_extent(trans, inode, |
4998 | cur_offset, ins.objectid, | 5051 | cur_offset, ins.objectid, |
4999 | ins.offset, ins.offset, | 5052 | ins.offset, ins.offset, |
5000 | ins.offset, 0, 0, 0, | 5053 | ins.offset, locked_end, |
5054 | 0, 0, 0, | ||
5001 | BTRFS_FILE_EXTENT_PREALLOC); | 5055 | BTRFS_FILE_EXTENT_PREALLOC); |
5002 | BUG_ON(ret); | 5056 | BUG_ON(ret); |
5003 | num_bytes -= ins.offset; | 5057 | num_bytes -= ins.offset; |
@@ -5015,7 +5069,6 @@ out: | |||
5015 | BUG_ON(ret); | 5069 | BUG_ON(ret); |
5016 | } | 5070 | } |
5017 | 5071 | ||
5018 | btrfs_end_transaction(trans, root); | ||
5019 | return ret; | 5072 | return ret; |
5020 | } | 5073 | } |
5021 | 5074 | ||
@@ -5027,13 +5080,21 @@ static long btrfs_fallocate(struct inode *inode, int mode, | |||
5027 | u64 alloc_start; | 5080 | u64 alloc_start; |
5028 | u64 alloc_end; | 5081 | u64 alloc_end; |
5029 | u64 alloc_hint = 0; | 5082 | u64 alloc_hint = 0; |
5083 | u64 locked_end; | ||
5030 | u64 mask = BTRFS_I(inode)->root->sectorsize - 1; | 5084 | u64 mask = BTRFS_I(inode)->root->sectorsize - 1; |
5031 | struct extent_map *em; | 5085 | struct extent_map *em; |
5086 | struct btrfs_trans_handle *trans; | ||
5032 | int ret; | 5087 | int ret; |
5033 | 5088 | ||
5034 | alloc_start = offset & ~mask; | 5089 | alloc_start = offset & ~mask; |
5035 | alloc_end = (offset + len + mask) & ~mask; | 5090 | alloc_end = (offset + len + mask) & ~mask; |
5036 | 5091 | ||
5092 | /* | ||
5093 | * wait for ordered IO before we have any locks. We'll loop again | ||
5094 | * below with the locks held. | ||
5095 | */ | ||
5096 | btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start); | ||
5097 | |||
5037 | mutex_lock(&inode->i_mutex); | 5098 | mutex_lock(&inode->i_mutex); |
5038 | if (alloc_start > inode->i_size) { | 5099 | if (alloc_start > inode->i_size) { |
5039 | ret = btrfs_cont_expand(inode, alloc_start); | 5100 | ret = btrfs_cont_expand(inode, alloc_start); |
@@ -5041,10 +5102,21 @@ static long btrfs_fallocate(struct inode *inode, int mode, | |||
5041 | goto out; | 5102 | goto out; |
5042 | } | 5103 | } |
5043 | 5104 | ||
5105 | locked_end = alloc_end - 1; | ||
5044 | while (1) { | 5106 | while (1) { |
5045 | struct btrfs_ordered_extent *ordered; | 5107 | struct btrfs_ordered_extent *ordered; |
5046 | lock_extent(&BTRFS_I(inode)->io_tree, alloc_start, | 5108 | |
5047 | alloc_end - 1, GFP_NOFS); | 5109 | trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1); |
5110 | if (!trans) { | ||
5111 | ret = -EIO; | ||
5112 | goto out; | ||
5113 | } | ||
5114 | |||
5115 | /* the extent lock is ordered inside the running | ||
5116 | * transaction | ||
5117 | */ | ||
5118 | lock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end, | ||
5119 | GFP_NOFS); | ||
5048 | ordered = btrfs_lookup_first_ordered_extent(inode, | 5120 | ordered = btrfs_lookup_first_ordered_extent(inode, |
5049 | alloc_end - 1); | 5121 | alloc_end - 1); |
5050 | if (ordered && | 5122 | if (ordered && |
@@ -5052,7 +5124,13 @@ static long btrfs_fallocate(struct inode *inode, int mode, | |||
5052 | ordered->file_offset < alloc_end) { | 5124 | ordered->file_offset < alloc_end) { |
5053 | btrfs_put_ordered_extent(ordered); | 5125 | btrfs_put_ordered_extent(ordered); |
5054 | unlock_extent(&BTRFS_I(inode)->io_tree, | 5126 | unlock_extent(&BTRFS_I(inode)->io_tree, |
5055 | alloc_start, alloc_end - 1, GFP_NOFS); | 5127 | alloc_start, locked_end, GFP_NOFS); |
5128 | btrfs_end_transaction(trans, BTRFS_I(inode)->root); | ||
5129 | |||
5130 | /* | ||
5131 | * we can't wait on the range with the transaction | ||
5132 | * running or with the extent lock held | ||
5133 | */ | ||
5056 | btrfs_wait_ordered_range(inode, alloc_start, | 5134 | btrfs_wait_ordered_range(inode, alloc_start, |
5057 | alloc_end - alloc_start); | 5135 | alloc_end - alloc_start); |
5058 | } else { | 5136 | } else { |
@@ -5070,8 +5148,9 @@ static long btrfs_fallocate(struct inode *inode, int mode, | |||
5070 | last_byte = min(extent_map_end(em), alloc_end); | 5148 | last_byte = min(extent_map_end(em), alloc_end); |
5071 | last_byte = (last_byte + mask) & ~mask; | 5149 | last_byte = (last_byte + mask) & ~mask; |
5072 | if (em->block_start == EXTENT_MAP_HOLE) { | 5150 | if (em->block_start == EXTENT_MAP_HOLE) { |
5073 | ret = prealloc_file_range(inode, cur_offset, | 5151 | ret = prealloc_file_range(trans, inode, cur_offset, |
5074 | last_byte, alloc_hint, mode); | 5152 | last_byte, locked_end + 1, |
5153 | alloc_hint, mode); | ||
5075 | if (ret < 0) { | 5154 | if (ret < 0) { |
5076 | free_extent_map(em); | 5155 | free_extent_map(em); |
5077 | break; | 5156 | break; |
@@ -5087,8 +5166,10 @@ static long btrfs_fallocate(struct inode *inode, int mode, | |||
5087 | break; | 5166 | break; |
5088 | } | 5167 | } |
5089 | } | 5168 | } |
5090 | unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, alloc_end - 1, | 5169 | unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end, |
5091 | GFP_NOFS); | 5170 | GFP_NOFS); |
5171 | |||
5172 | btrfs_end_transaction(trans, BTRFS_I(inode)->root); | ||
5092 | out: | 5173 | out: |
5093 | mutex_unlock(&inode->i_mutex); | 5174 | mutex_unlock(&inode->i_mutex); |
5094 | return ret; | 5175 | return ret; |