diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 196 |
1 files changed, 130 insertions, 66 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 93c28a1d6bdc..fcd66b6a8086 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -112,6 +112,7 @@ static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | |||
112 | static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | 112 | static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, |
113 | struct btrfs_root *root, struct inode *inode, | 113 | struct btrfs_root *root, struct inode *inode, |
114 | u64 start, size_t size, size_t compressed_size, | 114 | u64 start, size_t size, size_t compressed_size, |
115 | int compress_type, | ||
115 | struct page **compressed_pages) | 116 | struct page **compressed_pages) |
116 | { | 117 | { |
117 | struct btrfs_key key; | 118 | struct btrfs_key key; |
@@ -126,12 +127,9 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
126 | size_t cur_size = size; | 127 | size_t cur_size = size; |
127 | size_t datasize; | 128 | size_t datasize; |
128 | unsigned long offset; | 129 | unsigned long offset; |
129 | int compress_type = BTRFS_COMPRESS_NONE; | ||
130 | 130 | ||
131 | if (compressed_size && compressed_pages) { | 131 | if (compressed_size && compressed_pages) |
132 | compress_type = root->fs_info->compress_type; | ||
133 | cur_size = compressed_size; | 132 | cur_size = compressed_size; |
134 | } | ||
135 | 133 | ||
136 | path = btrfs_alloc_path(); | 134 | path = btrfs_alloc_path(); |
137 | if (!path) | 135 | if (!path) |
@@ -221,7 +219,7 @@ fail: | |||
221 | static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | 219 | static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, |
222 | struct btrfs_root *root, | 220 | struct btrfs_root *root, |
223 | struct inode *inode, u64 start, u64 end, | 221 | struct inode *inode, u64 start, u64 end, |
224 | size_t compressed_size, | 222 | size_t compressed_size, int compress_type, |
225 | struct page **compressed_pages) | 223 | struct page **compressed_pages) |
226 | { | 224 | { |
227 | u64 isize = i_size_read(inode); | 225 | u64 isize = i_size_read(inode); |
@@ -254,7 +252,7 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, | |||
254 | inline_len = min_t(u64, isize, actual_end); | 252 | inline_len = min_t(u64, isize, actual_end); |
255 | ret = insert_inline_extent(trans, root, inode, start, | 253 | ret = insert_inline_extent(trans, root, inode, start, |
256 | inline_len, compressed_size, | 254 | inline_len, compressed_size, |
257 | compressed_pages); | 255 | compress_type, compressed_pages); |
258 | BUG_ON(ret); | 256 | BUG_ON(ret); |
259 | btrfs_delalloc_release_metadata(inode, end + 1 - start); | 257 | btrfs_delalloc_release_metadata(inode, end + 1 - start); |
260 | btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); | 258 | btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); |
@@ -433,12 +431,13 @@ again: | |||
433 | * to make an uncompressed inline extent. | 431 | * to make an uncompressed inline extent. |
434 | */ | 432 | */ |
435 | ret = cow_file_range_inline(trans, root, inode, | 433 | ret = cow_file_range_inline(trans, root, inode, |
436 | start, end, 0, NULL); | 434 | start, end, 0, 0, NULL); |
437 | } else { | 435 | } else { |
438 | /* try making a compressed inline extent */ | 436 | /* try making a compressed inline extent */ |
439 | ret = cow_file_range_inline(trans, root, inode, | 437 | ret = cow_file_range_inline(trans, root, inode, |
440 | start, end, | 438 | start, end, |
441 | total_compressed, pages); | 439 | total_compressed, |
440 | compress_type, pages); | ||
442 | } | 441 | } |
443 | if (ret == 0) { | 442 | if (ret == 0) { |
444 | /* | 443 | /* |
@@ -792,7 +791,7 @@ static noinline int cow_file_range(struct inode *inode, | |||
792 | if (start == 0) { | 791 | if (start == 0) { |
793 | /* lets try to make an inline extent */ | 792 | /* lets try to make an inline extent */ |
794 | ret = cow_file_range_inline(trans, root, inode, | 793 | ret = cow_file_range_inline(trans, root, inode, |
795 | start, end, 0, NULL); | 794 | start, end, 0, 0, NULL); |
796 | if (ret == 0) { | 795 | if (ret == 0) { |
797 | extent_clear_unlock_delalloc(inode, | 796 | extent_clear_unlock_delalloc(inode, |
798 | &BTRFS_I(inode)->io_tree, | 797 | &BTRFS_I(inode)->io_tree, |
@@ -1771,9 +1770,12 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1771 | add_pending_csums(trans, inode, ordered_extent->file_offset, | 1770 | add_pending_csums(trans, inode, ordered_extent->file_offset, |
1772 | &ordered_extent->list); | 1771 | &ordered_extent->list); |
1773 | 1772 | ||
1774 | btrfs_ordered_update_i_size(inode, 0, ordered_extent); | 1773 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); |
1775 | ret = btrfs_update_inode(trans, root, inode); | 1774 | if (!ret) { |
1776 | BUG_ON(ret); | 1775 | ret = btrfs_update_inode(trans, root, inode); |
1776 | BUG_ON(ret); | ||
1777 | } | ||
1778 | ret = 0; | ||
1777 | out: | 1779 | out: |
1778 | if (nolock) { | 1780 | if (nolock) { |
1779 | if (trans) | 1781 | if (trans) |
@@ -2222,8 +2224,6 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) | |||
2222 | insert = 1; | 2224 | insert = 1; |
2223 | #endif | 2225 | #endif |
2224 | insert = 1; | 2226 | insert = 1; |
2225 | } else { | ||
2226 | WARN_ON(!BTRFS_I(inode)->orphan_meta_reserved); | ||
2227 | } | 2227 | } |
2228 | 2228 | ||
2229 | if (!BTRFS_I(inode)->orphan_meta_reserved) { | 2229 | if (!BTRFS_I(inode)->orphan_meta_reserved) { |
@@ -2324,7 +2324,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2324 | 2324 | ||
2325 | /* | 2325 | /* |
2326 | * if ret == 0 means we found what we were searching for, which | 2326 | * if ret == 0 means we found what we were searching for, which |
2327 | * is weird, but possible, so only screw with path if we didnt | 2327 | * is weird, but possible, so only screw with path if we didn't |
2328 | * find the key and see if we have stuff that matches | 2328 | * find the key and see if we have stuff that matches |
2329 | */ | 2329 | */ |
2330 | if (ret > 0) { | 2330 | if (ret > 0) { |
@@ -2537,8 +2537,6 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
2537 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | 2537 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); |
2538 | 2538 | ||
2539 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); | 2539 | alloc_group_block = btrfs_inode_block_group(leaf, inode_item); |
2540 | if (location.objectid == BTRFS_FREE_SPACE_OBJECTID) | ||
2541 | inode->i_mapping->flags &= ~__GFP_FS; | ||
2542 | 2540 | ||
2543 | /* | 2541 | /* |
2544 | * try to precache a NULL acl entry for files that don't have | 2542 | * try to precache a NULL acl entry for files that don't have |
@@ -2595,6 +2593,13 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, | |||
2595 | struct btrfs_inode_item *item, | 2593 | struct btrfs_inode_item *item, |
2596 | struct inode *inode) | 2594 | struct inode *inode) |
2597 | { | 2595 | { |
2596 | if (!leaf->map_token) | ||
2597 | map_private_extent_buffer(leaf, (unsigned long)item, | ||
2598 | sizeof(struct btrfs_inode_item), | ||
2599 | &leaf->map_token, &leaf->kaddr, | ||
2600 | &leaf->map_start, &leaf->map_len, | ||
2601 | KM_USER1); | ||
2602 | |||
2598 | btrfs_set_inode_uid(leaf, item, inode->i_uid); | 2603 | btrfs_set_inode_uid(leaf, item, inode->i_uid); |
2599 | btrfs_set_inode_gid(leaf, item, inode->i_gid); | 2604 | btrfs_set_inode_gid(leaf, item, inode->i_gid); |
2600 | btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size); | 2605 | btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size); |
@@ -2623,6 +2628,11 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, | |||
2623 | btrfs_set_inode_rdev(leaf, item, inode->i_rdev); | 2628 | btrfs_set_inode_rdev(leaf, item, inode->i_rdev); |
2624 | btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); | 2629 | btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags); |
2625 | btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group); | 2630 | btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group); |
2631 | |||
2632 | if (leaf->map_token) { | ||
2633 | unmap_extent_buffer(leaf, leaf->map_token, KM_USER1); | ||
2634 | leaf->map_token = NULL; | ||
2635 | } | ||
2626 | } | 2636 | } |
2627 | 2637 | ||
2628 | /* | 2638 | /* |
@@ -4212,10 +4222,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4212 | struct btrfs_key found_key; | 4222 | struct btrfs_key found_key; |
4213 | struct btrfs_path *path; | 4223 | struct btrfs_path *path; |
4214 | int ret; | 4224 | int ret; |
4215 | u32 nritems; | ||
4216 | struct extent_buffer *leaf; | 4225 | struct extent_buffer *leaf; |
4217 | int slot; | 4226 | int slot; |
4218 | int advance; | ||
4219 | unsigned char d_type; | 4227 | unsigned char d_type; |
4220 | int over = 0; | 4228 | int over = 0; |
4221 | u32 di_cur; | 4229 | u32 di_cur; |
@@ -4258,27 +4266,19 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4258 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 4266 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
4259 | if (ret < 0) | 4267 | if (ret < 0) |
4260 | goto err; | 4268 | goto err; |
4261 | advance = 0; | ||
4262 | 4269 | ||
4263 | while (1) { | 4270 | while (1) { |
4264 | leaf = path->nodes[0]; | 4271 | leaf = path->nodes[0]; |
4265 | nritems = btrfs_header_nritems(leaf); | ||
4266 | slot = path->slots[0]; | 4272 | slot = path->slots[0]; |
4267 | if (advance || slot >= nritems) { | 4273 | if (slot >= btrfs_header_nritems(leaf)) { |
4268 | if (slot >= nritems - 1) { | 4274 | ret = btrfs_next_leaf(root, path); |
4269 | ret = btrfs_next_leaf(root, path); | 4275 | if (ret < 0) |
4270 | if (ret) | 4276 | goto err; |
4271 | break; | 4277 | else if (ret > 0) |
4272 | leaf = path->nodes[0]; | 4278 | break; |
4273 | nritems = btrfs_header_nritems(leaf); | 4279 | continue; |
4274 | slot = path->slots[0]; | ||
4275 | } else { | ||
4276 | slot++; | ||
4277 | path->slots[0]++; | ||
4278 | } | ||
4279 | } | 4280 | } |
4280 | 4281 | ||
4281 | advance = 1; | ||
4282 | item = btrfs_item_nr(leaf, slot); | 4282 | item = btrfs_item_nr(leaf, slot); |
4283 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | 4283 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
4284 | 4284 | ||
@@ -4287,7 +4287,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4287 | if (btrfs_key_type(&found_key) != key_type) | 4287 | if (btrfs_key_type(&found_key) != key_type) |
4288 | break; | 4288 | break; |
4289 | if (found_key.offset < filp->f_pos) | 4289 | if (found_key.offset < filp->f_pos) |
4290 | continue; | 4290 | goto next; |
4291 | 4291 | ||
4292 | filp->f_pos = found_key.offset; | 4292 | filp->f_pos = found_key.offset; |
4293 | 4293 | ||
@@ -4340,6 +4340,8 @@ skip: | |||
4340 | di_cur += di_len; | 4340 | di_cur += di_len; |
4341 | di = (struct btrfs_dir_item *)((char *)di + di_len); | 4341 | di = (struct btrfs_dir_item *)((char *)di + di_len); |
4342 | } | 4342 | } |
4343 | next: | ||
4344 | path->slots[0]++; | ||
4343 | } | 4345 | } |
4344 | 4346 | ||
4345 | /* Reached end of directory/root. Bump pos past the last item. */ | 4347 | /* Reached end of directory/root. Bump pos past the last item. */ |
@@ -4532,14 +4534,17 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
4532 | BUG_ON(!path); | 4534 | BUG_ON(!path); |
4533 | 4535 | ||
4534 | inode = new_inode(root->fs_info->sb); | 4536 | inode = new_inode(root->fs_info->sb); |
4535 | if (!inode) | 4537 | if (!inode) { |
4538 | btrfs_free_path(path); | ||
4536 | return ERR_PTR(-ENOMEM); | 4539 | return ERR_PTR(-ENOMEM); |
4540 | } | ||
4537 | 4541 | ||
4538 | if (dir) { | 4542 | if (dir) { |
4539 | trace_btrfs_inode_request(dir); | 4543 | trace_btrfs_inode_request(dir); |
4540 | 4544 | ||
4541 | ret = btrfs_set_inode_index(dir, index); | 4545 | ret = btrfs_set_inode_index(dir, index); |
4542 | if (ret) { | 4546 | if (ret) { |
4547 | btrfs_free_path(path); | ||
4543 | iput(inode); | 4548 | iput(inode); |
4544 | return ERR_PTR(ret); | 4549 | return ERR_PTR(ret); |
4545 | } | 4550 | } |
@@ -4839,9 +4844,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4839 | if (inode->i_nlink == ~0U) | 4844 | if (inode->i_nlink == ~0U) |
4840 | return -EMLINK; | 4845 | return -EMLINK; |
4841 | 4846 | ||
4842 | btrfs_inc_nlink(inode); | ||
4843 | inode->i_ctime = CURRENT_TIME; | ||
4844 | |||
4845 | err = btrfs_set_inode_index(dir, &index); | 4847 | err = btrfs_set_inode_index(dir, &index); |
4846 | if (err) | 4848 | if (err) |
4847 | goto fail; | 4849 | goto fail; |
@@ -4857,6 +4859,9 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4857 | goto fail; | 4859 | goto fail; |
4858 | } | 4860 | } |
4859 | 4861 | ||
4862 | btrfs_inc_nlink(inode); | ||
4863 | inode->i_ctime = CURRENT_TIME; | ||
4864 | |||
4860 | btrfs_set_trans_block_group(trans, dir); | 4865 | btrfs_set_trans_block_group(trans, dir); |
4861 | ihold(inode); | 4866 | ihold(inode); |
4862 | 4867 | ||
@@ -5226,7 +5231,7 @@ again: | |||
5226 | btrfs_mark_buffer_dirty(leaf); | 5231 | btrfs_mark_buffer_dirty(leaf); |
5227 | } | 5232 | } |
5228 | set_extent_uptodate(io_tree, em->start, | 5233 | set_extent_uptodate(io_tree, em->start, |
5229 | extent_map_end(em) - 1, GFP_NOFS); | 5234 | extent_map_end(em) - 1, NULL, GFP_NOFS); |
5230 | goto insert; | 5235 | goto insert; |
5231 | } else { | 5236 | } else { |
5232 | printk(KERN_ERR "btrfs unknown found_type %d\n", found_type); | 5237 | printk(KERN_ERR "btrfs unknown found_type %d\n", found_type); |
@@ -5433,17 +5438,30 @@ out: | |||
5433 | } | 5438 | } |
5434 | 5439 | ||
5435 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | 5440 | static struct extent_map *btrfs_new_extent_direct(struct inode *inode, |
5441 | struct extent_map *em, | ||
5436 | u64 start, u64 len) | 5442 | u64 start, u64 len) |
5437 | { | 5443 | { |
5438 | struct btrfs_root *root = BTRFS_I(inode)->root; | 5444 | struct btrfs_root *root = BTRFS_I(inode)->root; |
5439 | struct btrfs_trans_handle *trans; | 5445 | struct btrfs_trans_handle *trans; |
5440 | struct extent_map *em; | ||
5441 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 5446 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
5442 | struct btrfs_key ins; | 5447 | struct btrfs_key ins; |
5443 | u64 alloc_hint; | 5448 | u64 alloc_hint; |
5444 | int ret; | 5449 | int ret; |
5450 | bool insert = false; | ||
5445 | 5451 | ||
5446 | btrfs_drop_extent_cache(inode, start, start + len - 1, 0); | 5452 | /* |
5453 | * Ok if the extent map we looked up is a hole and is for the exact | ||
5454 | * range we want, there is no reason to allocate a new one, however if | ||
5455 | * it is not right then we need to free this one and drop the cache for | ||
5456 | * our range. | ||
5457 | */ | ||
5458 | if (em->block_start != EXTENT_MAP_HOLE || em->start != start || | ||
5459 | em->len != len) { | ||
5460 | free_extent_map(em); | ||
5461 | em = NULL; | ||
5462 | insert = true; | ||
5463 | btrfs_drop_extent_cache(inode, start, start + len - 1, 0); | ||
5464 | } | ||
5447 | 5465 | ||
5448 | trans = btrfs_join_transaction(root, 0); | 5466 | trans = btrfs_join_transaction(root, 0); |
5449 | if (IS_ERR(trans)) | 5467 | if (IS_ERR(trans)) |
@@ -5459,10 +5477,12 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | |||
5459 | goto out; | 5477 | goto out; |
5460 | } | 5478 | } |
5461 | 5479 | ||
5462 | em = alloc_extent_map(GFP_NOFS); | ||
5463 | if (!em) { | 5480 | if (!em) { |
5464 | em = ERR_PTR(-ENOMEM); | 5481 | em = alloc_extent_map(GFP_NOFS); |
5465 | goto out; | 5482 | if (!em) { |
5483 | em = ERR_PTR(-ENOMEM); | ||
5484 | goto out; | ||
5485 | } | ||
5466 | } | 5486 | } |
5467 | 5487 | ||
5468 | em->start = start; | 5488 | em->start = start; |
@@ -5472,9 +5492,15 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode, | |||
5472 | em->block_start = ins.objectid; | 5492 | em->block_start = ins.objectid; |
5473 | em->block_len = ins.offset; | 5493 | em->block_len = ins.offset; |
5474 | em->bdev = root->fs_info->fs_devices->latest_bdev; | 5494 | em->bdev = root->fs_info->fs_devices->latest_bdev; |
5495 | |||
5496 | /* | ||
5497 | * We need to do this because if we're using the original em we searched | ||
5498 | * for, we could have EXTENT_FLAG_VACANCY set, and we don't want that. | ||
5499 | */ | ||
5500 | em->flags = 0; | ||
5475 | set_bit(EXTENT_FLAG_PINNED, &em->flags); | 5501 | set_bit(EXTENT_FLAG_PINNED, &em->flags); |
5476 | 5502 | ||
5477 | while (1) { | 5503 | while (insert) { |
5478 | write_lock(&em_tree->lock); | 5504 | write_lock(&em_tree->lock); |
5479 | ret = add_extent_mapping(em_tree, em); | 5505 | ret = add_extent_mapping(em_tree, em); |
5480 | write_unlock(&em_tree->lock); | 5506 | write_unlock(&em_tree->lock); |
@@ -5692,8 +5718,7 @@ must_cow: | |||
5692 | * it above | 5718 | * it above |
5693 | */ | 5719 | */ |
5694 | len = bh_result->b_size; | 5720 | len = bh_result->b_size; |
5695 | free_extent_map(em); | 5721 | em = btrfs_new_extent_direct(inode, em, start, len); |
5696 | em = btrfs_new_extent_direct(inode, start, len); | ||
5697 | if (IS_ERR(em)) | 5722 | if (IS_ERR(em)) |
5698 | return PTR_ERR(em); | 5723 | return PTR_ERR(em); |
5699 | len = min(len, em->len - (start - em->start)); | 5724 | len = min(len, em->len - (start - em->start)); |
@@ -5856,8 +5881,10 @@ again: | |||
5856 | } | 5881 | } |
5857 | 5882 | ||
5858 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); | 5883 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); |
5859 | btrfs_ordered_update_i_size(inode, 0, ordered); | 5884 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); |
5860 | btrfs_update_inode(trans, root, inode); | 5885 | if (!ret) |
5886 | btrfs_update_inode(trans, root, inode); | ||
5887 | ret = 0; | ||
5861 | out_unlock: | 5888 | out_unlock: |
5862 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, | 5889 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, |
5863 | ordered->file_offset + ordered->len - 1, | 5890 | ordered->file_offset + ordered->len - 1, |
@@ -5943,7 +5970,7 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev, | |||
5943 | 5970 | ||
5944 | static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, | 5971 | static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, |
5945 | int rw, u64 file_offset, int skip_sum, | 5972 | int rw, u64 file_offset, int skip_sum, |
5946 | u32 *csums) | 5973 | u32 *csums, int async_submit) |
5947 | { | 5974 | { |
5948 | int write = rw & REQ_WRITE; | 5975 | int write = rw & REQ_WRITE; |
5949 | struct btrfs_root *root = BTRFS_I(inode)->root; | 5976 | struct btrfs_root *root = BTRFS_I(inode)->root; |
@@ -5954,13 +5981,24 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, | |||
5954 | if (ret) | 5981 | if (ret) |
5955 | goto err; | 5982 | goto err; |
5956 | 5983 | ||
5957 | if (write && !skip_sum) { | 5984 | if (skip_sum) |
5985 | goto map; | ||
5986 | |||
5987 | if (write && async_submit) { | ||
5958 | ret = btrfs_wq_submit_bio(root->fs_info, | 5988 | ret = btrfs_wq_submit_bio(root->fs_info, |
5959 | inode, rw, bio, 0, 0, | 5989 | inode, rw, bio, 0, 0, |
5960 | file_offset, | 5990 | file_offset, |
5961 | __btrfs_submit_bio_start_direct_io, | 5991 | __btrfs_submit_bio_start_direct_io, |
5962 | __btrfs_submit_bio_done); | 5992 | __btrfs_submit_bio_done); |
5963 | goto err; | 5993 | goto err; |
5994 | } else if (write) { | ||
5995 | /* | ||
5996 | * If we aren't doing async submit, calculate the csum of the | ||
5997 | * bio now. | ||
5998 | */ | ||
5999 | ret = btrfs_csum_one_bio(root, inode, bio, file_offset, 1); | ||
6000 | if (ret) | ||
6001 | goto err; | ||
5964 | } else if (!skip_sum) { | 6002 | } else if (!skip_sum) { |
5965 | ret = btrfs_lookup_bio_sums_dio(root, inode, bio, | 6003 | ret = btrfs_lookup_bio_sums_dio(root, inode, bio, |
5966 | file_offset, csums); | 6004 | file_offset, csums); |
@@ -5968,7 +6006,8 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, | |||
5968 | goto err; | 6006 | goto err; |
5969 | } | 6007 | } |
5970 | 6008 | ||
5971 | ret = btrfs_map_bio(root, rw, bio, 0, 1); | 6009 | map: |
6010 | ret = btrfs_map_bio(root, rw, bio, 0, async_submit); | ||
5972 | err: | 6011 | err: |
5973 | bio_put(bio); | 6012 | bio_put(bio); |
5974 | return ret; | 6013 | return ret; |
@@ -5990,15 +6029,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | |||
5990 | int nr_pages = 0; | 6029 | int nr_pages = 0; |
5991 | u32 *csums = dip->csums; | 6030 | u32 *csums = dip->csums; |
5992 | int ret = 0; | 6031 | int ret = 0; |
6032 | int async_submit = 0; | ||
5993 | int write = rw & REQ_WRITE; | 6033 | int write = rw & REQ_WRITE; |
5994 | 6034 | ||
5995 | bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS); | ||
5996 | if (!bio) | ||
5997 | return -ENOMEM; | ||
5998 | bio->bi_private = dip; | ||
5999 | bio->bi_end_io = btrfs_end_dio_bio; | ||
6000 | atomic_inc(&dip->pending_bios); | ||
6001 | |||
6002 | map_length = orig_bio->bi_size; | 6035 | map_length = orig_bio->bi_size; |
6003 | ret = btrfs_map_block(map_tree, READ, start_sector << 9, | 6036 | ret = btrfs_map_block(map_tree, READ, start_sector << 9, |
6004 | &map_length, NULL, 0); | 6037 | &map_length, NULL, 0); |
@@ -6007,6 +6040,19 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | |||
6007 | return -EIO; | 6040 | return -EIO; |
6008 | } | 6041 | } |
6009 | 6042 | ||
6043 | if (map_length >= orig_bio->bi_size) { | ||
6044 | bio = orig_bio; | ||
6045 | goto submit; | ||
6046 | } | ||
6047 | |||
6048 | async_submit = 1; | ||
6049 | bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS); | ||
6050 | if (!bio) | ||
6051 | return -ENOMEM; | ||
6052 | bio->bi_private = dip; | ||
6053 | bio->bi_end_io = btrfs_end_dio_bio; | ||
6054 | atomic_inc(&dip->pending_bios); | ||
6055 | |||
6010 | while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) { | 6056 | while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) { |
6011 | if (unlikely(map_length < submit_len + bvec->bv_len || | 6057 | if (unlikely(map_length < submit_len + bvec->bv_len || |
6012 | bio_add_page(bio, bvec->bv_page, bvec->bv_len, | 6058 | bio_add_page(bio, bvec->bv_page, bvec->bv_len, |
@@ -6020,7 +6066,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | |||
6020 | atomic_inc(&dip->pending_bios); | 6066 | atomic_inc(&dip->pending_bios); |
6021 | ret = __btrfs_submit_dio_bio(bio, inode, rw, | 6067 | ret = __btrfs_submit_dio_bio(bio, inode, rw, |
6022 | file_offset, skip_sum, | 6068 | file_offset, skip_sum, |
6023 | csums); | 6069 | csums, async_submit); |
6024 | if (ret) { | 6070 | if (ret) { |
6025 | bio_put(bio); | 6071 | bio_put(bio); |
6026 | atomic_dec(&dip->pending_bios); | 6072 | atomic_dec(&dip->pending_bios); |
@@ -6057,8 +6103,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | |||
6057 | } | 6103 | } |
6058 | } | 6104 | } |
6059 | 6105 | ||
6106 | submit: | ||
6060 | ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, | 6107 | ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, |
6061 | csums); | 6108 | csums, async_submit); |
6062 | if (!ret) | 6109 | if (!ret) |
6063 | return 0; | 6110 | return 0; |
6064 | 6111 | ||
@@ -6153,6 +6200,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io | |||
6153 | unsigned long nr_segs) | 6200 | unsigned long nr_segs) |
6154 | { | 6201 | { |
6155 | int seg; | 6202 | int seg; |
6203 | int i; | ||
6156 | size_t size; | 6204 | size_t size; |
6157 | unsigned long addr; | 6205 | unsigned long addr; |
6158 | unsigned blocksize_mask = root->sectorsize - 1; | 6206 | unsigned blocksize_mask = root->sectorsize - 1; |
@@ -6167,8 +6215,22 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io | |||
6167 | addr = (unsigned long)iov[seg].iov_base; | 6215 | addr = (unsigned long)iov[seg].iov_base; |
6168 | size = iov[seg].iov_len; | 6216 | size = iov[seg].iov_len; |
6169 | end += size; | 6217 | end += size; |
6170 | if ((addr & blocksize_mask) || (size & blocksize_mask)) | 6218 | if ((addr & blocksize_mask) || (size & blocksize_mask)) |
6171 | goto out; | 6219 | goto out; |
6220 | |||
6221 | /* If this is a write we don't need to check anymore */ | ||
6222 | if (rw & WRITE) | ||
6223 | continue; | ||
6224 | |||
6225 | /* | ||
6226 | * Check to make sure we don't have duplicate iov_base's in this | ||
6227 | * iovec, if so return EINVAL, otherwise we'll get csum errors | ||
6228 | * when reading back. | ||
6229 | */ | ||
6230 | for (i = seg + 1; i < nr_segs; i++) { | ||
6231 | if (iov[seg].iov_base == iov[i].iov_base) | ||
6232 | goto out; | ||
6233 | } | ||
6172 | } | 6234 | } |
6173 | retval = 0; | 6235 | retval = 0; |
6174 | out: | 6236 | out: |
@@ -6960,8 +7022,10 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
6960 | * should cover the worst case number of items we'll modify. | 7022 | * should cover the worst case number of items we'll modify. |
6961 | */ | 7023 | */ |
6962 | trans = btrfs_start_transaction(root, 20); | 7024 | trans = btrfs_start_transaction(root, 20); |
6963 | if (IS_ERR(trans)) | 7025 | if (IS_ERR(trans)) { |
6964 | return PTR_ERR(trans); | 7026 | ret = PTR_ERR(trans); |
7027 | goto out_notrans; | ||
7028 | } | ||
6965 | 7029 | ||
6966 | btrfs_set_trans_block_group(trans, new_dir); | 7030 | btrfs_set_trans_block_group(trans, new_dir); |
6967 | 7031 | ||
@@ -7061,7 +7125,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
7061 | } | 7125 | } |
7062 | out_fail: | 7126 | out_fail: |
7063 | btrfs_end_transaction_throttle(trans, root); | 7127 | btrfs_end_transaction_throttle(trans, root); |
7064 | 7128 | out_notrans: | |
7065 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | 7129 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) |
7066 | up_read(&root->fs_info->subvol_sem); | 7130 | up_read(&root->fs_info->subvol_sem); |
7067 | 7131 | ||