diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-11 14:23:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-11 14:23:13 -0400 |
commit | 474a503d4bf77ae0cbe484dd0842a2648c0b1c28 (patch) | |
tree | 70e3e4023209e741546491a58622bd45fb13e308 /fs/btrfs/inode.c | |
parent | d43c36dc6b357fa1806800f18aa30123c747a6d1 (diff) | |
parent | ac6889cbb254be1ffea376bea4a96ce9be0e0ed0 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
Btrfs: fix file clone ioctl for bookend extents
Btrfs: fix uninit compiler warning in cow_file_range_nocow
Btrfs: constify dentry_operations
Btrfs: optimize back reference update during btrfs_drop_snapshot
Btrfs: remove negative dentry when deleting subvolumne
Btrfs: optimize fsync for the single writer case
Btrfs: async delalloc flushing under space pressure
Btrfs: release delalloc reservations on extent item insertion
Btrfs: delay clearing EXTENT_DELALLOC for compressed extents
Btrfs: cleanup extent_clear_unlock_delalloc flags
Btrfs: fix possible softlockup in the allocator
Btrfs: fix deadlock on async thread startup
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 111 |
1 files changed, 74 insertions, 37 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 112e5aa85892..9e138b793dc7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -424,9 +424,12 @@ again: | |||
424 | * and free up our temp pages. | 424 | * and free up our temp pages. |
425 | */ | 425 | */ |
426 | extent_clear_unlock_delalloc(inode, | 426 | extent_clear_unlock_delalloc(inode, |
427 | &BTRFS_I(inode)->io_tree, | 427 | &BTRFS_I(inode)->io_tree, |
428 | start, end, NULL, 1, 0, | 428 | start, end, NULL, |
429 | 0, 1, 1, 1, 0); | 429 | EXTENT_CLEAR_UNLOCK_PAGE | EXTENT_CLEAR_DIRTY | |
430 | EXTENT_CLEAR_DELALLOC | | ||
431 | EXTENT_CLEAR_ACCOUNTING | | ||
432 | EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK); | ||
430 | ret = 0; | 433 | ret = 0; |
431 | goto free_pages_out; | 434 | goto free_pages_out; |
432 | } | 435 | } |
@@ -637,11 +640,14 @@ static noinline int submit_compressed_extents(struct inode *inode, | |||
637 | * clear dirty, set writeback and unlock the pages. | 640 | * clear dirty, set writeback and unlock the pages. |
638 | */ | 641 | */ |
639 | extent_clear_unlock_delalloc(inode, | 642 | extent_clear_unlock_delalloc(inode, |
640 | &BTRFS_I(inode)->io_tree, | 643 | &BTRFS_I(inode)->io_tree, |
641 | async_extent->start, | 644 | async_extent->start, |
642 | async_extent->start + | 645 | async_extent->start + |
643 | async_extent->ram_size - 1, | 646 | async_extent->ram_size - 1, |
644 | NULL, 1, 1, 0, 1, 1, 0, 0); | 647 | NULL, EXTENT_CLEAR_UNLOCK_PAGE | |
648 | EXTENT_CLEAR_UNLOCK | | ||
649 | EXTENT_CLEAR_DELALLOC | | ||
650 | EXTENT_CLEAR_DIRTY | EXTENT_SET_WRITEBACK); | ||
645 | 651 | ||
646 | ret = btrfs_submit_compressed_write(inode, | 652 | ret = btrfs_submit_compressed_write(inode, |
647 | async_extent->start, | 653 | async_extent->start, |
@@ -712,9 +718,15 @@ static noinline int cow_file_range(struct inode *inode, | |||
712 | start, end, 0, NULL); | 718 | start, end, 0, NULL); |
713 | if (ret == 0) { | 719 | if (ret == 0) { |
714 | extent_clear_unlock_delalloc(inode, | 720 | extent_clear_unlock_delalloc(inode, |
715 | &BTRFS_I(inode)->io_tree, | 721 | &BTRFS_I(inode)->io_tree, |
716 | start, end, NULL, 1, 1, | 722 | start, end, NULL, |
717 | 1, 1, 1, 1, 0); | 723 | EXTENT_CLEAR_UNLOCK_PAGE | |
724 | EXTENT_CLEAR_UNLOCK | | ||
725 | EXTENT_CLEAR_DELALLOC | | ||
726 | EXTENT_CLEAR_ACCOUNTING | | ||
727 | EXTENT_CLEAR_DIRTY | | ||
728 | EXTENT_SET_WRITEBACK | | ||
729 | EXTENT_END_WRITEBACK); | ||
718 | *nr_written = *nr_written + | 730 | *nr_written = *nr_written + |
719 | (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE; | 731 | (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE; |
720 | *page_started = 1; | 732 | *page_started = 1; |
@@ -738,6 +750,8 @@ static noinline int cow_file_range(struct inode *inode, | |||
738 | btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0); | 750 | btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0); |
739 | 751 | ||
740 | while (disk_num_bytes > 0) { | 752 | while (disk_num_bytes > 0) { |
753 | unsigned long op; | ||
754 | |||
741 | cur_alloc_size = min(disk_num_bytes, root->fs_info->max_extent); | 755 | cur_alloc_size = min(disk_num_bytes, root->fs_info->max_extent); |
742 | ret = btrfs_reserve_extent(trans, root, cur_alloc_size, | 756 | ret = btrfs_reserve_extent(trans, root, cur_alloc_size, |
743 | root->sectorsize, 0, alloc_hint, | 757 | root->sectorsize, 0, alloc_hint, |
@@ -789,10 +803,13 @@ static noinline int cow_file_range(struct inode *inode, | |||
789 | * Do set the Private2 bit so we know this page was properly | 803 | * Do set the Private2 bit so we know this page was properly |
790 | * setup for writepage | 804 | * setup for writepage |
791 | */ | 805 | */ |
806 | op = unlock ? EXTENT_CLEAR_UNLOCK_PAGE : 0; | ||
807 | op |= EXTENT_CLEAR_UNLOCK | EXTENT_CLEAR_DELALLOC | | ||
808 | EXTENT_SET_PRIVATE2; | ||
809 | |||
792 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, | 810 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, |
793 | start, start + ram_size - 1, | 811 | start, start + ram_size - 1, |
794 | locked_page, unlock, 1, | 812 | locked_page, op); |
795 | 1, 0, 0, 0, 1); | ||
796 | disk_num_bytes -= cur_alloc_size; | 813 | disk_num_bytes -= cur_alloc_size; |
797 | num_bytes -= cur_alloc_size; | 814 | num_bytes -= cur_alloc_size; |
798 | alloc_hint = ins.objectid + ins.offset; | 815 | alloc_hint = ins.objectid + ins.offset; |
@@ -864,8 +881,8 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, | |||
864 | u64 cur_end; | 881 | u64 cur_end; |
865 | int limit = 10 * 1024 * 1042; | 882 | int limit = 10 * 1024 * 1042; |
866 | 883 | ||
867 | clear_extent_bit(&BTRFS_I(inode)->io_tree, start, end, EXTENT_LOCKED | | 884 | clear_extent_bit(&BTRFS_I(inode)->io_tree, start, end, EXTENT_LOCKED, |
868 | EXTENT_DELALLOC, 1, 0, NULL, GFP_NOFS); | 885 | 1, 0, NULL, GFP_NOFS); |
869 | while (start < end) { | 886 | while (start < end) { |
870 | async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); | 887 | async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); |
871 | async_cow->inode = inode; | 888 | async_cow->inode = inode; |
@@ -1006,6 +1023,7 @@ next_slot: | |||
1006 | 1023 | ||
1007 | if (found_key.offset > cur_offset) { | 1024 | if (found_key.offset > cur_offset) { |
1008 | extent_end = found_key.offset; | 1025 | extent_end = found_key.offset; |
1026 | extent_type = 0; | ||
1009 | goto out_check; | 1027 | goto out_check; |
1010 | } | 1028 | } |
1011 | 1029 | ||
@@ -1112,8 +1130,10 @@ out_check: | |||
1112 | BUG_ON(ret); | 1130 | BUG_ON(ret); |
1113 | 1131 | ||
1114 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, | 1132 | extent_clear_unlock_delalloc(inode, &BTRFS_I(inode)->io_tree, |
1115 | cur_offset, cur_offset + num_bytes - 1, | 1133 | cur_offset, cur_offset + num_bytes - 1, |
1116 | locked_page, 1, 1, 1, 0, 0, 0, 1); | 1134 | locked_page, EXTENT_CLEAR_UNLOCK_PAGE | |
1135 | EXTENT_CLEAR_UNLOCK | EXTENT_CLEAR_DELALLOC | | ||
1136 | EXTENT_SET_PRIVATE2); | ||
1117 | cur_offset = extent_end; | 1137 | cur_offset = extent_end; |
1118 | if (cur_offset > end) | 1138 | if (cur_offset > end) |
1119 | break; | 1139 | break; |
@@ -1178,15 +1198,17 @@ static int btrfs_split_extent_hook(struct inode *inode, | |||
1178 | root->fs_info->max_extent); | 1198 | root->fs_info->max_extent); |
1179 | 1199 | ||
1180 | /* | 1200 | /* |
1181 | * if we break a large extent up then leave delalloc_extents be, | 1201 | * if we break a large extent up then leave oustanding_extents |
1182 | * since we've already accounted for the large extent. | 1202 | * be, since we've already accounted for the large extent. |
1183 | */ | 1203 | */ |
1184 | if (div64_u64(new_size + root->fs_info->max_extent - 1, | 1204 | if (div64_u64(new_size + root->fs_info->max_extent - 1, |
1185 | root->fs_info->max_extent) < num_extents) | 1205 | root->fs_info->max_extent) < num_extents) |
1186 | return 0; | 1206 | return 0; |
1187 | } | 1207 | } |
1188 | 1208 | ||
1189 | BTRFS_I(inode)->delalloc_extents++; | 1209 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1210 | BTRFS_I(inode)->outstanding_extents++; | ||
1211 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1190 | 1212 | ||
1191 | return 0; | 1213 | return 0; |
1192 | } | 1214 | } |
@@ -1217,7 +1239,9 @@ static int btrfs_merge_extent_hook(struct inode *inode, | |||
1217 | 1239 | ||
1218 | /* we're not bigger than the max, unreserve the space and go */ | 1240 | /* we're not bigger than the max, unreserve the space and go */ |
1219 | if (new_size <= root->fs_info->max_extent) { | 1241 | if (new_size <= root->fs_info->max_extent) { |
1220 | BTRFS_I(inode)->delalloc_extents--; | 1242 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1243 | BTRFS_I(inode)->outstanding_extents--; | ||
1244 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1221 | return 0; | 1245 | return 0; |
1222 | } | 1246 | } |
1223 | 1247 | ||
@@ -1231,7 +1255,9 @@ static int btrfs_merge_extent_hook(struct inode *inode, | |||
1231 | root->fs_info->max_extent) > num_extents) | 1255 | root->fs_info->max_extent) > num_extents) |
1232 | return 0; | 1256 | return 0; |
1233 | 1257 | ||
1234 | BTRFS_I(inode)->delalloc_extents--; | 1258 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1259 | BTRFS_I(inode)->outstanding_extents--; | ||
1260 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1235 | 1261 | ||
1236 | return 0; | 1262 | return 0; |
1237 | } | 1263 | } |
@@ -1253,7 +1279,9 @@ static int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end, | |||
1253 | if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { | 1279 | if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { |
1254 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1280 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1255 | 1281 | ||
1256 | BTRFS_I(inode)->delalloc_extents++; | 1282 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1283 | BTRFS_I(inode)->outstanding_extents++; | ||
1284 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1257 | btrfs_delalloc_reserve_space(root, inode, end - start + 1); | 1285 | btrfs_delalloc_reserve_space(root, inode, end - start + 1); |
1258 | spin_lock(&root->fs_info->delalloc_lock); | 1286 | spin_lock(&root->fs_info->delalloc_lock); |
1259 | BTRFS_I(inode)->delalloc_bytes += end - start + 1; | 1287 | BTRFS_I(inode)->delalloc_bytes += end - start + 1; |
@@ -1281,8 +1309,12 @@ static int btrfs_clear_bit_hook(struct inode *inode, | |||
1281 | if ((state->state & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { | 1309 | if ((state->state & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) { |
1282 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1310 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1283 | 1311 | ||
1284 | BTRFS_I(inode)->delalloc_extents--; | 1312 | if (bits & EXTENT_DO_ACCOUNTING) { |
1285 | btrfs_unreserve_metadata_for_delalloc(root, inode, 1); | 1313 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
1314 | BTRFS_I(inode)->outstanding_extents--; | ||
1315 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
1316 | btrfs_unreserve_metadata_for_delalloc(root, inode, 1); | ||
1317 | } | ||
1286 | 1318 | ||
1287 | spin_lock(&root->fs_info->delalloc_lock); | 1319 | spin_lock(&root->fs_info->delalloc_lock); |
1288 | if (state->end - state->start + 1 > | 1320 | if (state->end - state->start + 1 > |
@@ -3598,12 +3630,14 @@ static int btrfs_dentry_delete(struct dentry *dentry) | |||
3598 | { | 3630 | { |
3599 | struct btrfs_root *root; | 3631 | struct btrfs_root *root; |
3600 | 3632 | ||
3601 | if (!dentry->d_inode) | 3633 | if (!dentry->d_inode && !IS_ROOT(dentry)) |
3602 | return 0; | 3634 | dentry = dentry->d_parent; |
3603 | 3635 | ||
3604 | root = BTRFS_I(dentry->d_inode)->root; | 3636 | if (dentry->d_inode) { |
3605 | if (btrfs_root_refs(&root->root_item) == 0) | 3637 | root = BTRFS_I(dentry->d_inode)->root; |
3606 | return 1; | 3638 | if (btrfs_root_refs(&root->root_item) == 0) |
3639 | return 1; | ||
3640 | } | ||
3607 | return 0; | 3641 | return 0; |
3608 | } | 3642 | } |
3609 | 3643 | ||
@@ -4808,7 +4842,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) | |||
4808 | */ | 4842 | */ |
4809 | clear_extent_bit(tree, page_start, page_end, | 4843 | clear_extent_bit(tree, page_start, page_end, |
4810 | EXTENT_DIRTY | EXTENT_DELALLOC | | 4844 | EXTENT_DIRTY | EXTENT_DELALLOC | |
4811 | EXTENT_LOCKED, 1, 0, NULL, GFP_NOFS); | 4845 | EXTENT_LOCKED | EXTENT_DO_ACCOUNTING, 1, 0, |
4846 | NULL, GFP_NOFS); | ||
4812 | /* | 4847 | /* |
4813 | * whoever cleared the private bit is responsible | 4848 | * whoever cleared the private bit is responsible |
4814 | * for the finish_ordered_io | 4849 | * for the finish_ordered_io |
@@ -4821,8 +4856,8 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) | |||
4821 | lock_extent(tree, page_start, page_end, GFP_NOFS); | 4856 | lock_extent(tree, page_start, page_end, GFP_NOFS); |
4822 | } | 4857 | } |
4823 | clear_extent_bit(tree, page_start, page_end, | 4858 | clear_extent_bit(tree, page_start, page_end, |
4824 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC, | 4859 | EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC | |
4825 | 1, 1, NULL, GFP_NOFS); | 4860 | EXTENT_DO_ACCOUNTING, 1, 1, NULL, GFP_NOFS); |
4826 | __btrfs_releasepage(page, GFP_NOFS); | 4861 | __btrfs_releasepage(page, GFP_NOFS); |
4827 | 4862 | ||
4828 | ClearPageChecked(page); | 4863 | ClearPageChecked(page); |
@@ -4917,7 +4952,8 @@ again: | |||
4917 | * prepare_pages in the normal write path. | 4952 | * prepare_pages in the normal write path. |
4918 | */ | 4953 | */ |
4919 | clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end, | 4954 | clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end, |
4920 | EXTENT_DIRTY | EXTENT_DELALLOC, GFP_NOFS); | 4955 | EXTENT_DIRTY | EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING, |
4956 | GFP_NOFS); | ||
4921 | 4957 | ||
4922 | ret = btrfs_set_extent_delalloc(inode, page_start, page_end); | 4958 | ret = btrfs_set_extent_delalloc(inode, page_start, page_end); |
4923 | if (ret) { | 4959 | if (ret) { |
@@ -5065,8 +5101,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
5065 | return NULL; | 5101 | return NULL; |
5066 | ei->last_trans = 0; | 5102 | ei->last_trans = 0; |
5067 | ei->logged_trans = 0; | 5103 | ei->logged_trans = 0; |
5068 | ei->delalloc_extents = 0; | 5104 | ei->outstanding_extents = 0; |
5069 | ei->delalloc_reserved_extents = 0; | 5105 | ei->reserved_extents = 0; |
5106 | spin_lock_init(&ei->accounting_lock); | ||
5070 | btrfs_ordered_inode_tree_init(&ei->ordered_tree); | 5107 | btrfs_ordered_inode_tree_init(&ei->ordered_tree); |
5071 | INIT_LIST_HEAD(&ei->i_orphan); | 5108 | INIT_LIST_HEAD(&ei->i_orphan); |
5072 | INIT_LIST_HEAD(&ei->ordered_operations); | 5109 | INIT_LIST_HEAD(&ei->ordered_operations); |
@@ -5805,6 +5842,6 @@ static const struct inode_operations btrfs_symlink_inode_operations = { | |||
5805 | .removexattr = btrfs_removexattr, | 5842 | .removexattr = btrfs_removexattr, |
5806 | }; | 5843 | }; |
5807 | 5844 | ||
5808 | struct dentry_operations btrfs_dentry_operations = { | 5845 | const struct dentry_operations btrfs_dentry_operations = { |
5809 | .d_delete = btrfs_dentry_delete, | 5846 | .d_delete = btrfs_dentry_delete, |
5810 | }; | 5847 | }; |