diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 401dfb2a94e8..ccc4f1121210 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -428,6 +428,7 @@ again: | |||
428 | start, end, NULL, | 428 | start, end, NULL, |
429 | EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_DIRTY | | 429 | EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_DIRTY | |
430 | EXTENT_CLEAR_DELALLOC | | 430 | EXTENT_CLEAR_DELALLOC | |
431 | EXTENT_CLEAR_ACCOUNTING | | ||
431 | EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK); | 432 | EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK); |
432 | ret = 0; | 433 | ret = 0; |
433 | goto free_pages_out; | 434 | goto free_pages_out; |
@@ -722,6 +723,7 @@ static noinline int cow_file_range(struct inode *inode, | |||
722 | EXTENT_CLEAR_UNLOCK_PAGE | | 723 | EXTENT_CLEAR_UNLOCK_PAGE | |
723 | EXTENT_CLEAR_UNLOCK | | 724 | EXTENT_CLEAR_UNLOCK | |
724 | EXTENT_CLEAR_DELALLOC | | 725 | EXTENT_CLEAR_DELALLOC | |
726 | EXTENT_CLEAR_ACCOUNTING | | ||
725 | EXTENT_CLEAR_DIRTY | | 727 | EXTENT_CLEAR_DIRTY | |
726 | EXTENT_SET_WRITEBACK | | 728 | EXTENT_SET_WRITEBACK | |
727 | EXTENT_END_WRITEBACK); | 729 | EXTENT_END_WRITEBACK); |
@@ -1195,15 +1197,17 @@ static int btrfs_split_extent_hook(struct inode *inode, | |||
1195 | root->fs_info->max_extent); | 1197 | root->fs_info->max_extent); |
1196 | 1198 | ||
1197 | /* | 1199 | /* |
1198 | * if we break a large extent up then leave delalloc_extents be, | 1200 | * if we break a large extent up then leave oustanding_extents |
1199 | * since we've already accounted for the large extent. | 1201 | * be, since we've already accounted for the large extent. |
1200 | */ | 1202 | */ |
1201 | if (div64_u64(new_size + root->fs_info->max_extent - 1, | 1203 | if (div64_u64(new_size + root->fs_info->max_extent - 1, |
1202 | root->fs_info->max_extent) < num_extents) | 1204 | root->fs_info->max_extent) < num_extents) |
1203 | return 0; | 1205 | return 0; |
1204 | } | 1206 | } |
1205 | 1207 | ||
1206 | BTRFS_I(inode)->delalloc_extents++; | 1208 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1209 | BTRFS_I(inode)->outstanding_extents++; | ||
1210 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1207 | 1211 | ||
1208 | return 0; | 1212 | return 0; |
1209 | } | 1213 | } |
@@ -1234,7 +1238,9 @@ static int btrfs_merge_extent_hook(struct inode *inode, | |||
1234 | 1238 | ||
1235 | /* we're not bigger than the max, unreserve the space and go */ | 1239 | /* we're not bigger than the max, unreserve the space and go */ |
1236 | if (new_size <= root->fs_info->max_extent) { | 1240 | if (new_size <= root->fs_info->max_extent) { |
1237 | BTRFS_I(inode)->delalloc_extents--; | 1241 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1242 | BTRFS_I(inode)->outstanding_extents--; | ||
1243 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1238 | return 0; | 1244 | return 0; |
1239 | } | 1245 | } |
1240 | 1246 | ||
@@ -1248,7 +1254,9 @@ static int btrfs_merge_extent_hook(struct inode *inode, | |||
1248 | root->fs_info->max_extent) > num_extents) | 1254 | root->fs_info->max_extent) > num_extents) |
1249 | return 0; | 1255 | return 0; |
1250 | 1256 | ||
1251 | BTRFS_I(inode)->delalloc_extents--; | 1257 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1258 | BTRFS_I(inode)->outstanding_extents--; | ||
1259 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1252 | 1260 | ||
1253 | return 0; | 1261 | return 0; |
1254 | } | 1262 | } |
@@ -1270,7 +1278,9 @@ static int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, | |||
1270 | if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { | 1278 | if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { |
1271 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1279 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1272 | 1280 | ||
1273 | BTRFS_I(inode)->delalloc_extents++; | 1281 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1282 | BTRFS_I(inode)->outstanding_extents++; | ||
1283 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1274 | btrfs_delalloc_reserve_space(root, inode, end - start + 1); | 1284 | btrfs_delalloc_reserve_space(root, inode, end - start + 1); |
1275 | spin_lock(&root->fs_info->delalloc_lock); | 1285 | spin_lock(&root->fs_info->delalloc_lock); |
1276 | BTRFS_I(inode)->delalloc_bytes += end - start + 1; | 1286 | BTRFS_I(inode)->delalloc_bytes += end - start + 1; |
@@ -1298,8 +1308,12 @@ static int btrfs_clear_bit_hook(struct inode *inode, | |||
1298 | if ((state->state & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { | 1308 | if ((state->state & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { |
1299 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1309 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1300 | 1310 | ||
1301 | BTRFS_I(inode)->delalloc_extents--; | 1311 | if (bits & EXTENT_DO_ACCOUNTING) { |
1302 | btrfs_unreserve_metadata_for_delalloc(root, inode, 1); | 1312 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1313 | BTRFS_I(inode)->outstanding_extents--; | ||
1314 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1315 | btrfs_unreserve_metadata_for_delalloc(root, inode, 1); | ||
1316 | } | ||
1303 | 1317 | ||
1304 | spin_lock(&root->fs_info->delalloc_lock); | 1318 | spin_lock(&root->fs_info->delalloc_lock); |
1305 | if (state->end - state->start + 1 > | 1319 | if (state->end - state->start + 1 > |
@@ -4825,7 +4839,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) | |||
4825 | */ | 4839 | */ |
4826 | clear_extent_bit(tree, page_start, page_end, | 4840 | clear_extent_bit(tree, page_start, page_end, |
4827 | EXTENT_DIRTY | EXTENT_DELALLOC | | 4841 | EXTENT_DIRTY | EXTENT_DELALLOC | |
4828 | EXTENT_LOCKED, 1, 0, NULL, GFP_NOFS); | 4842 | EXTENT_LOCKED | EXTENT_DO_ACCOUNTING, 1, 0, |
4843 | NULL, GFP_NOFS); | ||
4829 | /* | 4844 | /* |
4830 | * whoever cleared the private bit is responsible | 4845 | * whoever cleared the private bit is responsible |
4831 | * for the finish_ordered_io | 4846 | * for the finish_ordered_io |
@@ -4838,8 +4853,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) | |||
4838 | lock_extent(tree, page_start, page_end, GFP_NOFS); | 4853 | lock_extent(tree, page_start, page_end, GFP_NOFS); |
4839 | } | 4854 | } |
4840 | clear_extent_bit(tree, page_start, page_end, | 4855 | clear_extent_bit(tree, page_start, page_end, |
4841 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC, | 4856 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC | |
4842 | 1, 1, NULL, GFP_NOFS); | 4857 | EXTENT_DO_ACCOUNTING, 1, 1, NULL, GFP_NOFS); |
4843 | __btrfs_releasepage(page, GFP_NOFS); | 4858 | __btrfs_releasepage(page, GFP_NOFS); |
4844 | 4859 | ||
4845 | ClearPageChecked(page); | 4860 | ClearPageChecked(page); |
@@ -4934,7 +4949,8 @@ again: | |||
4934 | * prepare_pages in the normal write path. | 4949 | * prepare_pages in the normal write path. |
4935 | */ | 4950 | */ |
4936 | clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end, | 4951 | clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end, |
4937 | EXTENT_DIRTY | EXTENT_DELALLOC, GFP_NOFS); | 4952 | EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING, |
4953 | GFP_NOFS); | ||
4938 | 4954 | ||
4939 | ret = btrfs_set_extent_delalloc(inode, page_start, page_end); | 4955 | ret = btrfs_set_extent_delalloc(inode, page_start, page_end); |
4940 | if (ret) { | 4956 | if (ret) { |
@@ -5082,8 +5098,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
5082 | return NULL; | 5098 | return NULL; |
5083 | ei->last_trans = 0; | 5099 | ei->last_trans = 0; |
5084 | ei->logged_trans = 0; | 5100 | ei->logged_trans = 0; |
5085 | ei->delalloc_extents = 0; | 5101 | ei->outstanding_extents = 0; |
5086 | ei->delalloc_reserved_extents = 0; | 5102 | ei->reserved_extents = 0; |
5103 | spin_lock_init(&ei->accounting_lock); | ||
5087 | btrfs_ordered_inode_tree_init(&ei->ordered_tree); | 5104 | btrfs_ordered_inode_tree_init(&ei->ordered_tree); |
5088 | INIT_LIST_HEAD(&ei->i_orphan); | 5105 | INIT_LIST_HEAD(&ei->i_orphan); |
5089 | INIT_LIST_HEAD(&ei->ordered_operations); | 5106 | INIT_LIST_HEAD(&ei->ordered_operations); |