aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c52
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/dir-item.c2
-rw-r--r--fs/btrfs/extent_map.c11
-rw-r--r--fs/btrfs/extent_map.h1
-rw-r--r--fs/btrfs/file-item.c2
-rw-r--r--fs/btrfs/file.c36
-rw-r--r--fs/btrfs/inode.c67
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:
1930int btrfs_truncate_item(struct btrfs_trans_handle *trans, 1930int 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
907int btrfs_truncate_item(struct btrfs_trans_handle *trans, 907int 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);
911int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root 911int 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 }
680delete:
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;