diff options
author | Liu Bo <bo.li.liu@oracle.com> | 2017-01-31 10:50:22 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-02-17 06:03:48 -0500 |
commit | 6f9994dbabe5756df1922d84a568cbff74ae1323 (patch) | |
tree | 3b5d8e583bb73d757fd5c994ed9461a6ac1c3d8f /fs/btrfs/inode.c | |
parent | 4136135b080f5680fb31eda9348d1f636e4dbfb9 (diff) |
Btrfs: create a helper to create em for IO
We have similar codes to create and insert extent mapping around IO path,
this merges them into a single helper.
Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 189 |
1 files changed, 74 insertions, 115 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 175c28a94a57..b37b062789a7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -109,11 +109,11 @@ static noinline int cow_file_range(struct inode *inode, | |||
109 | u64 start, u64 end, u64 delalloc_end, | 109 | u64 start, u64 end, u64 delalloc_end, |
110 | int *page_started, unsigned long *nr_written, | 110 | int *page_started, unsigned long *nr_written, |
111 | int unlock, struct btrfs_dedupe_hash *hash); | 111 | int unlock, struct btrfs_dedupe_hash *hash); |
112 | static struct extent_map *create_pinned_em(struct inode *inode, u64 start, | 112 | static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len, |
113 | u64 len, u64 orig_start, | 113 | u64 orig_start, u64 block_start, |
114 | u64 block_start, u64 block_len, | 114 | u64 block_len, u64 orig_block_len, |
115 | u64 orig_block_len, u64 ram_bytes, | 115 | u64 ram_bytes, int compress_type, |
116 | int type); | 116 | int type); |
117 | 117 | ||
118 | static int btrfs_dirty_inode(struct inode *inode); | 118 | static int btrfs_dirty_inode(struct inode *inode); |
119 | 119 | ||
@@ -697,7 +697,6 @@ static noinline void submit_compressed_extents(struct inode *inode, | |||
697 | struct btrfs_key ins; | 697 | struct btrfs_key ins; |
698 | struct extent_map *em; | 698 | struct extent_map *em; |
699 | struct btrfs_root *root = BTRFS_I(inode)->root; | 699 | struct btrfs_root *root = BTRFS_I(inode)->root; |
700 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | ||
701 | struct extent_io_tree *io_tree; | 700 | struct extent_io_tree *io_tree; |
702 | int ret = 0; | 701 | int ret = 0; |
703 | 702 | ||
@@ -785,46 +784,19 @@ retry: | |||
785 | * here we're doing allocation and writeback of the | 784 | * here we're doing allocation and writeback of the |
786 | * compressed pages | 785 | * compressed pages |
787 | */ | 786 | */ |
788 | btrfs_drop_extent_cache(inode, async_extent->start, | 787 | em = create_io_em(inode, async_extent->start, |
789 | async_extent->start + | 788 | async_extent->ram_size, /* len */ |
790 | async_extent->ram_size - 1, 0); | 789 | async_extent->start, /* orig_start */ |
791 | 790 | ins.objectid, /* block_start */ | |
792 | em = alloc_extent_map(); | 791 | ins.offset, /* block_len */ |
793 | if (!em) { | 792 | ins.offset, /* orig_block_len */ |
794 | ret = -ENOMEM; | 793 | async_extent->ram_size, /* ram_bytes */ |
795 | goto out_free_reserve; | 794 | async_extent->compress_type, |
796 | } | 795 | BTRFS_ORDERED_COMPRESSED); |
797 | em->start = async_extent->start; | 796 | if (IS_ERR(em)) |
798 | em->len = async_extent->ram_size; | 797 | /* ret value is not necessary due to void function */ |
799 | em->orig_start = em->start; | ||
800 | em->mod_start = em->start; | ||
801 | em->mod_len = em->len; | ||
802 | |||
803 | em->block_start = ins.objectid; | ||
804 | em->block_len = ins.offset; | ||
805 | em->orig_block_len = ins.offset; | ||
806 | em->ram_bytes = async_extent->ram_size; | ||
807 | em->bdev = fs_info->fs_devices->latest_bdev; | ||
808 | em->compress_type = async_extent->compress_type; | ||
809 | set_bit(EXTENT_FLAG_PINNED, &em->flags); | ||
810 | set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); | ||
811 | em->generation = -1; | ||
812 | |||
813 | while (1) { | ||
814 | write_lock(&em_tree->lock); | ||
815 | ret = add_extent_mapping(em_tree, em, 1); | ||
816 | write_unlock(&em_tree->lock); | ||
817 | if (ret != -EEXIST) { | ||
818 | free_extent_map(em); | ||
819 | break; | ||
820 | } | ||
821 | btrfs_drop_extent_cache(inode, async_extent->start, | ||
822 | async_extent->start + | ||
823 | async_extent->ram_size - 1, 0); | ||
824 | } | ||
825 | |||
826 | if (ret) | ||
827 | goto out_free_reserve; | 798 | goto out_free_reserve; |
799 | free_extent_map(em); | ||
828 | 800 | ||
829 | ret = btrfs_add_ordered_extent_compress(inode, | 801 | ret = btrfs_add_ordered_extent_compress(inode, |
830 | async_extent->start, | 802 | async_extent->start, |
@@ -959,7 +931,6 @@ static noinline int cow_file_range(struct inode *inode, | |||
959 | u64 blocksize = fs_info->sectorsize; | 931 | u64 blocksize = fs_info->sectorsize; |
960 | struct btrfs_key ins; | 932 | struct btrfs_key ins; |
961 | struct extent_map *em; | 933 | struct extent_map *em; |
962 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | ||
963 | int ret = 0; | 934 | int ret = 0; |
964 | 935 | ||
965 | if (btrfs_is_free_space_inode(inode)) { | 936 | if (btrfs_is_free_space_inode(inode)) { |
@@ -1012,39 +983,18 @@ static noinline int cow_file_range(struct inode *inode, | |||
1012 | if (ret < 0) | 983 | if (ret < 0) |
1013 | goto out_unlock; | 984 | goto out_unlock; |
1014 | 985 | ||
1015 | em = alloc_extent_map(); | ||
1016 | if (!em) { | ||
1017 | ret = -ENOMEM; | ||
1018 | goto out_reserve; | ||
1019 | } | ||
1020 | em->start = start; | ||
1021 | em->orig_start = em->start; | ||
1022 | ram_size = ins.offset; | 986 | ram_size = ins.offset; |
1023 | em->len = ins.offset; | 987 | em = create_io_em(inode, start, ins.offset, /* len */ |
1024 | em->mod_start = em->start; | 988 | start, /* orig_start */ |
1025 | em->mod_len = em->len; | 989 | ins.objectid, /* block_start */ |
1026 | 990 | ins.offset, /* block_len */ | |
1027 | em->block_start = ins.objectid; | 991 | ins.offset, /* orig_block_len */ |
1028 | em->block_len = ins.offset; | 992 | ram_size, /* ram_bytes */ |
1029 | em->orig_block_len = ins.offset; | 993 | BTRFS_COMPRESS_NONE, /* compress_type */ |
1030 | em->ram_bytes = ram_size; | 994 | 0 /* type */); |
1031 | em->bdev = fs_info->fs_devices->latest_bdev; | 995 | if (IS_ERR(em)) |
1032 | set_bit(EXTENT_FLAG_PINNED, &em->flags); | ||
1033 | em->generation = -1; | ||
1034 | |||
1035 | while (1) { | ||
1036 | write_lock(&em_tree->lock); | ||
1037 | ret = add_extent_mapping(em_tree, em, 1); | ||
1038 | write_unlock(&em_tree->lock); | ||
1039 | if (ret != -EEXIST) { | ||
1040 | free_extent_map(em); | ||
1041 | break; | ||
1042 | } | ||
1043 | btrfs_drop_extent_cache(inode, start, | ||
1044 | start + ram_size - 1, 0); | ||
1045 | } | ||
1046 | if (ret) | ||
1047 | goto out_reserve; | 996 | goto out_reserve; |
997 | free_extent_map(em); | ||
1048 | 998 | ||
1049 | cur_alloc_size = ins.offset; | 999 | cur_alloc_size = ins.offset; |
1050 | ret = btrfs_add_ordered_extent(inode, start, ins.objectid, | 1000 | ret = btrfs_add_ordered_extent(inode, start, ins.objectid, |
@@ -1251,6 +1201,7 @@ static noinline int run_delalloc_nocow(struct inode *inode, | |||
1251 | struct btrfs_path *path; | 1201 | struct btrfs_path *path; |
1252 | struct btrfs_file_extent_item *fi; | 1202 | struct btrfs_file_extent_item *fi; |
1253 | struct btrfs_key found_key; | 1203 | struct btrfs_key found_key; |
1204 | struct extent_map *em; | ||
1254 | u64 cow_start; | 1205 | u64 cow_start; |
1255 | u64 cur_offset; | 1206 | u64 cur_offset; |
1256 | u64 extent_end; | 1207 | u64 extent_end; |
@@ -1431,35 +1382,28 @@ out_check: | |||
1431 | } | 1382 | } |
1432 | 1383 | ||
1433 | if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | 1384 | if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { |
1434 | struct extent_map *em; | 1385 | u64 orig_start = found_key.offset - extent_offset; |
1435 | struct extent_map_tree *em_tree; | 1386 | |
1436 | em_tree = &BTRFS_I(inode)->extent_tree; | 1387 | em = create_io_em(inode, cur_offset, num_bytes, |
1437 | em = alloc_extent_map(); | 1388 | orig_start, |
1438 | BUG_ON(!em); /* -ENOMEM */ | 1389 | disk_bytenr, /* block_start */ |
1439 | em->start = cur_offset; | 1390 | num_bytes, /* block_len */ |
1440 | em->orig_start = found_key.offset - extent_offset; | 1391 | disk_num_bytes, /* orig_block_len */ |
1441 | em->len = num_bytes; | 1392 | ram_bytes, BTRFS_COMPRESS_NONE, |
1442 | em->block_len = num_bytes; | 1393 | BTRFS_ORDERED_PREALLOC); |
1443 | em->block_start = disk_bytenr; | 1394 | if (IS_ERR(em)) { |
1444 | em->orig_block_len = disk_num_bytes; | 1395 | if (!nolock && nocow) |
1445 | em->ram_bytes = ram_bytes; | 1396 | btrfs_end_write_no_snapshoting(root); |
1446 | em->bdev = fs_info->fs_devices->latest_bdev; | 1397 | if (nocow) |
1447 | em->mod_start = em->start; | 1398 | btrfs_dec_nocow_writers(fs_info, |
1448 | em->mod_len = em->len; | 1399 | disk_bytenr); |
1449 | set_bit(EXTENT_FLAG_PINNED, &em->flags); | 1400 | ret = PTR_ERR(em); |
1450 | set_bit(EXTENT_FLAG_FILLING, &em->flags); | 1401 | goto error; |
1451 | em->generation = -1; | ||
1452 | while (1) { | ||
1453 | write_lock(&em_tree->lock); | ||
1454 | ret = add_extent_mapping(em_tree, em, 1); | ||
1455 | write_unlock(&em_tree->lock); | ||
1456 | if (ret != -EEXIST) { | ||
1457 | free_extent_map(em); | ||
1458 | break; | ||
1459 | } | ||
1460 | btrfs_drop_extent_cache(inode, em->start, | ||
1461 | em->start + em->len - 1, 0); | ||
1462 | } | 1402 | } |
1403 | free_extent_map(em); | ||
1404 | } | ||
1405 | |||
1406 | if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
1463 | type = BTRFS_ORDERED_PREALLOC; | 1407 | type = BTRFS_ORDERED_PREALLOC; |
1464 | } else { | 1408 | } else { |
1465 | type = BTRFS_ORDERED_NOCOW; | 1409 | type = BTRFS_ORDERED_NOCOW; |
@@ -7207,9 +7151,11 @@ static struct extent_map *btrfs_create_dio_extent(struct inode *inode, | |||
7207 | int ret; | 7151 | int ret; |
7208 | 7152 | ||
7209 | if (type != BTRFS_ORDERED_NOCOW) { | 7153 | if (type != BTRFS_ORDERED_NOCOW) { |
7210 | em = create_pinned_em(inode, start, len, orig_start, | 7154 | em = create_io_em(inode, start, len, orig_start, |
7211 | block_start, block_len, orig_block_len, | 7155 | block_start, block_len, orig_block_len, |
7212 | ram_bytes, type); | 7156 | ram_bytes, |
7157 | BTRFS_COMPRESS_NONE, /* compress_type */ | ||
7158 | type); | ||
7213 | if (IS_ERR(em)) | 7159 | if (IS_ERR(em)) |
7214 | goto out; | 7160 | goto out; |
7215 | } | 7161 | } |
@@ -7545,17 +7491,23 @@ static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend, | |||
7545 | return ret; | 7491 | return ret; |
7546 | } | 7492 | } |
7547 | 7493 | ||
7548 | static struct extent_map *create_pinned_em(struct inode *inode, u64 start, | 7494 | /* The callers of this must take lock_extent() */ |
7549 | u64 len, u64 orig_start, | 7495 | static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len, |
7550 | u64 block_start, u64 block_len, | 7496 | u64 orig_start, u64 block_start, |
7551 | u64 orig_block_len, u64 ram_bytes, | 7497 | u64 block_len, u64 orig_block_len, |
7552 | int type) | 7498 | u64 ram_bytes, int compress_type, |
7499 | int type) | ||
7553 | { | 7500 | { |
7554 | struct extent_map_tree *em_tree; | 7501 | struct extent_map_tree *em_tree; |
7555 | struct extent_map *em; | 7502 | struct extent_map *em; |
7556 | struct btrfs_root *root = BTRFS_I(inode)->root; | 7503 | struct btrfs_root *root = BTRFS_I(inode)->root; |
7557 | int ret; | 7504 | int ret; |
7558 | 7505 | ||
7506 | ASSERT(type == BTRFS_ORDERED_PREALLOC || | ||
7507 | type == BTRFS_ORDERED_COMPRESSED || | ||
7508 | type == BTRFS_ORDERED_NOCOW || | ||
7509 | type == 0); | ||
7510 | |||
7559 | em_tree = &BTRFS_I(inode)->extent_tree; | 7511 | em_tree = &BTRFS_I(inode)->extent_tree; |
7560 | em = alloc_extent_map(); | 7512 | em = alloc_extent_map(); |
7561 | if (!em) | 7513 | if (!em) |
@@ -7563,8 +7515,6 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start, | |||
7563 | 7515 | ||
7564 | em->start = start; | 7516 | em->start = start; |
7565 | em->orig_start = orig_start; | 7517 | em->orig_start = orig_start; |
7566 | em->mod_start = start; | ||
7567 | em->mod_len = len; | ||
7568 | em->len = len; | 7518 | em->len = len; |
7569 | em->block_len = block_len; | 7519 | em->block_len = block_len; |
7570 | em->block_start = block_start; | 7520 | em->block_start = block_start; |
@@ -7575,6 +7525,10 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start, | |||
7575 | set_bit(EXTENT_FLAG_PINNED, &em->flags); | 7525 | set_bit(EXTENT_FLAG_PINNED, &em->flags); |
7576 | if (type == BTRFS_ORDERED_PREALLOC) | 7526 | if (type == BTRFS_ORDERED_PREALLOC) |
7577 | set_bit(EXTENT_FLAG_FILLING, &em->flags); | 7527 | set_bit(EXTENT_FLAG_FILLING, &em->flags); |
7528 | else if (type == BTRFS_ORDERED_COMPRESSED) { | ||
7529 | set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); | ||
7530 | em->compress_type = compress_type; | ||
7531 | } | ||
7578 | 7532 | ||
7579 | do { | 7533 | do { |
7580 | btrfs_drop_extent_cache(inode, em->start, | 7534 | btrfs_drop_extent_cache(inode, em->start, |
@@ -7582,6 +7536,10 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start, | |||
7582 | write_lock(&em_tree->lock); | 7536 | write_lock(&em_tree->lock); |
7583 | ret = add_extent_mapping(em_tree, em, 1); | 7537 | ret = add_extent_mapping(em_tree, em, 1); |
7584 | write_unlock(&em_tree->lock); | 7538 | write_unlock(&em_tree->lock); |
7539 | /* | ||
7540 | * The caller has taken lock_extent(), who could race with us | ||
7541 | * to add em? | ||
7542 | */ | ||
7585 | } while (ret == -EEXIST); | 7543 | } while (ret == -EEXIST); |
7586 | 7544 | ||
7587 | if (ret) { | 7545 | if (ret) { |
@@ -7589,6 +7547,7 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start, | |||
7589 | return ERR_PTR(ret); | 7547 | return ERR_PTR(ret); |
7590 | } | 7548 | } |
7591 | 7549 | ||
7550 | /* em got 2 refs now, callers needs to do free_extent_map once. */ | ||
7592 | return em; | 7551 | return em; |
7593 | } | 7552 | } |
7594 | 7553 | ||