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 | ||
