diff options
-rw-r--r-- | fs/btrfs/ctree.c | 52 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 2 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 11 | ||||
-rw-r--r-- | fs/btrfs/extent_map.h | 1 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 2 | ||||
-rw-r--r-- | fs/btrfs/file.c | 36 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 67 |
8 files changed, 135 insertions, 38 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 516b90224a1b..eef9c92f86d5 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -1930,7 +1930,7 @@ again: | |||
1930 | int btrfs_truncate_item(struct btrfs_trans_handle *trans, | 1930 | int btrfs_truncate_item(struct btrfs_trans_handle *trans, |
1931 | struct btrfs_root *root, | 1931 | struct btrfs_root *root, |
1932 | struct btrfs_path *path, | 1932 | struct btrfs_path *path, |
1933 | u32 new_size) | 1933 | u32 new_size, int from_end) |
1934 | { | 1934 | { |
1935 | int ret = 0; | 1935 | int ret = 0; |
1936 | int slot; | 1936 | int slot; |
@@ -1946,13 +1946,17 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans, | |||
1946 | 1946 | ||
1947 | slot_orig = path->slots[0]; | 1947 | slot_orig = path->slots[0]; |
1948 | leaf = path->nodes[0]; | 1948 | leaf = path->nodes[0]; |
1949 | slot = path->slots[0]; | ||
1950 | |||
1951 | old_size = btrfs_item_size_nr(leaf, slot); | ||
1952 | if (old_size == new_size) | ||
1953 | return 0; | ||
1949 | 1954 | ||
1950 | nritems = btrfs_header_nritems(leaf); | 1955 | nritems = btrfs_header_nritems(leaf); |
1951 | data_end = leaf_data_end(root, leaf); | 1956 | data_end = leaf_data_end(root, leaf); |
1952 | 1957 | ||
1953 | slot = path->slots[0]; | ||
1954 | old_data_start = btrfs_item_offset_nr(leaf, slot); | 1958 | old_data_start = btrfs_item_offset_nr(leaf, slot); |
1955 | old_size = btrfs_item_size_nr(leaf, slot); BUG_ON(old_size <= new_size); | 1959 | |
1956 | size_diff = old_size - new_size; | 1960 | size_diff = old_size - new_size; |
1957 | 1961 | ||
1958 | BUG_ON(slot < 0); | 1962 | BUG_ON(slot < 0); |
@@ -1984,9 +1988,45 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans, | |||
1984 | } | 1988 | } |
1985 | 1989 | ||
1986 | /* shift the data */ | 1990 | /* shift the data */ |
1987 | memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + | 1991 | if (from_end) { |
1988 | data_end + size_diff, btrfs_leaf_data(leaf) + | 1992 | memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + |
1989 | data_end, old_data_start + new_size - data_end); | 1993 | data_end + size_diff, btrfs_leaf_data(leaf) + |
1994 | data_end, old_data_start + new_size - data_end); | ||
1995 | } else { | ||
1996 | struct btrfs_disk_key disk_key; | ||
1997 | u64 offset; | ||
1998 | |||
1999 | btrfs_item_key(leaf, &disk_key, slot); | ||
2000 | |||
2001 | if (btrfs_disk_key_type(&disk_key) == BTRFS_EXTENT_DATA_KEY) { | ||
2002 | unsigned long ptr; | ||
2003 | struct btrfs_file_extent_item *fi; | ||
2004 | |||
2005 | fi = btrfs_item_ptr(leaf, slot, | ||
2006 | struct btrfs_file_extent_item); | ||
2007 | fi = (struct btrfs_file_extent_item *)( | ||
2008 | (unsigned long)fi - size_diff); | ||
2009 | |||
2010 | if (btrfs_file_extent_type(leaf, fi) == | ||
2011 | BTRFS_FILE_EXTENT_INLINE) { | ||
2012 | ptr = btrfs_item_ptr_offset(leaf, slot); | ||
2013 | memmove_extent_buffer(leaf, ptr, | ||
2014 | (unsigned long)fi, | ||
2015 | offsetof(struct btrfs_file_extent_item, | ||
2016 | disk_bytenr)); | ||
2017 | } | ||
2018 | } | ||
2019 | |||
2020 | memmove_extent_buffer(leaf, btrfs_leaf_data(leaf) + | ||
2021 | data_end + size_diff, btrfs_leaf_data(leaf) + | ||
2022 | data_end, old_data_start - data_end); | ||
2023 | |||
2024 | offset = btrfs_disk_key_offset(&disk_key); | ||
2025 | btrfs_set_disk_key_offset(&disk_key, offset + size_diff); | ||
2026 | btrfs_set_item_key(leaf, &disk_key, slot); | ||
2027 | if (slot == 0) | ||
2028 | fixup_low_keys(trans, root, path, &disk_key, 1); | ||
2029 | } | ||
1990 | 2030 | ||
1991 | item = btrfs_item_nr(leaf, slot); | 2031 | item = btrfs_item_nr(leaf, slot); |
1992 | btrfs_set_item_size(leaf, item, new_size); | 2032 | btrfs_set_item_size(leaf, item, new_size); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 70e143b13577..d82afb618bf1 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -907,7 +907,7 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
907 | int btrfs_truncate_item(struct btrfs_trans_handle *trans, | 907 | int btrfs_truncate_item(struct btrfs_trans_handle *trans, |
908 | struct btrfs_root *root, | 908 | struct btrfs_root *root, |
909 | struct btrfs_path *path, | 909 | struct btrfs_path *path, |
910 | u32 new_size); | 910 | u32 new_size, int from_end); |
911 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | 911 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root |
912 | *root, struct btrfs_key *key, struct btrfs_path *p, int | 912 | *root, struct btrfs_key *key, struct btrfs_path *p, int |
913 | ins_len, int cow); | 913 | ins_len, int cow); |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 6f19de41b878..514a1dc337a8 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -249,7 +249,7 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, | |||
249 | memmove_extent_buffer(leaf, ptr, ptr + sub_item_len, | 249 | memmove_extent_buffer(leaf, ptr, ptr + sub_item_len, |
250 | item_len - (ptr + sub_item_len - start)); | 250 | item_len - (ptr + sub_item_len - start)); |
251 | ret = btrfs_truncate_item(trans, root, path, | 251 | ret = btrfs_truncate_item(trans, root, path, |
252 | item_len - sub_item_len); | 252 | item_len - sub_item_len, 1); |
253 | } | 253 | } |
254 | return 0; | 254 | return 0; |
255 | } | 255 | } |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 238cb1d81d56..44be9cfd30ee 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -263,7 +263,12 @@ int add_extent_mapping(struct extent_map_tree *tree, | |||
263 | if (prev && prev->end + 1 == em->start && | 263 | if (prev && prev->end + 1 == em->start && |
264 | ((em->block_start == EXTENT_MAP_HOLE && | 264 | ((em->block_start == EXTENT_MAP_HOLE && |
265 | prev->block_start == EXTENT_MAP_HOLE) || | 265 | prev->block_start == EXTENT_MAP_HOLE) || |
266 | (em->block_start == prev->block_end + 1))) { | 266 | (em->block_start == EXTENT_MAP_INLINE && |
267 | prev->block_start == EXTENT_MAP_INLINE) || | ||
268 | (em->block_start == EXTENT_MAP_DELALLOC && | ||
269 | prev->block_start == EXTENT_MAP_DELALLOC) || | ||
270 | (em->block_start < EXTENT_MAP_DELALLOC - 1 && | ||
271 | em->block_start == prev->block_end + 1))) { | ||
267 | em->start = prev->start; | 272 | em->start = prev->start; |
268 | em->block_start = prev->block_start; | 273 | em->block_start = prev->block_start; |
269 | rb_erase(&prev->rb_node, &tree->map); | 274 | rb_erase(&prev->rb_node, &tree->map); |
@@ -1618,13 +1623,13 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
1618 | u64 extent_offset; | 1623 | u64 extent_offset; |
1619 | u64 last_byte = i_size_read(inode); | 1624 | u64 last_byte = i_size_read(inode); |
1620 | u64 block_start; | 1625 | u64 block_start; |
1626 | u64 iosize; | ||
1621 | sector_t sector; | 1627 | sector_t sector; |
1622 | struct extent_map *em; | 1628 | struct extent_map *em; |
1623 | struct block_device *bdev; | 1629 | struct block_device *bdev; |
1624 | int ret; | 1630 | int ret; |
1625 | int nr = 0; | 1631 | int nr = 0; |
1626 | size_t page_offset = 0; | 1632 | size_t page_offset = 0; |
1627 | size_t iosize; | ||
1628 | size_t blocksize; | 1633 | size_t blocksize; |
1629 | loff_t i_size = i_size_read(inode); | 1634 | loff_t i_size = i_size_read(inode); |
1630 | unsigned long end_index = i_size >> PAGE_CACHE_SHIFT; | 1635 | unsigned long end_index = i_size >> PAGE_CACHE_SHIFT; |
@@ -1684,7 +1689,7 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
1684 | clear_extent_dirty(tree, cur, page_end, GFP_NOFS); | 1689 | clear_extent_dirty(tree, cur, page_end, GFP_NOFS); |
1685 | break; | 1690 | break; |
1686 | } | 1691 | } |
1687 | em = get_extent(inode, page, page_offset, cur, end, 0); | 1692 | em = get_extent(inode, page, page_offset, cur, end, 1); |
1688 | if (IS_ERR(em) || !em) { | 1693 | if (IS_ERR(em) || !em) { |
1689 | SetPageError(page); | 1694 | SetPageError(page); |
1690 | break; | 1695 | break; |
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index 39d78d31b6a2..b6f6519f9ba3 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
@@ -24,7 +24,6 @@ | |||
24 | * page->private values. Every page that is controlled by the extent | 24 | * page->private values. Every page that is controlled by the extent |
25 | * map has page->private set to one. | 25 | * map has page->private set to one. |
26 | */ | 26 | */ |
27 | |||
28 | #define EXTENT_PAGE_PRIVATE 1 | 27 | #define EXTENT_PAGE_PRIVATE 1 |
29 | #define EXTENT_PAGE_PRIVATE_FIRST_PAGE 3 | 28 | #define EXTENT_PAGE_PRIVATE_FIRST_PAGE 3 |
30 | 29 | ||
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 7eb9a5412e2f..614176e52851 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -291,7 +291,7 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | |||
291 | new_item_size = blocks * BTRFS_CRC32_SIZE; | 291 | new_item_size = blocks * BTRFS_CRC32_SIZE; |
292 | if (new_item_size >= btrfs_item_size_nr(leaf, slot)) | 292 | if (new_item_size >= btrfs_item_size_nr(leaf, slot)) |
293 | return 0; | 293 | return 0; |
294 | ret = btrfs_truncate_item(trans, root, path, new_item_size); | 294 | ret = btrfs_truncate_item(trans, root, path, new_item_size, 1); |
295 | BUG_ON(ret); | 295 | BUG_ON(ret); |
296 | return ret; | 296 | return ret; |
297 | } | 297 | } |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index abdd9caad94e..4e52f7ec1cbe 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -115,8 +115,20 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
115 | goto fail; | 115 | goto fail; |
116 | } | 116 | } |
117 | if (ret == 1) { | 117 | if (ret == 1) { |
118 | struct btrfs_key found_key; | ||
119 | |||
120 | if (path->slots[0] == 0) | ||
121 | goto insert; | ||
122 | |||
118 | path->slots[0]--; | 123 | path->slots[0]--; |
119 | leaf = path->nodes[0]; | 124 | leaf = path->nodes[0]; |
125 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | ||
126 | |||
127 | if (found_key.objectid != inode->i_ino) | ||
128 | goto insert; | ||
129 | |||
130 | if (found_key.type != BTRFS_EXTENT_DATA_KEY) | ||
131 | goto insert; | ||
120 | ei = btrfs_item_ptr(leaf, path->slots[0], | 132 | ei = btrfs_item_ptr(leaf, path->slots[0], |
121 | struct btrfs_file_extent_item); | 133 | struct btrfs_file_extent_item); |
122 | 134 | ||
@@ -152,6 +164,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
152 | ret = btrfs_search_slot(trans, root, &key, path, | 164 | ret = btrfs_search_slot(trans, root, &key, path, |
153 | offset + size - found_end, 1); | 165 | offset + size - found_end, 1); |
154 | BUG_ON(ret != 0); | 166 | BUG_ON(ret != 0); |
167 | |||
155 | ret = btrfs_extend_item(trans, root, path, | 168 | ret = btrfs_extend_item(trans, root, path, |
156 | offset + size - found_end); | 169 | offset + size - found_end); |
157 | if (ret) { | 170 | if (ret) { |
@@ -292,7 +305,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
292 | */ | 305 | */ |
293 | inline_size = end_pos; | 306 | inline_size = end_pos; |
294 | if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) || | 307 | if (isize >= BTRFS_MAX_INLINE_DATA_SIZE(root) || |
295 | inline_size > 8192 || | 308 | inline_size > 32768 || |
296 | inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) { | 309 | inline_size >= BTRFS_MAX_INLINE_DATA_SIZE(root)) { |
297 | u64 last_end; | 310 | u64 last_end; |
298 | 311 | ||
@@ -312,7 +325,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
312 | aligned_end = (pos + write_bytes + root->sectorsize - 1) & | 325 | aligned_end = (pos + write_bytes + root->sectorsize - 1) & |
313 | ~((u64)root->sectorsize - 1); | 326 | ~((u64)root->sectorsize - 1); |
314 | err = btrfs_drop_extents(trans, root, inode, start_pos, | 327 | err = btrfs_drop_extents(trans, root, inode, start_pos, |
315 | aligned_end, end_pos, &hint_byte); | 328 | aligned_end, aligned_end, &hint_byte); |
316 | if (err) | 329 | if (err) |
317 | goto failed; | 330 | goto failed; |
318 | err = insert_inline_extent(trans, root, inode, start_pos, | 331 | err = insert_inline_extent(trans, root, inode, start_pos, |
@@ -456,13 +469,15 @@ next_slot: | |||
456 | goto next_slot; | 469 | goto next_slot; |
457 | } | 470 | } |
458 | 471 | ||
459 | /* FIXME, there's only one inline extent allowed right now */ | ||
460 | if (found_inline) { | 472 | if (found_inline) { |
461 | u64 mask = root->sectorsize - 1; | 473 | u64 mask = root->sectorsize - 1; |
462 | search_start = (extent_end + mask) & ~mask; | 474 | search_start = (extent_end + mask) & ~mask; |
463 | } else | 475 | } else |
464 | search_start = extent_end; | 476 | search_start = extent_end; |
465 | 477 | ||
478 | if (end <= extent_end && start >= key.offset && found_inline) { | ||
479 | *hint_byte = EXTENT_MAP_INLINE; | ||
480 | } | ||
466 | if (end < extent_end && end >= key.offset) { | 481 | if (end < extent_end && end >= key.offset) { |
467 | if (found_extent) { | 482 | if (found_extent) { |
468 | u64 disk_bytenr = | 483 | u64 disk_bytenr = |
@@ -479,8 +494,10 @@ next_slot: | |||
479 | BUG_ON(ret); | 494 | BUG_ON(ret); |
480 | } | 495 | } |
481 | } | 496 | } |
482 | if (!found_inline) | 497 | bookend = 1; |
483 | bookend = 1; | 498 | if (found_inline && start <= key.offset && |
499 | inline_end < extent_end) | ||
500 | keep = 1; | ||
484 | } | 501 | } |
485 | /* truncate existing extent */ | 502 | /* truncate existing extent */ |
486 | if (start > key.offset) { | 503 | if (start > key.offset) { |
@@ -510,7 +527,7 @@ next_slot: | |||
510 | new_size = btrfs_file_extent_calc_inline_size( | 527 | new_size = btrfs_file_extent_calc_inline_size( |
511 | inline_end - key.offset); | 528 | inline_end - key.offset); |
512 | btrfs_truncate_item(trans, root, path, | 529 | btrfs_truncate_item(trans, root, path, |
513 | new_size); | 530 | new_size, 1); |
514 | } | 531 | } |
515 | } | 532 | } |
516 | /* delete the entire extent */ | 533 | /* delete the entire extent */ |
@@ -551,6 +568,13 @@ next_slot: | |||
551 | if (!bookend) | 568 | if (!bookend) |
552 | continue; | 569 | continue; |
553 | } | 570 | } |
571 | if (bookend && found_inline && start <= key.offset && | ||
572 | inline_end < extent_end) { | ||
573 | u32 new_size; | ||
574 | new_size = btrfs_file_extent_calc_inline_size( | ||
575 | extent_end - inline_end); | ||
576 | btrfs_truncate_item(trans, root, path, new_size, 0); | ||
577 | } | ||
554 | /* create bookend, splitting the extent in two */ | 578 | /* create bookend, splitting the extent in two */ |
555 | if (bookend && found_extent) { | 579 | if (bookend && found_extent) { |
556 | struct btrfs_key ins; | 580 | struct btrfs_key ins; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5d10b64e42df..0c65141b9993 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -89,6 +89,9 @@ static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | |||
89 | ret = btrfs_drop_extents(trans, root, inode, | 89 | ret = btrfs_drop_extents(trans, root, inode, |
90 | start, start + num_bytes, start, &alloc_hint); | 90 | start, start + num_bytes, start, &alloc_hint); |
91 | 91 | ||
92 | if (alloc_hint == EXTENT_MAP_INLINE) | ||
93 | goto out; | ||
94 | |||
92 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0, | 95 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_bytes, 0, |
93 | alloc_hint, (u64)-1, &ins, 1); | 96 | alloc_hint, (u64)-1, &ins, 1); |
94 | if (ret) { | 97 | if (ret) { |
@@ -558,6 +561,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
558 | u64 item_end = 0; | 561 | u64 item_end = 0; |
559 | int found_extent; | 562 | int found_extent; |
560 | int del_item; | 563 | int del_item; |
564 | int extent_type = -1; | ||
561 | 565 | ||
562 | btrfs_drop_extent_cache(inode, inode->i_size, (u64)-1); | 566 | btrfs_drop_extent_cache(inode, inode->i_size, (u64)-1); |
563 | path = btrfs_alloc_path(); | 567 | path = btrfs_alloc_path(); |
@@ -597,10 +601,15 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
597 | if (found_type == BTRFS_EXTENT_DATA_KEY) { | 601 | if (found_type == BTRFS_EXTENT_DATA_KEY) { |
598 | fi = btrfs_item_ptr(leaf, path->slots[0], | 602 | fi = btrfs_item_ptr(leaf, path->slots[0], |
599 | struct btrfs_file_extent_item); | 603 | struct btrfs_file_extent_item); |
600 | if (btrfs_file_extent_type(leaf, fi) != | 604 | extent_type = btrfs_file_extent_type(leaf, fi); |
601 | BTRFS_FILE_EXTENT_INLINE) { | 605 | if (extent_type != BTRFS_FILE_EXTENT_INLINE) { |
602 | item_end += | 606 | item_end += |
603 | btrfs_file_extent_num_bytes(leaf, fi); | 607 | btrfs_file_extent_num_bytes(leaf, fi); |
608 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | ||
609 | struct btrfs_item *item = btrfs_item_nr(leaf, | ||
610 | path->slots[0]); | ||
611 | item_end += btrfs_file_extent_inline_len(leaf, | ||
612 | item); | ||
604 | } | 613 | } |
605 | } | 614 | } |
606 | if (found_type == BTRFS_CSUM_ITEM_KEY) { | 615 | if (found_type == BTRFS_CSUM_ITEM_KEY) { |
@@ -608,7 +617,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
608 | inode->i_size); | 617 | inode->i_size); |
609 | BUG_ON(ret); | 618 | BUG_ON(ret); |
610 | } | 619 | } |
611 | if (item_end < inode->i_size) { | 620 | if (item_end <= inode->i_size) { |
612 | if (found_type == BTRFS_DIR_ITEM_KEY) { | 621 | if (found_type == BTRFS_DIR_ITEM_KEY) { |
613 | found_type = BTRFS_INODE_ITEM_KEY; | 622 | found_type = BTRFS_INODE_ITEM_KEY; |
614 | } else if (found_type == BTRFS_EXTENT_ITEM_KEY) { | 623 | } else if (found_type == BTRFS_EXTENT_ITEM_KEY) { |
@@ -629,9 +638,10 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
629 | found_extent = 0; | 638 | found_extent = 0; |
630 | 639 | ||
631 | /* FIXME, shrink the extent if the ref count is only 1 */ | 640 | /* FIXME, shrink the extent if the ref count is only 1 */ |
632 | if (found_type == BTRFS_EXTENT_DATA_KEY && | 641 | if (found_type != BTRFS_EXTENT_DATA_KEY) |
633 | btrfs_file_extent_type(leaf, fi) != | 642 | goto delete; |
634 | BTRFS_FILE_EXTENT_INLINE) { | 643 | |
644 | if (extent_type != BTRFS_FILE_EXTENT_INLINE) { | ||
635 | u64 num_dec; | 645 | u64 num_dec; |
636 | extent_start = btrfs_file_extent_disk_bytenr(leaf, fi); | 646 | extent_start = btrfs_file_extent_disk_bytenr(leaf, fi); |
637 | if (!del_item) { | 647 | if (!del_item) { |
@@ -659,7 +669,15 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
659 | inode->i_blocks -= num_dec; | 669 | inode->i_blocks -= num_dec; |
660 | } | 670 | } |
661 | } | 671 | } |
672 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE && | ||
673 | !del_item) { | ||
674 | u32 newsize = inode->i_size - found_key.offset; | ||
675 | newsize = btrfs_file_extent_calc_inline_size(newsize); | ||
676 | ret = btrfs_truncate_item(trans, root, path, | ||
677 | newsize, 1); | ||
678 | BUG_ON(ret); | ||
662 | } | 679 | } |
680 | delete: | ||
663 | if (del_item) { | 681 | if (del_item) { |
664 | ret = btrfs_del_item(trans, root, path); | 682 | ret = btrfs_del_item(trans, root, path); |
665 | if (ret) | 683 | if (ret) |
@@ -769,7 +787,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
769 | u64 pos = (inode->i_size + mask) & ~mask; | 787 | u64 pos = (inode->i_size + mask) & ~mask; |
770 | u64 block_end = attr->ia_size | mask; | 788 | u64 block_end = attr->ia_size | mask; |
771 | u64 hole_size; | 789 | u64 hole_size; |
772 | u64 alloc_hint; | 790 | u64 alloc_hint = 0; |
773 | 791 | ||
774 | if (attr->ia_size <= pos) | 792 | if (attr->ia_size <= pos) |
775 | goto out; | 793 | goto out; |
@@ -786,8 +804,11 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
786 | pos, pos + hole_size, pos, | 804 | pos, pos + hole_size, pos, |
787 | &alloc_hint); | 805 | &alloc_hint); |
788 | 806 | ||
789 | err = btrfs_insert_file_extent(trans, root, inode->i_ino, | 807 | if (alloc_hint != EXTENT_MAP_INLINE) { |
790 | pos, 0, 0, hole_size); | 808 | err = btrfs_insert_file_extent(trans, root, |
809 | inode->i_ino, | ||
810 | pos, 0, 0, hole_size); | ||
811 | } | ||
791 | btrfs_end_transaction(trans, root); | 812 | btrfs_end_transaction(trans, root); |
792 | mutex_unlock(&root->fs_info->fs_mutex); | 813 | mutex_unlock(&root->fs_info->fs_mutex); |
793 | unlock_extent(em_tree, pos, block_end, GFP_NOFS); | 814 | unlock_extent(em_tree, pos, block_end, GFP_NOFS); |
@@ -1531,8 +1552,8 @@ again: | |||
1531 | em->end = EXTENT_MAP_HOLE; | 1552 | em->end = EXTENT_MAP_HOLE; |
1532 | } | 1553 | } |
1533 | em->bdev = inode->i_sb->s_bdev; | 1554 | em->bdev = inode->i_sb->s_bdev; |
1534 | ret = btrfs_lookup_file_extent(NULL, root, path, | 1555 | ret = btrfs_lookup_file_extent(trans, root, path, |
1535 | objectid, start, 0); | 1556 | objectid, start, trans != NULL); |
1536 | if (ret < 0) { | 1557 | if (ret < 0) { |
1537 | err = ret; | 1558 | err = ret; |
1538 | goto out; | 1559 | goto out; |
@@ -1627,15 +1648,23 @@ again: | |||
1627 | ((u64)root->sectorsize -1); | 1648 | ((u64)root->sectorsize -1); |
1628 | map = kmap(page); | 1649 | map = kmap(page); |
1629 | ptr = btrfs_file_extent_inline_start(item) + extent_offset; | 1650 | ptr = btrfs_file_extent_inline_start(item) + extent_offset; |
1630 | read_extent_buffer(leaf, map + page_offset, ptr, copy_size); | 1651 | if (create == 0 && !PageUptodate(page)) { |
1631 | 1652 | read_extent_buffer(leaf, map + page_offset, ptr, | |
1632 | if (em->start + copy_size <= em->end) { | 1653 | copy_size); |
1633 | size = min_t(u64, em->end + 1 - em->start, | 1654 | flush_dcache_page(page); |
1634 | PAGE_CACHE_SIZE - page_offset) - copy_size; | 1655 | } else if (create && PageUptodate(page)) { |
1635 | memset(map + page_offset + copy_size, 0, size); | 1656 | if (!trans) { |
1657 | kunmap(page); | ||
1658 | free_extent_map(em); | ||
1659 | em = NULL; | ||
1660 | btrfs_release_path(root, path); | ||
1661 | trans = btrfs_start_transaction(root, 1); | ||
1662 | goto again; | ||
1663 | } | ||
1664 | write_extent_buffer(leaf, map + page_offset, ptr, | ||
1665 | copy_size); | ||
1666 | btrfs_mark_buffer_dirty(leaf); | ||
1636 | } | 1667 | } |
1637 | |||
1638 | flush_dcache_page(page); | ||
1639 | kunmap(page); | 1668 | kunmap(page); |
1640 | set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS); | 1669 | set_extent_uptodate(em_tree, em->start, em->end, GFP_NOFS); |
1641 | goto insert; | 1670 | goto insert; |