diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-08-27 16:49:44 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-08-27 16:49:44 -0400 |
commit | b888db2bd7b67f190b32934e6a86181f262ac3ec (patch) | |
tree | 7eb4472c65b6a634db6be689eedca09f09a40cd5 /fs | |
parent | a52d9a8033c454cd9b4697cfafb467509fc1693f (diff) |
Btrfs: Add delayed allocation to the extent based page tree code
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 9 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 147 | ||||
-rw-r--r-- | fs/btrfs/extent_map.h | 3 | ||||
-rw-r--r-- | fs/btrfs/file.c | 50 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 141 | ||||
-rw-r--r-- | fs/btrfs/super.c | 1 |
6 files changed, 216 insertions, 135 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 4049aadbeda9..c31e84d42653 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -39,7 +39,6 @@ static int cache_block_group(struct btrfs_root *root, | |||
39 | u64 i; | 39 | u64 i; |
40 | u64 last = 0; | 40 | u64 last = 0; |
41 | u64 hole_size; | 41 | u64 hole_size; |
42 | u64 limit; | ||
43 | int found = 0; | 42 | int found = 0; |
44 | 43 | ||
45 | root = root->fs_info->extent_root; | 44 | root = root->fs_info->extent_root; |
@@ -62,7 +61,6 @@ static int cache_block_group(struct btrfs_root *root, | |||
62 | return ret; | 61 | return ret; |
63 | if (ret && path->slots[0] > 0) | 62 | if (ret && path->slots[0] > 0) |
64 | path->slots[0]--; | 63 | path->slots[0]--; |
65 | limit = block_group->key.objectid + block_group->key.offset; | ||
66 | while(1) { | 64 | while(1) { |
67 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 65 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
68 | slot = path->slots[0]; | 66 | slot = path->slots[0]; |
@@ -982,7 +980,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
982 | struct btrfs_block_group_cache *block_group; | 980 | struct btrfs_block_group_cache *block_group; |
983 | int full_scan = 0; | 981 | int full_scan = 0; |
984 | int wrapped = 0; | 982 | int wrapped = 0; |
985 | u64 limit; | ||
986 | 983 | ||
987 | WARN_ON(num_blocks < 1); | 984 | WARN_ON(num_blocks < 1); |
988 | ins->flags = 0; | 985 | ins->flags = 0; |
@@ -1049,12 +1046,6 @@ check_failed: | |||
1049 | l = btrfs_buffer_leaf(path->nodes[0]); | 1046 | l = btrfs_buffer_leaf(path->nodes[0]); |
1050 | slot = path->slots[0]; | 1047 | slot = path->slots[0]; |
1051 | if (slot >= btrfs_header_nritems(&l->header)) { | 1048 | if (slot >= btrfs_header_nritems(&l->header)) { |
1052 | if (start_found) | ||
1053 | limit = last_block + | ||
1054 | (block_group->key.offset >> 1); | ||
1055 | else | ||
1056 | limit = search_start + | ||
1057 | (block_group->key.offset >> 1); | ||
1058 | ret = btrfs_next_leaf(root, path); | 1049 | ret = btrfs_next_leaf(root, path); |
1059 | if (ret == 0) | 1050 | if (ret == 0) |
1060 | continue; | 1051 | continue; |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index d378edf0964e..a9c7419615b9 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -30,9 +30,6 @@ struct tree_entry { | |||
30 | 30 | ||
31 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) | 31 | #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) |
32 | 32 | ||
33 | static LIST_HEAD(all_states); | ||
34 | spinlock_t state_lock = SPIN_LOCK_UNLOCKED; | ||
35 | |||
36 | void __init extent_map_init(void) | 33 | void __init extent_map_init(void) |
37 | { | 34 | { |
38 | extent_map_cache = kmem_cache_create("extent_map", | 35 | extent_map_cache = kmem_cache_create("extent_map", |
@@ -49,15 +46,6 @@ void __init extent_map_init(void) | |||
49 | 46 | ||
50 | void __exit extent_map_exit(void) | 47 | void __exit extent_map_exit(void) |
51 | { | 48 | { |
52 | while(!list_empty(&all_states)) { | ||
53 | struct extent_state *state; | ||
54 | struct list_head *cur = all_states.next; | ||
55 | state = list_entry(cur, struct extent_state, list); | ||
56 | printk("found leaked state %Lu %Lu state %d in_tree %d\n", | ||
57 | state->start, state->end, state->state, state->in_tree); | ||
58 | list_del(&state->list); | ||
59 | kfree(state); | ||
60 | } | ||
61 | if (extent_map_cache) | 49 | if (extent_map_cache) |
62 | kmem_cache_destroy(extent_map_cache); | 50 | kmem_cache_destroy(extent_map_cache); |
63 | if (extent_state_cache) | 51 | if (extent_state_cache) |
@@ -69,6 +57,7 @@ void extent_map_tree_init(struct extent_map_tree *tree, | |||
69 | { | 57 | { |
70 | tree->map.rb_node = NULL; | 58 | tree->map.rb_node = NULL; |
71 | tree->state.rb_node = NULL; | 59 | tree->state.rb_node = NULL; |
60 | tree->fill_delalloc = NULL; | ||
72 | rwlock_init(&tree->lock); | 61 | rwlock_init(&tree->lock); |
73 | tree->mapping = mapping; | 62 | tree->mapping = mapping; |
74 | } | 63 | } |
@@ -106,9 +95,6 @@ struct extent_state *alloc_extent_state(gfp_t mask) | |||
106 | state->in_tree = 0; | 95 | state->in_tree = 0; |
107 | atomic_set(&state->refs, 1); | 96 | atomic_set(&state->refs, 1); |
108 | init_waitqueue_head(&state->wq); | 97 | init_waitqueue_head(&state->wq); |
109 | spin_lock_irq(&state_lock); | ||
110 | list_add(&state->list, &all_states); | ||
111 | spin_unlock_irq(&state_lock); | ||
112 | return state; | 98 | return state; |
113 | } | 99 | } |
114 | EXPORT_SYMBOL(alloc_extent_state); | 100 | EXPORT_SYMBOL(alloc_extent_state); |
@@ -117,9 +103,6 @@ void free_extent_state(struct extent_state *state) | |||
117 | { | 103 | { |
118 | if (atomic_dec_and_test(&state->refs)) { | 104 | if (atomic_dec_and_test(&state->refs)) { |
119 | WARN_ON(state->in_tree); | 105 | WARN_ON(state->in_tree); |
120 | spin_lock_irq(&state_lock); | ||
121 | list_del_init(&state->list); | ||
122 | spin_unlock_irq(&state_lock); | ||
123 | kmem_cache_free(extent_state_cache, state); | 106 | kmem_cache_free(extent_state_cache, state); |
124 | } | 107 | } |
125 | } | 108 | } |
@@ -369,7 +352,7 @@ static int insert_state(struct extent_map_tree *tree, | |||
369 | if (node) { | 352 | if (node) { |
370 | struct extent_state *found; | 353 | struct extent_state *found; |
371 | found = rb_entry(node, struct extent_state, rb_node); | 354 | found = rb_entry(node, struct extent_state, rb_node); |
372 | printk("found node %Lu %Lu on insert of %Lu %Lu\n", found->start, found->end, start, end); | 355 | printk("found node %Lu %Lu on insert of %Lu %Lu\n", found->start, found->end, start, end); |
373 | free_extent_state(state); | 356 | free_extent_state(state); |
374 | return -EEXIST; | 357 | return -EEXIST; |
375 | } | 358 | } |
@@ -408,7 +391,7 @@ static int split_state(struct extent_map_tree *tree, struct extent_state *orig, | |||
408 | if (node) { | 391 | if (node) { |
409 | struct extent_state *found; | 392 | struct extent_state *found; |
410 | found = rb_entry(node, struct extent_state, rb_node); | 393 | found = rb_entry(node, struct extent_state, rb_node); |
411 | printk("found node %Lu %Lu on insert of %Lu %Lu\n", found->start, found->end, prealloc->start, prealloc->end); | 394 | printk("found node %Lu %Lu on insert of %Lu %Lu\n", found->start, found->end, prealloc->start, prealloc->end); |
412 | free_extent_state(prealloc); | 395 | free_extent_state(prealloc); |
413 | return -EEXIST; | 396 | return -EEXIST; |
414 | } | 397 | } |
@@ -792,10 +775,20 @@ int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, | |||
792 | } | 775 | } |
793 | EXPORT_SYMBOL(set_extent_dirty); | 776 | EXPORT_SYMBOL(set_extent_dirty); |
794 | 777 | ||
778 | int set_extent_delalloc(struct extent_map_tree *tree, u64 start, u64 end, | ||
779 | gfp_t mask) | ||
780 | { | ||
781 | return set_extent_bit(tree, start, end, | ||
782 | EXTENT_DELALLOC | EXTENT_DIRTY, 0, NULL, | ||
783 | mask); | ||
784 | } | ||
785 | EXPORT_SYMBOL(set_extent_delalloc); | ||
786 | |||
795 | int clear_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, | 787 | int clear_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, |
796 | gfp_t mask) | 788 | gfp_t mask) |
797 | { | 789 | { |
798 | return clear_extent_bit(tree, start, end, EXTENT_DIRTY, 0, 0, mask); | 790 | return clear_extent_bit(tree, start, end, |
791 | EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0, mask); | ||
799 | } | 792 | } |
800 | EXPORT_SYMBOL(clear_extent_dirty); | 793 | EXPORT_SYMBOL(clear_extent_dirty); |
801 | 794 | ||
@@ -922,6 +915,62 @@ int set_range_writeback(struct extent_map_tree *tree, u64 start, u64 end) | |||
922 | } | 915 | } |
923 | EXPORT_SYMBOL(set_range_writeback); | 916 | EXPORT_SYMBOL(set_range_writeback); |
924 | 917 | ||
918 | u64 find_lock_delalloc_range(struct extent_map_tree *tree, | ||
919 | u64 start, u64 lock_start, u64 *end, u64 max_bytes) | ||
920 | { | ||
921 | struct rb_node *node; | ||
922 | struct extent_state *state; | ||
923 | u64 cur_start = start; | ||
924 | u64 found = 0; | ||
925 | u64 total_bytes = 0; | ||
926 | |||
927 | write_lock_irq(&tree->lock); | ||
928 | /* | ||
929 | * this search will find all the extents that end after | ||
930 | * our range starts. | ||
931 | */ | ||
932 | search_again: | ||
933 | node = tree_search(&tree->state, cur_start); | ||
934 | if (!node || IS_ERR(node)) { | ||
935 | goto out; | ||
936 | } | ||
937 | |||
938 | while(1) { | ||
939 | state = rb_entry(node, struct extent_state, rb_node); | ||
940 | if (state->start != cur_start) { | ||
941 | goto out; | ||
942 | } | ||
943 | if (!(state->state & EXTENT_DELALLOC)) { | ||
944 | goto out; | ||
945 | } | ||
946 | if (state->start >= lock_start) { | ||
947 | if (state->state & EXTENT_LOCKED) { | ||
948 | DEFINE_WAIT(wait); | ||
949 | atomic_inc(&state->refs); | ||
950 | write_unlock_irq(&tree->lock); | ||
951 | schedule(); | ||
952 | write_lock_irq(&tree->lock); | ||
953 | finish_wait(&state->wq, &wait); | ||
954 | free_extent_state(state); | ||
955 | goto search_again; | ||
956 | } | ||
957 | state->state |= EXTENT_LOCKED; | ||
958 | } | ||
959 | found++; | ||
960 | *end = state->end; | ||
961 | cur_start = state->end + 1; | ||
962 | node = rb_next(node); | ||
963 | if (!node) | ||
964 | break; | ||
965 | total_bytes = state->end - state->start + 1; | ||
966 | if (total_bytes >= max_bytes) | ||
967 | break; | ||
968 | } | ||
969 | out: | ||
970 | write_unlock_irq(&tree->lock); | ||
971 | return found; | ||
972 | } | ||
973 | |||
925 | /* | 974 | /* |
926 | * helper function to lock both pages and extents in the tree. | 975 | * helper function to lock both pages and extents in the tree. |
927 | * pages must be locked first. | 976 | * pages must be locked first. |
@@ -1285,6 +1334,7 @@ int extent_read_full_page(struct extent_map_tree *tree, struct page *page, | |||
1285 | if (!PagePrivate(page)) { | 1334 | if (!PagePrivate(page)) { |
1286 | SetPagePrivate(page); | 1335 | SetPagePrivate(page); |
1287 | set_page_private(page, 1); | 1336 | set_page_private(page, 1); |
1337 | WARN_ON(!page->mapping->a_ops->invalidatepage); | ||
1288 | page_cache_get(page); | 1338 | page_cache_get(page); |
1289 | } | 1339 | } |
1290 | 1340 | ||
@@ -1384,7 +1434,10 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
1384 | size_t blocksize; | 1434 | size_t blocksize; |
1385 | loff_t i_size = i_size_read(inode); | 1435 | loff_t i_size = i_size_read(inode); |
1386 | unsigned long end_index = i_size >> PAGE_CACHE_SHIFT; | 1436 | unsigned long end_index = i_size >> PAGE_CACHE_SHIFT; |
1437 | u64 nr_delalloc; | ||
1438 | u64 delalloc_end; | ||
1387 | 1439 | ||
1440 | WARN_ON(!PageLocked(page)); | ||
1388 | if (page->index > end_index) { | 1441 | if (page->index > end_index) { |
1389 | clear_extent_dirty(tree, start, page_end, GFP_NOFS); | 1442 | clear_extent_dirty(tree, start, page_end, GFP_NOFS); |
1390 | unlock_page(page); | 1443 | unlock_page(page); |
@@ -1400,11 +1453,34 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
1400 | if (!PagePrivate(page)) { | 1453 | if (!PagePrivate(page)) { |
1401 | SetPagePrivate(page); | 1454 | SetPagePrivate(page); |
1402 | set_page_private(page, 1); | 1455 | set_page_private(page, 1); |
1456 | WARN_ON(!page->mapping->a_ops->invalidatepage); | ||
1403 | page_cache_get(page); | 1457 | page_cache_get(page); |
1404 | } | 1458 | } |
1405 | 1459 | ||
1406 | end = page_end; | ||
1407 | lock_extent(tree, start, page_end, GFP_NOFS); | 1460 | lock_extent(tree, start, page_end, GFP_NOFS); |
1461 | nr_delalloc = find_lock_delalloc_range(tree, start, page_end + 1, | ||
1462 | &delalloc_end, | ||
1463 | 128 * 1024 * 1024); | ||
1464 | if (nr_delalloc) { | ||
1465 | tree->fill_delalloc(inode, start, delalloc_end); | ||
1466 | if (delalloc_end >= page_end + 1) { | ||
1467 | clear_extent_bit(tree, page_end + 1, delalloc_end, | ||
1468 | EXTENT_LOCKED | EXTENT_DELALLOC, | ||
1469 | 1, 0, GFP_NOFS); | ||
1470 | } | ||
1471 | clear_extent_bit(tree, start, page_end, EXTENT_DELALLOC, | ||
1472 | 0, 0, GFP_NOFS); | ||
1473 | if (test_range_bit(tree, start, page_end, EXTENT_DELALLOC, 0)) { | ||
1474 | printk("found delalloc bits after clear extent_bit\n"); | ||
1475 | } | ||
1476 | } else if (test_range_bit(tree, start, page_end, EXTENT_DELALLOC, 0)) { | ||
1477 | printk("found delalloc bits after find_delalloc_range returns 0\n"); | ||
1478 | } | ||
1479 | |||
1480 | end = page_end; | ||
1481 | if (test_range_bit(tree, start, page_end, EXTENT_DELALLOC, 0)) { | ||
1482 | printk("found delalloc bits after lock_extent\n"); | ||
1483 | } | ||
1408 | 1484 | ||
1409 | if (last_byte <= start) { | 1485 | if (last_byte <= start) { |
1410 | clear_extent_dirty(tree, start, page_end, GFP_NOFS); | 1486 | clear_extent_dirty(tree, start, page_end, GFP_NOFS); |
@@ -1419,7 +1495,7 @@ int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | |||
1419 | clear_extent_dirty(tree, cur, page_end, GFP_NOFS); | 1495 | clear_extent_dirty(tree, cur, page_end, GFP_NOFS); |
1420 | break; | 1496 | break; |
1421 | } | 1497 | } |
1422 | em = get_extent(inode, page, page_offset, cur, end, 1); | 1498 | em = get_extent(inode, page, page_offset, cur, end, 0); |
1423 | if (IS_ERR(em) || !em) { | 1499 | if (IS_ERR(em) || !em) { |
1424 | SetPageError(page); | 1500 | SetPageError(page); |
1425 | break; | 1501 | break; |
@@ -1507,6 +1583,7 @@ int extent_commit_write(struct extent_map_tree *tree, | |||
1507 | if (!PagePrivate(page)) { | 1583 | if (!PagePrivate(page)) { |
1508 | SetPagePrivate(page); | 1584 | SetPagePrivate(page); |
1509 | set_page_private(page, 1); | 1585 | set_page_private(page, 1); |
1586 | WARN_ON(!page->mapping->a_ops->invalidatepage); | ||
1510 | page_cache_get(page); | 1587 | page_cache_get(page); |
1511 | } | 1588 | } |
1512 | 1589 | ||
@@ -1543,6 +1620,7 @@ int extent_prepare_write(struct extent_map_tree *tree, | |||
1543 | if (!PagePrivate(page)) { | 1620 | if (!PagePrivate(page)) { |
1544 | SetPagePrivate(page); | 1621 | SetPagePrivate(page); |
1545 | set_page_private(page, 1); | 1622 | set_page_private(page, 1); |
1623 | WARN_ON(!page->mapping->a_ops->invalidatepage); | ||
1546 | page_cache_get(page); | 1624 | page_cache_get(page); |
1547 | } | 1625 | } |
1548 | block_start = (page_start + from) & ~((u64)blocksize - 1); | 1626 | block_start = (page_start + from) & ~((u64)blocksize - 1); |
@@ -1628,29 +1706,28 @@ int try_release_extent_mapping(struct extent_map_tree *tree, struct page *page) | |||
1628 | u64 start = page->index << PAGE_CACHE_SHIFT; | 1706 | u64 start = page->index << PAGE_CACHE_SHIFT; |
1629 | u64 end = start + PAGE_CACHE_SIZE - 1; | 1707 | u64 end = start + PAGE_CACHE_SIZE - 1; |
1630 | u64 orig_start = start; | 1708 | u64 orig_start = start; |
1709 | int ret = 1; | ||
1631 | 1710 | ||
1632 | while (start <= end) { | 1711 | while (start <= end) { |
1633 | em = lookup_extent_mapping(tree, start, end); | 1712 | em = lookup_extent_mapping(tree, start, end); |
1634 | if (!em || IS_ERR(em)) | 1713 | if (!em || IS_ERR(em)) |
1635 | break; | 1714 | break; |
1636 | if (test_range_bit(tree, em->start, em->end, | 1715 | if (!test_range_bit(tree, em->start, em->end, |
1637 | EXTENT_LOCKED, 0)) { | 1716 | EXTENT_LOCKED, 0)) { |
1717 | remove_extent_mapping(tree, em); | ||
1718 | /* once for the rb tree */ | ||
1638 | free_extent_map(em); | 1719 | free_extent_map(em); |
1639 | start = em->end + 1; | ||
1640 | printk("range still locked %Lu %Lu\n", em->start, em->end); | ||
1641 | break; | ||
1642 | } | 1720 | } |
1643 | remove_extent_mapping(tree, em); | ||
1644 | start = em->end + 1; | 1721 | start = em->end + 1; |
1645 | /* once for the rb tree */ | ||
1646 | free_extent_map(em); | ||
1647 | /* once for us */ | 1722 | /* once for us */ |
1648 | free_extent_map(em); | 1723 | free_extent_map(em); |
1649 | } | 1724 | } |
1650 | WARN_ON(test_range_bit(tree, orig_start, end, EXTENT_WRITEBACK, 0)); | 1725 | if (test_range_bit(tree, orig_start, end, EXTENT_LOCKED, 0)) |
1651 | clear_extent_bit(tree, orig_start, end, EXTENT_UPTODATE, | 1726 | ret = 0; |
1652 | 1, 1, GFP_NOFS); | 1727 | else |
1653 | return 1; | 1728 | clear_extent_bit(tree, orig_start, end, EXTENT_UPTODATE, |
1729 | 1, 1, GFP_NOFS); | ||
1730 | return ret; | ||
1654 | } | 1731 | } |
1655 | EXPORT_SYMBOL(try_release_extent_mapping); | 1732 | EXPORT_SYMBOL(try_release_extent_mapping); |
1656 | 1733 | ||
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index 108944aab4bd..e91a2e9619ee 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
@@ -11,6 +11,7 @@ struct extent_map_tree { | |||
11 | struct rb_root state; | 11 | struct rb_root state; |
12 | struct address_space *mapping; | 12 | struct address_space *mapping; |
13 | rwlock_t lock; | 13 | rwlock_t lock; |
14 | int (*fill_delalloc)(struct inode *inode, u64 start, u64 end); | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | /* note, this must start with the same fields as fs/extent_map.c:tree_entry */ | 17 | /* note, this must start with the same fields as fs/extent_map.c:tree_entry */ |
@@ -74,6 +75,8 @@ int set_extent_new(struct extent_map_tree *tree, u64 start, u64 end, | |||
74 | gfp_t mask); | 75 | gfp_t mask); |
75 | int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, | 76 | int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, |
76 | gfp_t mask); | 77 | gfp_t mask); |
78 | int set_extent_delalloc(struct extent_map_tree *tree, u64 start, u64 end, | ||
79 | gfp_t mask); | ||
77 | int extent_invalidatepage(struct extent_map_tree *tree, | 80 | int extent_invalidatepage(struct extent_map_tree *tree, |
78 | struct page *page, unsigned long offset); | 81 | struct page *page, unsigned long offset); |
79 | int extent_write_full_page(struct extent_map_tree *tree, struct page *page, | 82 | int extent_write_full_page(struct extent_map_tree *tree, struct page *page, |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 71a481894ab6..d3d39e4a2797 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -143,7 +143,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
143 | struct inode *inode = file->f_path.dentry->d_inode; | 143 | struct inode *inode = file->f_path.dentry->d_inode; |
144 | struct extent_map *em; | 144 | struct extent_map *em; |
145 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 145 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
146 | struct btrfs_key ins; | ||
147 | u64 hint_block; | 146 | u64 hint_block; |
148 | u64 num_blocks; | 147 | u64 num_blocks; |
149 | u64 start_pos; | 148 | u64 start_pos; |
@@ -162,6 +161,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
162 | inode->i_blkbits; | 161 | inode->i_blkbits; |
163 | 162 | ||
164 | end_of_last_block = start_pos + (num_blocks << inode->i_blkbits) - 1; | 163 | end_of_last_block = start_pos + (num_blocks << inode->i_blkbits) - 1; |
164 | lock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS); | ||
165 | mutex_lock(&root->fs_info->fs_mutex); | 165 | mutex_lock(&root->fs_info->fs_mutex); |
166 | trans = btrfs_start_transaction(root, 1); | 166 | trans = btrfs_start_transaction(root, 1); |
167 | if (!trans) { | 167 | if (!trans) { |
@@ -179,16 +179,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
179 | 179 | ||
180 | /* FIXME...EIEIO, ENOSPC and more */ | 180 | /* FIXME...EIEIO, ENOSPC and more */ |
181 | 181 | ||
182 | /* step one, delete the existing extents in this range */ | ||
183 | /* FIXME blocksize != pagesize */ | ||
184 | if (start_pos < inode->i_size) { | ||
185 | err = btrfs_drop_extents(trans, root, inode, | ||
186 | start_pos, (pos + write_bytes + root->blocksize -1) & | ||
187 | ~((u64)root->blocksize - 1), &hint_block); | ||
188 | if (err) | ||
189 | goto failed; | ||
190 | } | ||
191 | |||
192 | /* insert any holes we need to create */ | 182 | /* insert any holes we need to create */ |
193 | if (inode->i_size < start_pos) { | 183 | if (inode->i_size < start_pos) { |
194 | u64 last_pos_in_file; | 184 | u64 last_pos_in_file; |
@@ -213,29 +203,28 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
213 | */ | 203 | */ |
214 | if (isize >= PAGE_CACHE_SIZE || pos + write_bytes < inode->i_size || | 204 | if (isize >= PAGE_CACHE_SIZE || pos + write_bytes < inode->i_size || |
215 | pos + write_bytes - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) { | 205 | pos + write_bytes - start_pos > BTRFS_MAX_INLINE_DATA_SIZE(root)) { |
216 | err = btrfs_alloc_extent(trans, root, inode->i_ino, | 206 | u64 last_end; |
217 | num_blocks, 0, hint_block, (u64)-1, | ||
218 | &ins, 1); | ||
219 | BUG_ON(err); | ||
220 | err = btrfs_insert_file_extent(trans, root, inode->i_ino, | ||
221 | start_pos, ins.objectid, ins.offset, | ||
222 | ins.offset); | ||
223 | BUG_ON(err); | ||
224 | em->start = start_pos; | ||
225 | em->end = end_of_last_block; | ||
226 | em->block_start = ins.objectid << inode->i_blkbits; | ||
227 | em->block_end = em->block_start + | ||
228 | (ins.offset << inode->i_blkbits) - 1; | ||
229 | set_extent_dirty(em_tree, start_pos, end_of_last_block, | ||
230 | GFP_NOFS); | ||
231 | err = add_extent_mapping(em_tree, em); | ||
232 | for (i = 0; i < num_pages; i++) { | 207 | for (i = 0; i < num_pages; i++) { |
233 | struct page *p = pages[i]; | 208 | struct page *p = pages[i]; |
234 | SetPageUptodate(p); | 209 | SetPageUptodate(p); |
235 | __set_page_dirty_nobuffers(p); | 210 | set_page_dirty(p); |
236 | } | 211 | } |
212 | last_end = pages[num_pages -1]->index << PAGE_CACHE_SHIFT; | ||
213 | last_end += PAGE_CACHE_SIZE - 1; | ||
214 | set_extent_delalloc(em_tree, start_pos, end_of_last_block, | ||
215 | GFP_NOFS); | ||
237 | } else { | 216 | } else { |
238 | struct page *p = pages[0]; | 217 | struct page *p = pages[0]; |
218 | /* step one, delete the existing extents in this range */ | ||
219 | /* FIXME blocksize != pagesize */ | ||
220 | if (start_pos < inode->i_size) { | ||
221 | err = btrfs_drop_extents(trans, root, inode, start_pos, | ||
222 | (pos + write_bytes + root->blocksize -1) & | ||
223 | ~((u64)root->blocksize - 1), &hint_block); | ||
224 | if (err) | ||
225 | goto failed; | ||
226 | } | ||
227 | |||
239 | err = insert_inline_extent(trans, root, inode, start_pos, | 228 | err = insert_inline_extent(trans, root, inode, start_pos, |
240 | end_pos - start_pos, p, 0); | 229 | end_pos - start_pos, p, 0); |
241 | BUG_ON(err); | 230 | BUG_ON(err); |
@@ -253,6 +242,7 @@ failed: | |||
253 | err = btrfs_end_transaction(trans, root); | 242 | err = btrfs_end_transaction(trans, root); |
254 | out_unlock: | 243 | out_unlock: |
255 | mutex_unlock(&root->fs_info->fs_mutex); | 244 | mutex_unlock(&root->fs_info->fs_mutex); |
245 | unlock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS); | ||
256 | free_extent_map(em); | 246 | free_extent_map(em); |
257 | return err; | 247 | return err; |
258 | } | 248 | } |
@@ -531,7 +521,7 @@ static int prepare_pages(struct btrfs_root *root, | |||
531 | u64 num_blocks; | 521 | u64 num_blocks; |
532 | u64 start_pos; | 522 | u64 start_pos; |
533 | 523 | ||
534 | start_pos = pos & ~((u64)PAGE_CACHE_SIZE - 1); | 524 | start_pos = pos & ~((u64)root->blocksize - 1); |
535 | num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >> | 525 | num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >> |
536 | inode->i_blkbits; | 526 | inode->i_blkbits; |
537 | 527 | ||
@@ -548,8 +538,10 @@ static int prepare_pages(struct btrfs_root *root, | |||
548 | if (!PagePrivate(pages[i])) { | 538 | if (!PagePrivate(pages[i])) { |
549 | SetPagePrivate(pages[i]); | 539 | SetPagePrivate(pages[i]); |
550 | set_page_private(pages[i], 1); | 540 | set_page_private(pages[i], 1); |
541 | WARN_ON(!pages[i]->mapping->a_ops->invalidatepage); | ||
551 | page_cache_get(pages[i]); | 542 | page_cache_get(pages[i]); |
552 | } | 543 | } |
544 | WARN_ON(!PageLocked(pages[i])); | ||
553 | } | 545 | } |
554 | return 0; | 546 | return 0; |
555 | } | 547 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fd4cb65fcf1f..dc181089aa74 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -70,6 +70,40 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { | |||
70 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, | 70 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static int run_delalloc_range(struct inode *inode, u64 start, u64 end) | ||
74 | { | ||
75 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
76 | struct btrfs_trans_handle *trans; | ||
77 | struct btrfs_key ins; | ||
78 | u64 alloc_hint = 0; | ||
79 | u64 num_blocks; | ||
80 | int ret; | ||
81 | u64 blocksize = 1 << inode->i_blkbits; | ||
82 | |||
83 | mutex_lock(&root->fs_info->fs_mutex); | ||
84 | trans = btrfs_start_transaction(root, 1); | ||
85 | btrfs_set_trans_block_group(trans, inode); | ||
86 | BUG_ON(!trans); | ||
87 | num_blocks = (end - start + blocksize) & ~(blocksize - 1); | ||
88 | ret = btrfs_drop_extents(trans, root, inode, | ||
89 | start, start + num_blocks, &alloc_hint); | ||
90 | num_blocks = num_blocks >> inode->i_blkbits; | ||
91 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, num_blocks, 0, | ||
92 | alloc_hint, (u64)-1, &ins, 1); | ||
93 | if (ret) { | ||
94 | WARN_ON(1); | ||
95 | goto out; | ||
96 | } | ||
97 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | ||
98 | start, ins.objectid, ins.offset, | ||
99 | ins.offset); | ||
100 | out: | ||
101 | btrfs_end_transaction(trans, root); | ||
102 | mutex_unlock(&root->fs_info->fs_mutex); | ||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | |||
73 | void btrfs_read_locked_inode(struct inode *inode) | 107 | void btrfs_read_locked_inode(struct inode *inode) |
74 | { | 108 | { |
75 | struct btrfs_path *path; | 109 | struct btrfs_path *path; |
@@ -121,8 +155,7 @@ void btrfs_read_locked_inode(struct inode *inode) | |||
121 | switch (inode->i_mode & S_IFMT) { | 155 | switch (inode->i_mode & S_IFMT) { |
122 | case S_IFREG: | 156 | case S_IFREG: |
123 | inode->i_mapping->a_ops = &btrfs_aops; | 157 | inode->i_mapping->a_ops = &btrfs_aops; |
124 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, | 158 | BTRFS_I(inode)->extent_tree.fill_delalloc = run_delalloc_range; |
125 | inode->i_mapping, GFP_NOFS); | ||
126 | inode->i_fop = &btrfs_file_operations; | 159 | inode->i_fop = &btrfs_file_operations; |
127 | inode->i_op = &btrfs_file_inode_operations; | 160 | inode->i_op = &btrfs_file_inode_operations; |
128 | break; | 161 | break; |
@@ -450,11 +483,17 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
450 | BUG_ON(ret); | 483 | BUG_ON(ret); |
451 | } | 484 | } |
452 | if (item_end < inode->i_size) { | 485 | if (item_end < inode->i_size) { |
453 | if (found_type) { | 486 | if (found_type == BTRFS_DIR_ITEM_KEY) { |
454 | btrfs_set_key_type(&key, found_type - 1); | 487 | found_type = BTRFS_INODE_ITEM_KEY; |
455 | continue; | 488 | } else if (found_type == BTRFS_EXTENT_ITEM_KEY) { |
489 | found_type = BTRFS_CSUM_ITEM_KEY; | ||
490 | } else if (found_type) { | ||
491 | found_type--; | ||
492 | } else { | ||
493 | break; | ||
456 | } | 494 | } |
457 | break; | 495 | btrfs_set_key_type(&key, found_type - 1); |
496 | continue; | ||
458 | } | 497 | } |
459 | if (btrfs_disk_key_offset(found_key) >= inode->i_size) | 498 | if (btrfs_disk_key_offset(found_key) >= inode->i_size) |
460 | del_item = 1; | 499 | del_item = 1; |
@@ -514,47 +553,34 @@ error: | |||
514 | return ret; | 553 | return ret; |
515 | } | 554 | } |
516 | 555 | ||
517 | static int btrfs_cow_one_page(struct btrfs_trans_handle *trans, | 556 | static int btrfs_cow_one_page(struct inode *inode, struct page *page, |
518 | struct inode *inode, struct page *page, | ||
519 | size_t zero_start) | 557 | size_t zero_start) |
520 | { | 558 | { |
521 | char *kaddr; | 559 | char *kaddr; |
522 | int ret = 0; | 560 | int ret = 0; |
523 | struct btrfs_root *root = BTRFS_I(inode)->root; | 561 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
524 | u64 alloc_hint = 0; | ||
525 | u64 page_start = page->index << PAGE_CACHE_SHIFT; | 562 | u64 page_start = page->index << PAGE_CACHE_SHIFT; |
526 | struct btrfs_key ins; | 563 | u64 page_end = page_start + PAGE_CACHE_SIZE - 1; |
527 | 564 | ||
528 | if (!PagePrivate(page)) { | 565 | if (!PagePrivate(page)) { |
529 | SetPagePrivate(page); | 566 | SetPagePrivate(page); |
530 | set_page_private(page, 1); | 567 | set_page_private(page, 1); |
568 | WARN_ON(!page->mapping->a_ops->invalidatepage); | ||
531 | page_cache_get(page); | 569 | page_cache_get(page); |
532 | } | 570 | } |
533 | 571 | ||
534 | btrfs_set_trans_block_group(trans, inode); | 572 | lock_extent(em_tree, page_start, page_end, GFP_NOFS); |
535 | 573 | set_extent_delalloc(&BTRFS_I(inode)->extent_tree, page_start, | |
536 | ret = btrfs_drop_extents(trans, root, inode, | 574 | page_end, GFP_NOFS); |
537 | page_start, page_start + PAGE_CACHE_SIZE, | ||
538 | &alloc_hint); | ||
539 | if (ret) | ||
540 | goto out; | ||
541 | ret = btrfs_alloc_extent(trans, root, inode->i_ino, 1, 0, | ||
542 | alloc_hint, (u64)-1, &ins, 1); | ||
543 | if (ret) | ||
544 | goto out; | ||
545 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | ||
546 | page_start, ins.objectid, 1, 1); | ||
547 | if (ret) | ||
548 | goto out; | ||
549 | SetPageChecked(page); | ||
550 | kaddr = kmap(page); | ||
551 | if (zero_start != PAGE_CACHE_SIZE) { | 575 | if (zero_start != PAGE_CACHE_SIZE) { |
576 | kaddr = kmap(page); | ||
552 | memset(kaddr + zero_start, 0, PAGE_CACHE_SIZE - zero_start); | 577 | memset(kaddr + zero_start, 0, PAGE_CACHE_SIZE - zero_start); |
553 | flush_dcache_page(page); | 578 | flush_dcache_page(page); |
579 | kunmap(page); | ||
554 | } | 580 | } |
555 | kunmap(page); | 581 | set_page_dirty(page); |
582 | unlock_extent(em_tree, page_start, page_end, GFP_NOFS); | ||
556 | 583 | ||
557 | out: | ||
558 | return ret; | 584 | return ret; |
559 | } | 585 | } |
560 | 586 | ||
@@ -565,8 +591,6 @@ out: | |||
565 | static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | 591 | static int btrfs_truncate_page(struct address_space *mapping, loff_t from) |
566 | { | 592 | { |
567 | struct inode *inode = mapping->host; | 593 | struct inode *inode = mapping->host; |
568 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
569 | struct btrfs_trans_handle *trans; | ||
570 | unsigned blocksize = 1 << inode->i_blkbits; | 594 | unsigned blocksize = 1 << inode->i_blkbits; |
571 | pgoff_t index = from >> PAGE_CACHE_SHIFT; | 595 | pgoff_t index = from >> PAGE_CACHE_SHIFT; |
572 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | 596 | unsigned offset = from & (PAGE_CACHE_SIZE-1); |
@@ -591,21 +615,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | |||
591 | } | 615 | } |
592 | page_start = page->index << PAGE_CACHE_SHIFT; | 616 | page_start = page->index << PAGE_CACHE_SHIFT; |
593 | 617 | ||
594 | mutex_lock(&root->fs_info->fs_mutex); | 618 | ret = btrfs_cow_one_page(inode, page, offset); |
595 | trans = btrfs_start_transaction(root, 1); | ||
596 | ret = btrfs_cow_one_page(trans, inode, page, offset); | ||
597 | if (!ret) { | ||
598 | char *kaddr = kmap(page); | ||
599 | ret = btrfs_csum_file_block(trans, root, inode->i_ino, | ||
600 | page_start, kaddr, PAGE_CACHE_SIZE); | ||
601 | kunmap(page); | ||
602 | } | ||
603 | set_extent_dirty(&BTRFS_I(inode)->extent_tree, | ||
604 | page_start, page_start + PAGE_CACHE_SIZE - 1, | ||
605 | GFP_NOFS); | ||
606 | set_page_dirty(page); | ||
607 | btrfs_end_transaction(trans, root); | ||
608 | mutex_unlock(&root->fs_info->fs_mutex); | ||
609 | 619 | ||
610 | unlock_page(page); | 620 | unlock_page(page); |
611 | page_cache_release(page); | 621 | page_cache_release(page); |
@@ -757,6 +767,8 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p) | |||
757 | struct btrfs_iget_args *args = p; | 767 | struct btrfs_iget_args *args = p; |
758 | inode->i_ino = args->ino; | 768 | inode->i_ino = args->ino; |
759 | BTRFS_I(inode)->root = args->root; | 769 | BTRFS_I(inode)->root = args->root; |
770 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, | ||
771 | inode->i_mapping, GFP_NOFS); | ||
760 | return 0; | 772 | return 0; |
761 | } | 773 | } |
762 | 774 | ||
@@ -968,7 +980,10 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
968 | if (!inode) | 980 | if (!inode) |
969 | return ERR_PTR(-ENOMEM); | 981 | return ERR_PTR(-ENOMEM); |
970 | 982 | ||
983 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, | ||
984 | inode->i_mapping, GFP_NOFS); | ||
971 | BTRFS_I(inode)->root = root; | 985 | BTRFS_I(inode)->root = root; |
986 | |||
972 | if (mode & S_IFDIR) | 987 | if (mode & S_IFDIR) |
973 | owner = 0; | 988 | owner = 0; |
974 | else | 989 | else |
@@ -1128,6 +1143,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
1128 | inode->i_op = &btrfs_file_inode_operations; | 1143 | inode->i_op = &btrfs_file_inode_operations; |
1129 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, | 1144 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, |
1130 | inode->i_mapping, GFP_NOFS); | 1145 | inode->i_mapping, GFP_NOFS); |
1146 | BTRFS_I(inode)->extent_tree.fill_delalloc = run_delalloc_range; | ||
1131 | } | 1147 | } |
1132 | dir->i_sb->s_dirt = 1; | 1148 | dir->i_sb->s_dirt = 1; |
1133 | btrfs_update_inode_block_group(trans, inode); | 1149 | btrfs_update_inode_block_group(trans, inode); |
@@ -1344,9 +1360,11 @@ again: | |||
1344 | extent_end = extent_start + | 1360 | extent_end = extent_start + |
1345 | (btrfs_file_extent_num_blocks(item) << inode->i_blkbits); | 1361 | (btrfs_file_extent_num_blocks(item) << inode->i_blkbits); |
1346 | err = 0; | 1362 | err = 0; |
1347 | if (start < extent_start || start > extent_end) { | 1363 | if (start < extent_start || start >= extent_end) { |
1348 | em->start = start; | 1364 | em->start = start; |
1349 | if (start < extent_start) { | 1365 | if (start < extent_start) { |
1366 | if (end < extent_start) | ||
1367 | goto not_found; | ||
1350 | em->end = extent_end - 1; | 1368 | em->end = extent_end - 1; |
1351 | } else { | 1369 | } else { |
1352 | em->end = end; | 1370 | em->end = end; |
@@ -1375,9 +1393,11 @@ again: | |||
1375 | size = btrfs_file_extent_inline_len(leaf->items + | 1393 | size = btrfs_file_extent_inline_len(leaf->items + |
1376 | path->slots[0]); | 1394 | path->slots[0]); |
1377 | extent_end = extent_start + size; | 1395 | extent_end = extent_start + size; |
1378 | if (start < extent_start || start > extent_end) { | 1396 | if (start < extent_start || start >= extent_end) { |
1379 | em->start = start; | 1397 | em->start = start; |
1380 | if (start < extent_start) { | 1398 | if (start < extent_start) { |
1399 | if (end < extent_start) | ||
1400 | goto not_found; | ||
1381 | em->end = extent_end - 1; | 1401 | em->end = extent_end - 1; |
1382 | } else { | 1402 | } else { |
1383 | em->end = end; | 1403 | em->end = end; |
@@ -1412,8 +1432,7 @@ not_found_em: | |||
1412 | insert: | 1432 | insert: |
1413 | btrfs_release_path(root, path); | 1433 | btrfs_release_path(root, path); |
1414 | if (em->start > start || em->end < start) { | 1434 | if (em->start > start || em->end < start) { |
1415 | printk("bad extent! %Lu %Lu start %Lu end %Lu\n", em->start, em->end, start, end); | 1435 | printk("bad extent! em: [%Lu %Lu] passed [%Lu %Lu]\n", em->start, em->end, start, end); |
1416 | WARN_ON(1); | ||
1417 | err = -EIO; | 1436 | err = -EIO; |
1418 | goto out; | 1437 | goto out; |
1419 | } | 1438 | } |
@@ -1648,6 +1667,13 @@ int btrfs_readpage(struct file *file, struct page *page) | |||
1648 | static int btrfs_writepage(struct page *page, struct writeback_control *wbc) | 1667 | static int btrfs_writepage(struct page *page, struct writeback_control *wbc) |
1649 | { | 1668 | { |
1650 | struct extent_map_tree *tree; | 1669 | struct extent_map_tree *tree; |
1670 | |||
1671 | |||
1672 | if (current->flags & PF_MEMALLOC) { | ||
1673 | redirty_page_for_writepage(wbc, page); | ||
1674 | unlock_page(page); | ||
1675 | return 0; | ||
1676 | } | ||
1651 | tree = &BTRFS_I(page->mapping->host)->extent_tree; | 1677 | tree = &BTRFS_I(page->mapping->host)->extent_tree; |
1652 | return extent_write_full_page(tree, page, btrfs_get_extent, wbc); | 1678 | return extent_write_full_page(tree, page, btrfs_get_extent, wbc); |
1653 | } | 1679 | } |
@@ -1698,8 +1724,6 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) | |||
1698 | int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 1724 | int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) |
1699 | { | 1725 | { |
1700 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | 1726 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; |
1701 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1702 | struct btrfs_trans_handle *trans; | ||
1703 | unsigned long end; | 1727 | unsigned long end; |
1704 | loff_t size; | 1728 | loff_t size; |
1705 | int ret = -EINVAL; | 1729 | int ret = -EINVAL; |
@@ -1722,15 +1746,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
1722 | else | 1746 | else |
1723 | end = PAGE_CACHE_SIZE; | 1747 | end = PAGE_CACHE_SIZE; |
1724 | 1748 | ||
1725 | mutex_lock(&root->fs_info->fs_mutex); | 1749 | ret = btrfs_cow_one_page(inode, page, end); |
1726 | trans = btrfs_start_transaction(root, 1); | ||
1727 | ret = btrfs_cow_one_page(trans, inode, page, end); | ||
1728 | btrfs_end_transaction(trans, root); | ||
1729 | mutex_unlock(&root->fs_info->fs_mutex); | ||
1730 | set_extent_dirty(&BTRFS_I(inode)->extent_tree, | ||
1731 | page_start, page_start + PAGE_CACHE_SIZE - 1, | ||
1732 | GFP_NOFS); | ||
1733 | set_page_dirty(page); | ||
1734 | 1750 | ||
1735 | out_unlock: | 1751 | out_unlock: |
1736 | unlock_page(page); | 1752 | unlock_page(page); |
@@ -2264,6 +2280,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
2264 | inode->i_op = &btrfs_file_inode_operations; | 2280 | inode->i_op = &btrfs_file_inode_operations; |
2265 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, | 2281 | extent_map_tree_init(&BTRFS_I(inode)->extent_tree, |
2266 | inode->i_mapping, GFP_NOFS); | 2282 | inode->i_mapping, GFP_NOFS); |
2283 | BTRFS_I(inode)->extent_tree.fill_delalloc = run_delalloc_range; | ||
2267 | } | 2284 | } |
2268 | dir->i_sb->s_dirt = 1; | 2285 | dir->i_sb->s_dirt = 1; |
2269 | btrfs_update_inode_block_group(trans, inode); | 2286 | btrfs_update_inode_block_group(trans, inode); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 7b7c32c73a2c..7da95538745f 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -83,6 +83,7 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | |||
83 | bi->location.offset = 0; | 83 | bi->location.offset = 0; |
84 | bi->location.flags = 0; | 84 | bi->location.flags = 0; |
85 | bi->root = tree_root; | 85 | bi->root = tree_root; |
86 | |||
86 | btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); | 87 | btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); |
87 | 88 | ||
88 | if (!inode) { | 89 | if (!inode) { |