aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-11-01 11:28:41 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:57 -0400
commit179e29e488cc74f1e9bd67bc45f70b832740e9ec (patch)
treeaa055d77b8d3f2b4bc59b1bb8a5b98ec0b223fb5
parent35ebb934bd7fcc7ca991b155b7980c3c4ff9f1a5 (diff)
Btrfs: Fix a number of inline extent problems that Yan Zheng reported.
The fixes do a number of things: 1) Most btrfs_drop_extent callers will try to leave the inline extents in place. It can truncate bytes off the beginning of the inline extent if required. 2) writepage can now update the inline extent, allowing mmap writes to go directly into the inline extent. 3) btrfs_truncate_in_transaction truncates inline extents 4) extent_map.c fixed to not merge inline extent mappings and hole mappings together Signed-off-by: Chris Mason <chris.mason@oracle.com>
-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;