diff options
-rw-r--r-- | fs/btrfs/ctree.h | 6 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 76 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 42 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 69 |
4 files changed, 155 insertions, 38 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index af523d695432..b7e2c1c1ef36 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -3749,6 +3749,12 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
3749 | struct bio *bio, u64 file_start, int contig); | 3749 | struct bio *bio, u64 file_start, int contig); |
3750 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | 3750 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, |
3751 | struct list_head *list, int search_commit); | 3751 | struct list_head *list, int search_commit); |
3752 | void btrfs_extent_item_to_extent_map(struct inode *inode, | ||
3753 | const struct btrfs_path *path, | ||
3754 | struct btrfs_file_extent_item *fi, | ||
3755 | const bool new_inline, | ||
3756 | struct extent_map *em); | ||
3757 | |||
3752 | /* inode.c */ | 3758 | /* inode.c */ |
3753 | struct btrfs_delalloc_work { | 3759 | struct btrfs_delalloc_work { |
3754 | struct inode *inode; | 3760 | struct inode *inode; |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 609d56b9fd8e..f46cfe45d686 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -885,3 +885,79 @@ out: | |||
885 | fail_unlock: | 885 | fail_unlock: |
886 | goto out; | 886 | goto out; |
887 | } | 887 | } |
888 | |||
889 | void btrfs_extent_item_to_extent_map(struct inode *inode, | ||
890 | const struct btrfs_path *path, | ||
891 | struct btrfs_file_extent_item *fi, | ||
892 | const bool new_inline, | ||
893 | struct extent_map *em) | ||
894 | { | ||
895 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
896 | struct extent_buffer *leaf = path->nodes[0]; | ||
897 | const int slot = path->slots[0]; | ||
898 | struct btrfs_key key; | ||
899 | u64 extent_start, extent_end; | ||
900 | u64 bytenr; | ||
901 | u8 type = btrfs_file_extent_type(leaf, fi); | ||
902 | int compress_type = btrfs_file_extent_compression(leaf, fi); | ||
903 | |||
904 | em->bdev = root->fs_info->fs_devices->latest_bdev; | ||
905 | btrfs_item_key_to_cpu(leaf, &key, slot); | ||
906 | extent_start = key.offset; | ||
907 | |||
908 | if (type == BTRFS_FILE_EXTENT_REG || | ||
909 | type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
910 | extent_end = extent_start + | ||
911 | btrfs_file_extent_num_bytes(leaf, fi); | ||
912 | } else if (type == BTRFS_FILE_EXTENT_INLINE) { | ||
913 | size_t size; | ||
914 | size = btrfs_file_extent_inline_len(leaf, slot, fi); | ||
915 | extent_end = ALIGN(extent_start + size, root->sectorsize); | ||
916 | } | ||
917 | |||
918 | em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi); | ||
919 | if (type == BTRFS_FILE_EXTENT_REG || | ||
920 | type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
921 | em->start = extent_start; | ||
922 | em->len = extent_end - extent_start; | ||
923 | em->orig_start = extent_start - | ||
924 | btrfs_file_extent_offset(leaf, fi); | ||
925 | em->orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi); | ||
926 | bytenr = btrfs_file_extent_disk_bytenr(leaf, fi); | ||
927 | if (bytenr == 0) { | ||
928 | em->block_start = EXTENT_MAP_HOLE; | ||
929 | return; | ||
930 | } | ||
931 | if (compress_type != BTRFS_COMPRESS_NONE) { | ||
932 | set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); | ||
933 | em->compress_type = compress_type; | ||
934 | em->block_start = bytenr; | ||
935 | em->block_len = em->orig_block_len; | ||
936 | } else { | ||
937 | bytenr += btrfs_file_extent_offset(leaf, fi); | ||
938 | em->block_start = bytenr; | ||
939 | em->block_len = em->len; | ||
940 | if (type == BTRFS_FILE_EXTENT_PREALLOC) | ||
941 | set_bit(EXTENT_FLAG_PREALLOC, &em->flags); | ||
942 | } | ||
943 | } else if (type == BTRFS_FILE_EXTENT_INLINE) { | ||
944 | em->block_start = EXTENT_MAP_INLINE; | ||
945 | em->start = extent_start; | ||
946 | em->len = extent_end - extent_start; | ||
947 | /* | ||
948 | * Initialize orig_start and block_len with the same values | ||
949 | * as in inode.c:btrfs_get_extent(). | ||
950 | */ | ||
951 | em->orig_start = EXTENT_MAP_HOLE; | ||
952 | em->block_len = (u64)-1; | ||
953 | if (!new_inline && compress_type != BTRFS_COMPRESS_NONE) { | ||
954 | set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); | ||
955 | em->compress_type = compress_type; | ||
956 | } | ||
957 | } else { | ||
958 | btrfs_err(root->fs_info, | ||
959 | "unknown file extent item type %d, inode %llu, offset %llu, root %llu", | ||
960 | type, btrfs_ino(inode), extent_start, | ||
961 | root->root_key.objectid); | ||
962 | } | ||
963 | } | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 477e64a1146f..372b2cb2b297 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -6129,7 +6129,6 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
6129 | { | 6129 | { |
6130 | int ret; | 6130 | int ret; |
6131 | int err = 0; | 6131 | int err = 0; |
6132 | u64 bytenr; | ||
6133 | u64 extent_start = 0; | 6132 | u64 extent_start = 0; |
6134 | u64 extent_end = 0; | 6133 | u64 extent_end = 0; |
6135 | u64 objectid = btrfs_ino(inode); | 6134 | u64 objectid = btrfs_ino(inode); |
@@ -6143,7 +6142,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
6143 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 6142 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
6144 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 6143 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
6145 | struct btrfs_trans_handle *trans = NULL; | 6144 | struct btrfs_trans_handle *trans = NULL; |
6146 | int compress_type; | 6145 | const bool new_inline = !page || create; |
6147 | 6146 | ||
6148 | again: | 6147 | again: |
6149 | read_lock(&em_tree->lock); | 6148 | read_lock(&em_tree->lock); |
@@ -6217,7 +6216,6 @@ again: | |||
6217 | 6216 | ||
6218 | found_type = btrfs_file_extent_type(leaf, item); | 6217 | found_type = btrfs_file_extent_type(leaf, item); |
6219 | extent_start = found_key.offset; | 6218 | extent_start = found_key.offset; |
6220 | compress_type = btrfs_file_extent_compression(leaf, item); | ||
6221 | if (found_type == BTRFS_FILE_EXTENT_REG || | 6219 | if (found_type == BTRFS_FILE_EXTENT_REG || |
6222 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | 6220 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { |
6223 | extent_end = extent_start + | 6221 | extent_end = extent_start + |
@@ -6252,32 +6250,10 @@ next: | |||
6252 | goto not_found_em; | 6250 | goto not_found_em; |
6253 | } | 6251 | } |
6254 | 6252 | ||
6255 | em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, item); | 6253 | btrfs_extent_item_to_extent_map(inode, path, item, new_inline, em); |
6254 | |||
6256 | if (found_type == BTRFS_FILE_EXTENT_REG || | 6255 | if (found_type == BTRFS_FILE_EXTENT_REG || |
6257 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { | 6256 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { |
6258 | em->start = extent_start; | ||
6259 | em->len = extent_end - extent_start; | ||
6260 | em->orig_start = extent_start - | ||
6261 | btrfs_file_extent_offset(leaf, item); | ||
6262 | em->orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, | ||
6263 | item); | ||
6264 | bytenr = btrfs_file_extent_disk_bytenr(leaf, item); | ||
6265 | if (bytenr == 0) { | ||
6266 | em->block_start = EXTENT_MAP_HOLE; | ||
6267 | goto insert; | ||
6268 | } | ||
6269 | if (compress_type != BTRFS_COMPRESS_NONE) { | ||
6270 | set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); | ||
6271 | em->compress_type = compress_type; | ||
6272 | em->block_start = bytenr; | ||
6273 | em->block_len = em->orig_block_len; | ||
6274 | } else { | ||
6275 | bytenr += btrfs_file_extent_offset(leaf, item); | ||
6276 | em->block_start = bytenr; | ||
6277 | em->block_len = em->len; | ||
6278 | if (found_type == BTRFS_FILE_EXTENT_PREALLOC) | ||
6279 | set_bit(EXTENT_FLAG_PREALLOC, &em->flags); | ||
6280 | } | ||
6281 | goto insert; | 6257 | goto insert; |
6282 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 6258 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
6283 | unsigned long ptr; | 6259 | unsigned long ptr; |
@@ -6286,12 +6262,8 @@ next: | |||
6286 | size_t extent_offset; | 6262 | size_t extent_offset; |
6287 | size_t copy_size; | 6263 | size_t copy_size; |
6288 | 6264 | ||
6289 | em->block_start = EXTENT_MAP_INLINE; | 6265 | if (new_inline) |
6290 | if (!page || create) { | ||
6291 | em->start = extent_start; | ||
6292 | em->len = extent_end - extent_start; | ||
6293 | goto out; | 6266 | goto out; |
6294 | } | ||
6295 | 6267 | ||
6296 | size = btrfs_file_extent_inline_len(leaf, path->slots[0], item); | 6268 | size = btrfs_file_extent_inline_len(leaf, path->slots[0], item); |
6297 | extent_offset = page_offset(page) + pg_offset - extent_start; | 6269 | extent_offset = page_offset(page) + pg_offset - extent_start; |
@@ -6301,10 +6273,6 @@ next: | |||
6301 | em->len = ALIGN(copy_size, root->sectorsize); | 6273 | em->len = ALIGN(copy_size, root->sectorsize); |
6302 | em->orig_block_len = em->len; | 6274 | em->orig_block_len = em->len; |
6303 | em->orig_start = em->start; | 6275 | em->orig_start = em->start; |
6304 | if (compress_type) { | ||
6305 | set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); | ||
6306 | em->compress_type = compress_type; | ||
6307 | } | ||
6308 | ptr = btrfs_file_extent_inline_start(item) + extent_offset; | 6276 | ptr = btrfs_file_extent_inline_start(item) + extent_offset; |
6309 | if (create == 0 && !PageUptodate(page)) { | 6277 | if (create == 0 && !PageUptodate(page)) { |
6310 | if (btrfs_file_extent_compression(leaf, item) != | 6278 | if (btrfs_file_extent_compression(leaf, item) != |
@@ -6351,8 +6319,6 @@ next: | |||
6351 | set_extent_uptodate(io_tree, em->start, | 6319 | set_extent_uptodate(io_tree, em->start, |
6352 | extent_map_end(em) - 1, NULL, GFP_NOFS); | 6320 | extent_map_end(em) - 1, NULL, GFP_NOFS); |
6353 | goto insert; | 6321 | goto insert; |
6354 | } else { | ||
6355 | WARN(1, KERN_ERR "btrfs unknown found_type %d\n", found_type); | ||
6356 | } | 6322 | } |
6357 | not_found: | 6323 | not_found: |
6358 | em->start = start; | 6324 | em->start = start; |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index dd9a02a53c7b..c2e796b664c1 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3043,6 +3043,60 @@ out: | |||
3043 | return ret; | 3043 | return ret; |
3044 | } | 3044 | } |
3045 | 3045 | ||
3046 | static void clone_update_extent_map(struct inode *inode, | ||
3047 | const struct btrfs_trans_handle *trans, | ||
3048 | const struct btrfs_path *path, | ||
3049 | struct btrfs_file_extent_item *fi, | ||
3050 | const u64 hole_offset, | ||
3051 | const u64 hole_len) | ||
3052 | { | ||
3053 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | ||
3054 | struct extent_map *em; | ||
3055 | int ret; | ||
3056 | |||
3057 | em = alloc_extent_map(); | ||
3058 | if (!em) { | ||
3059 | set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, | ||
3060 | &BTRFS_I(inode)->runtime_flags); | ||
3061 | return; | ||
3062 | } | ||
3063 | |||
3064 | if (fi) { | ||
3065 | btrfs_extent_item_to_extent_map(inode, path, fi, false, em); | ||
3066 | em->generation = -1; | ||
3067 | if (btrfs_file_extent_type(path->nodes[0], fi) == | ||
3068 | BTRFS_FILE_EXTENT_INLINE) | ||
3069 | set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, | ||
3070 | &BTRFS_I(inode)->runtime_flags); | ||
3071 | } else { | ||
3072 | em->start = hole_offset; | ||
3073 | em->len = hole_len; | ||
3074 | em->ram_bytes = em->len; | ||
3075 | em->orig_start = hole_offset; | ||
3076 | em->block_start = EXTENT_MAP_HOLE; | ||
3077 | em->block_len = 0; | ||
3078 | em->orig_block_len = 0; | ||
3079 | em->compress_type = BTRFS_COMPRESS_NONE; | ||
3080 | em->generation = trans->transid; | ||
3081 | } | ||
3082 | |||
3083 | while (1) { | ||
3084 | write_lock(&em_tree->lock); | ||
3085 | ret = add_extent_mapping(em_tree, em, 1); | ||
3086 | write_unlock(&em_tree->lock); | ||
3087 | if (ret != -EEXIST) { | ||
3088 | free_extent_map(em); | ||
3089 | break; | ||
3090 | } | ||
3091 | btrfs_drop_extent_cache(inode, em->start, | ||
3092 | em->start + em->len - 1, 0); | ||
3093 | } | ||
3094 | |||
3095 | if (unlikely(ret)) | ||
3096 | set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, | ||
3097 | &BTRFS_I(inode)->runtime_flags); | ||
3098 | } | ||
3099 | |||
3046 | /** | 3100 | /** |
3047 | * btrfs_clone() - clone a range from inode file to another | 3101 | * btrfs_clone() - clone a range from inode file to another |
3048 | * | 3102 | * |
@@ -3361,8 +3415,19 @@ process_slot: | |||
3361 | btrfs_item_ptr_offset(leaf, slot), | 3415 | btrfs_item_ptr_offset(leaf, slot), |
3362 | size); | 3416 | size); |
3363 | inode_add_bytes(inode, datal); | 3417 | inode_add_bytes(inode, datal); |
3418 | extent = btrfs_item_ptr(leaf, slot, | ||
3419 | struct btrfs_file_extent_item); | ||
3364 | } | 3420 | } |
3365 | 3421 | ||
3422 | /* If we have an implicit hole (NO_HOLES feature). */ | ||
3423 | if (drop_start < new_key.offset) | ||
3424 | clone_update_extent_map(inode, trans, | ||
3425 | path, NULL, drop_start, | ||
3426 | new_key.offset - drop_start); | ||
3427 | |||
3428 | clone_update_extent_map(inode, trans, path, | ||
3429 | extent, 0, 0); | ||
3430 | |||
3366 | btrfs_mark_buffer_dirty(leaf); | 3431 | btrfs_mark_buffer_dirty(leaf); |
3367 | btrfs_release_path(path); | 3432 | btrfs_release_path(path); |
3368 | 3433 | ||
@@ -3406,6 +3471,10 @@ process_slot: | |||
3406 | } | 3471 | } |
3407 | ret = clone_finish_inode_update(trans, inode, destoff + len, | 3472 | ret = clone_finish_inode_update(trans, inode, destoff + len, |
3408 | destoff, olen); | 3473 | destoff, olen); |
3474 | if (ret) | ||
3475 | goto out; | ||
3476 | clone_update_extent_map(inode, trans, path, NULL, last_dest_end, | ||
3477 | destoff + len - last_dest_end); | ||
3409 | } | 3478 | } |
3410 | 3479 | ||
3411 | out: | 3480 | out: |