diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-18 16:15:28 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-18 16:15:28 -0400 |
commit | a429e51371eee3c989160c003ee40bc3947c6a76 (patch) | |
tree | 863b55de8823be579264260a51407cd90aac103d /fs/btrfs | |
parent | 70b2befd0c8a4064715d8b340270650cc9d15af8 (diff) |
Btrfs: working file_write, reorganized key flags
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 30 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 52 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 70 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 4 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 66 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 2 | ||||
-rw-r--r-- | fs/btrfs/super.c | 118 |
7 files changed, 167 insertions, 175 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 5c160c236773..4efcd1bd63e5 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -893,7 +893,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
893 | } | 893 | } |
894 | 894 | ||
895 | left_nritems = btrfs_header_nritems(&left->header); | 895 | left_nritems = btrfs_header_nritems(&left->header); |
896 | for (i = left_nritems - 1; i >= 0; i--) { | 896 | if (left_nritems == 0) { |
897 | btrfs_block_release(root, right_buf); | ||
898 | return 1; | ||
899 | } | ||
900 | for (i = left_nritems - 1; i >= 1; i--) { | ||
897 | item = left->items + i; | 901 | item = left->items + i; |
898 | if (path->slots[0] == i) | 902 | if (path->slots[0] == i) |
899 | push_space += data_size + sizeof(*item); | 903 | push_space += data_size + sizeof(*item); |
@@ -907,6 +911,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
907 | btrfs_block_release(root, right_buf); | 911 | btrfs_block_release(root, right_buf); |
908 | return 1; | 912 | return 1; |
909 | } | 913 | } |
914 | if (push_items == left_nritems) | ||
915 | WARN_ON(1); | ||
910 | right_nritems = btrfs_header_nritems(&right->header); | 916 | right_nritems = btrfs_header_nritems(&right->header); |
911 | /* push left to right */ | 917 | /* push left to right */ |
912 | push_space = btrfs_item_end(left->items + left_nritems - push_items); | 918 | push_space = btrfs_item_end(left->items + left_nritems - push_items); |
@@ -943,6 +949,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
943 | 949 | ||
944 | btrfs_mark_buffer_dirty(left_buf); | 950 | btrfs_mark_buffer_dirty(left_buf); |
945 | btrfs_mark_buffer_dirty(right_buf); | 951 | btrfs_mark_buffer_dirty(right_buf); |
952 | |||
946 | btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key, | 953 | btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key, |
947 | &right->items[0].key, sizeof(struct btrfs_disk_key)); | 954 | &right->items[0].key, sizeof(struct btrfs_disk_key)); |
948 | btrfs_mark_buffer_dirty(upper); | 955 | btrfs_mark_buffer_dirty(upper); |
@@ -1004,7 +1011,12 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1004 | return 1; | 1011 | return 1; |
1005 | } | 1012 | } |
1006 | 1013 | ||
1007 | for (i = 0; i < btrfs_header_nritems(&right->header); i++) { | 1014 | if (btrfs_header_nritems(&right->header) == 0) { |
1015 | btrfs_block_release(root, t); | ||
1016 | return 1; | ||
1017 | } | ||
1018 | |||
1019 | for (i = 0; i < btrfs_header_nritems(&right->header) - 1; i++) { | ||
1008 | item = right->items + i; | 1020 | item = right->items + i; |
1009 | if (path->slots[0] == i) | 1021 | if (path->slots[0] == i) |
1010 | push_space += data_size + sizeof(*item); | 1022 | push_space += data_size + sizeof(*item); |
@@ -1018,6 +1030,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1018 | btrfs_block_release(root, t); | 1030 | btrfs_block_release(root, t); |
1019 | return 1; | 1031 | return 1; |
1020 | } | 1032 | } |
1033 | if (push_items == btrfs_header_nritems(&right->header)) | ||
1034 | WARN_ON(1); | ||
1021 | /* push data from right to left */ | 1035 | /* push data from right to left */ |
1022 | btrfs_memcpy(root, left, left->items + | 1036 | btrfs_memcpy(root, left, left->items + |
1023 | btrfs_header_nritems(&left->header), | 1037 | btrfs_header_nritems(&left->header), |
@@ -1064,7 +1078,6 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1064 | 1078 | ||
1065 | btrfs_mark_buffer_dirty(t); | 1079 | btrfs_mark_buffer_dirty(t); |
1066 | btrfs_mark_buffer_dirty(right_buf); | 1080 | btrfs_mark_buffer_dirty(right_buf); |
1067 | |||
1068 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); | 1081 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); |
1069 | if (wret) | 1082 | if (wret) |
1070 | ret = wret; | 1083 | ret = wret; |
@@ -1181,6 +1194,12 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1181 | path->nodes[0] = right_buffer; | 1194 | path->nodes[0] = right_buffer; |
1182 | path->slots[0] = 0; | 1195 | path->slots[0] = 0; |
1183 | path->slots[1] -= 1; | 1196 | path->slots[1] -= 1; |
1197 | if (path->slots[1] == 0) { | ||
1198 | wret = fixup_low_keys(trans, root, | ||
1199 | path, &disk_key, 1); | ||
1200 | if (wret) | ||
1201 | ret = wret; | ||
1202 | } | ||
1184 | return ret; | 1203 | return ret; |
1185 | } | 1204 | } |
1186 | mid = slot; | 1205 | mid = slot; |
@@ -1241,6 +1260,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1241 | path->slots[1], 1); | 1260 | path->slots[1], 1); |
1242 | if (wret) | 1261 | if (wret) |
1243 | ret = wret; | 1262 | ret = wret; |
1263 | if (path->slots[1] == 0) { | ||
1264 | wret = fixup_low_keys(trans, root, path, &disk_key, 1); | ||
1265 | if (wret) | ||
1266 | ret = wret; | ||
1267 | } | ||
1244 | btrfs_block_release(root, path->nodes[0]); | 1268 | btrfs_block_release(root, path->nodes[0]); |
1245 | path->nodes[0] = right_buffer; | 1269 | path->nodes[0] = right_buffer; |
1246 | path->slots[0] = 0; | 1270 | path->slots[0] = 0; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index d75a4d5bc010..8a329d3901a2 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -282,11 +282,12 @@ struct btrfs_root { | |||
282 | 282 | ||
283 | /* the lower bits in the key flags defines the item type */ | 283 | /* the lower bits in the key flags defines the item type */ |
284 | #define BTRFS_KEY_TYPE_MAX 256 | 284 | #define BTRFS_KEY_TYPE_MAX 256 |
285 | #define BTRFS_KEY_TYPE_MASK (BTRFS_KEY_TYPE_MAX - 1) | 285 | #define BTRFS_KEY_TYPE_SHIFT 24 |
286 | #define BTRFS_KEY_TYPE_MASK (((u32)BTRFS_KEY_TYPE_MAX - 1) << \ | ||
287 | BTRFS_KEY_TYPE_SHIFT) | ||
286 | 288 | ||
287 | #define BTRFS_KEY_OVERFLOW_MAX 128 | 289 | #define BTRFS_KEY_OVERFLOW_MAX 128 |
288 | #define BTRFS_KEY_OVERFLOW_SHIFT 8 | 290 | #define BTRFS_KEY_OVERFLOW_MASK ((u32)BTRFS_KEY_OVERFLOW_MAX - 1) |
289 | #define BTRFS_KEY_OVERFLOW_MASK (0x7FULL << BTRFS_KEY_OVERFLOW_SHIFT) | ||
290 | 291 | ||
291 | /* | 292 | /* |
292 | * inode items have the data typically returned from stat and store other | 293 | * inode items have the data typically returned from stat and store other |
@@ -586,56 +587,55 @@ static inline void btrfs_set_disk_key_flags(struct btrfs_disk_key *disk, | |||
586 | disk->flags = cpu_to_le32(val); | 587 | disk->flags = cpu_to_le32(val); |
587 | } | 588 | } |
588 | 589 | ||
589 | static inline u32 btrfs_key_overflow(struct btrfs_key *key) | 590 | static inline u32 btrfs_disk_key_type(struct btrfs_disk_key *key) |
590 | { | 591 | { |
591 | u32 over = key->flags & BTRFS_KEY_OVERFLOW_MASK; | 592 | return le32_to_cpu(key->flags) >> BTRFS_KEY_TYPE_SHIFT; |
592 | return over >> BTRFS_KEY_OVERFLOW_SHIFT; | ||
593 | } | 593 | } |
594 | 594 | ||
595 | static inline void btrfs_set_key_overflow(struct btrfs_key *key, u32 over) | 595 | static inline void btrfs_set_disk_key_type(struct btrfs_disk_key *key, |
596 | u32 val) | ||
596 | { | 597 | { |
597 | BUG_ON(over >= BTRFS_KEY_OVERFLOW_MAX); | 598 | u32 flags = btrfs_disk_key_flags(key); |
598 | over = over << BTRFS_KEY_OVERFLOW_SHIFT; | 599 | BUG_ON(val >= BTRFS_KEY_TYPE_MAX); |
599 | key->flags = (key->flags & ~((u64)BTRFS_KEY_OVERFLOW_MASK)) | over; | 600 | val = val << BTRFS_KEY_TYPE_SHIFT; |
601 | flags = (flags & ~BTRFS_KEY_TYPE_MASK) | val; | ||
602 | btrfs_set_disk_key_flags(key, flags); | ||
600 | } | 603 | } |
601 | 604 | ||
602 | static inline u32 btrfs_key_type(struct btrfs_key *key) | 605 | static inline u32 btrfs_key_type(struct btrfs_key *key) |
603 | { | 606 | { |
604 | return key->flags & BTRFS_KEY_TYPE_MASK; | 607 | return key->flags >> BTRFS_KEY_TYPE_SHIFT; |
605 | } | 608 | } |
606 | 609 | ||
607 | static inline u32 btrfs_disk_key_type(struct btrfs_disk_key *key) | 610 | static inline void btrfs_set_key_type(struct btrfs_key *key, u32 val) |
608 | { | 611 | { |
609 | return le32_to_cpu(key->flags) & BTRFS_KEY_TYPE_MASK; | 612 | BUG_ON(val >= BTRFS_KEY_TYPE_MAX); |
613 | val = val << BTRFS_KEY_TYPE_SHIFT; | ||
614 | key->flags = (key->flags & ~(BTRFS_KEY_TYPE_MASK)) | val; | ||
610 | } | 615 | } |
611 | 616 | ||
612 | static inline void btrfs_set_key_type(struct btrfs_key *key, u32 type) | 617 | static inline u32 btrfs_key_overflow(struct btrfs_key *key) |
613 | { | 618 | { |
614 | BUG_ON(type >= BTRFS_KEY_TYPE_MAX); | 619 | return key->flags & BTRFS_KEY_OVERFLOW_MASK; |
615 | key->flags = (key->flags & ~((u64)BTRFS_KEY_TYPE_MASK)) | type; | ||
616 | } | 620 | } |
617 | 621 | ||
618 | static inline void btrfs_set_disk_key_type(struct btrfs_disk_key *key, u32 type) | 622 | static inline void btrfs_set_key_overflow(struct btrfs_key *key, u32 over) |
619 | { | 623 | { |
620 | u32 flags = btrfs_disk_key_flags(key); | 624 | BUG_ON(over >= BTRFS_KEY_OVERFLOW_MAX); |
621 | BUG_ON(type >= BTRFS_KEY_TYPE_MAX); | 625 | key->flags = (key->flags & ~BTRFS_KEY_OVERFLOW_MASK) | over; |
622 | flags = (flags & ~((u64)BTRFS_KEY_TYPE_MASK)) | type; | ||
623 | btrfs_set_disk_key_flags(key, flags); | ||
624 | } | 626 | } |
625 | 627 | ||
626 | static inline u32 btrfs_disk_key_overflow(struct btrfs_disk_key *key) | 628 | static inline u32 btrfs_disk_key_overflow(struct btrfs_disk_key *key) |
627 | { | 629 | { |
628 | u32 over = le32_to_cpu(key->flags) & BTRFS_KEY_OVERFLOW_MASK; | 630 | return le32_to_cpu(key->flags) & BTRFS_KEY_OVERFLOW_MASK; |
629 | return over >> BTRFS_KEY_OVERFLOW_SHIFT; | ||
630 | } | 631 | } |
631 | 632 | ||
632 | static inline void btrfs_set_disK_key_overflow(struct btrfs_disk_key *key, | 633 | static inline void btrfs_set_disk_key_overflow(struct btrfs_disk_key *key, |
633 | u32 over) | 634 | u32 over) |
634 | { | 635 | { |
635 | u32 flags = btrfs_disk_key_flags(key); | 636 | u32 flags = btrfs_disk_key_flags(key); |
636 | BUG_ON(over >= BTRFS_KEY_OVERFLOW_MAX); | 637 | BUG_ON(over >= BTRFS_KEY_OVERFLOW_MAX); |
637 | over = over << BTRFS_KEY_OVERFLOW_SHIFT; | 638 | flags = (flags & ~BTRFS_KEY_OVERFLOW_MASK) | over; |
638 | flags = (flags & ~((u64)BTRFS_KEY_OVERFLOW_MASK)) | over; | ||
639 | btrfs_set_disk_key_flags(key, flags); | 639 | btrfs_set_disk_key_flags(key, flags); |
640 | } | 640 | } |
641 | 641 | ||
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index cd4137a8b87e..a43deb726486 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -58,30 +58,6 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
58 | 58 | ||
59 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); | 59 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); |
60 | btrfs_mark_buffer_dirty(path->nodes[0]); | 60 | btrfs_mark_buffer_dirty(path->nodes[0]); |
61 | |||
62 | /* FIXME, use some real flag for selecting the extra index */ | ||
63 | if (root == root->fs_info->tree_root) | ||
64 | goto out; | ||
65 | |||
66 | btrfs_release_path(root, path); | ||
67 | |||
68 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); | ||
69 | key.offset = location->objectid; | ||
70 | ret = insert_with_overflow(trans, root, path, &key, data_size); | ||
71 | // FIXME clear the dirindex bit | ||
72 | if (ret) | ||
73 | goto out; | ||
74 | |||
75 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
76 | path->slots[0], | ||
77 | struct btrfs_dir_item); | ||
78 | btrfs_cpu_key_to_disk(&dir_item->location, location); | ||
79 | btrfs_set_dir_type(dir_item, type); | ||
80 | btrfs_set_dir_flags(dir_item, 0); | ||
81 | btrfs_set_dir_name_len(dir_item, name_len); | ||
82 | name_ptr = (char *)(dir_item + 1); | ||
83 | btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); | ||
84 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
85 | out: | 61 | out: |
86 | btrfs_release_path(root, path); | 62 | btrfs_release_path(root, path); |
87 | btrfs_free_path(path); | 63 | btrfs_free_path(path); |
@@ -135,52 +111,6 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
135 | return 1; | 111 | return 1; |
136 | } | 112 | } |
137 | 113 | ||
138 | int btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, | ||
139 | struct btrfs_root *root, | ||
140 | struct btrfs_path *path, u64 dir, | ||
141 | u64 objectid, int mod) | ||
142 | { | ||
143 | int ret; | ||
144 | struct btrfs_key key; | ||
145 | int ins_len = mod < 0 ? -1 : 0; | ||
146 | int cow = mod != 0; | ||
147 | struct btrfs_disk_key *found_key; | ||
148 | struct btrfs_leaf *leaf; | ||
149 | int overflow = 0; | ||
150 | |||
151 | key.objectid = dir; | ||
152 | key.flags = 0; | ||
153 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); | ||
154 | key.offset = objectid; | ||
155 | |||
156 | while(1) { | ||
157 | btrfs_set_key_overflow(&key, overflow); | ||
158 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); | ||
159 | if (ret < 0) | ||
160 | return ret; | ||
161 | if (ret > 0) { | ||
162 | if (overflow >= BTRFS_KEY_OVERFLOW_MAX) | ||
163 | return 1; | ||
164 | overflow++; | ||
165 | btrfs_set_key_overflow(&key, overflow); | ||
166 | btrfs_release_path(root, path); | ||
167 | continue; | ||
168 | } else { | ||
169 | /* found */ | ||
170 | break; | ||
171 | } | ||
172 | } | ||
173 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
174 | found_key = &leaf->items[path->slots[0]].key; | ||
175 | |||
176 | if (btrfs_disk_key_objectid(found_key) != dir || | ||
177 | btrfs_disk_key_type(found_key) != BTRFS_DIR_INDEX_KEY) | ||
178 | return 1; | ||
179 | if (btrfs_disk_key_offset(found_key) == objectid) | ||
180 | return 0; | ||
181 | return 1; | ||
182 | } | ||
183 | |||
184 | int btrfs_match_dir_item_name(struct btrfs_root *root, | 114 | int btrfs_match_dir_item_name(struct btrfs_root *root, |
185 | struct btrfs_path *path, | 115 | struct btrfs_path *path, |
186 | const char *name, int name_len) | 116 | const char *name, int name_len) |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2cee9df001f6..cb04a70eb7e8 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -35,8 +35,10 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
35 | key.offset = num_blocks; | 35 | key.offset = num_blocks; |
36 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, | 36 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, path, |
37 | 0, 1); | 37 | 0, 1); |
38 | if (ret != 0) | 38 | if (ret != 0) { |
39 | printk("can't find block %Lu %Lu\n", blocknr, num_blocks); | ||
39 | BUG(); | 40 | BUG(); |
41 | } | ||
40 | BUG_ON(ret != 0); | 42 | BUG_ON(ret != 0); |
41 | l = btrfs_buffer_leaf(path->nodes[0]); | 43 | l = btrfs_buffer_leaf(path->nodes[0]); |
42 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); | 44 | item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item); |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index ff8f3339c684..8cc3c1d15412 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -4,7 +4,7 @@ | |||
4 | #include "transaction.h" | 4 | #include "transaction.h" |
5 | 5 | ||
6 | #define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \ | 6 | #define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \ |
7 | sizeof(struct btrfs_item)) / \ | 7 | sizeof(struct btrfs_item) * 2) / \ |
8 | sizeof(struct btrfs_csum_item)) - 1)) | 8 | sizeof(struct btrfs_csum_item)) - 1)) |
9 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | 9 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, |
10 | struct btrfs_root *root, | 10 | struct btrfs_root *root, |
@@ -19,11 +19,6 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | |||
19 | path = btrfs_alloc_path(); | 19 | path = btrfs_alloc_path(); |
20 | BUG_ON(!path); | 20 | BUG_ON(!path); |
21 | btrfs_init_path(path); | 21 | btrfs_init_path(path); |
22 | /* | ||
23 | ret = btrfs_alloc_extent(trans, root, num_blocks, hint_block, | ||
24 | (u64)-1, &ins); | ||
25 | */ | ||
26 | BUG_ON(ret); | ||
27 | file_key.objectid = objectid; | 22 | file_key.objectid = objectid; |
28 | file_key.offset = pos; | 23 | file_key.offset = pos; |
29 | file_key.flags = 0; | 24 | file_key.flags = 0; |
@@ -40,6 +35,7 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | |||
40 | btrfs_set_file_extent_num_blocks(item, num_blocks); | 35 | btrfs_set_file_extent_num_blocks(item, num_blocks); |
41 | btrfs_set_file_extent_generation(item, trans->transid); | 36 | btrfs_set_file_extent_generation(item, trans->transid); |
42 | btrfs_mark_buffer_dirty(path->nodes[0]); | 37 | btrfs_mark_buffer_dirty(path->nodes[0]); |
38 | |||
43 | btrfs_release_path(root, path); | 39 | btrfs_release_path(root, path); |
44 | btrfs_free_path(path); | 40 | btrfs_free_path(path); |
45 | return 0; | 41 | return 0; |
@@ -57,6 +53,7 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | |||
57 | struct btrfs_csum_item *item; | 53 | struct btrfs_csum_item *item; |
58 | struct btrfs_leaf *leaf; | 54 | struct btrfs_leaf *leaf; |
59 | u64 csum_offset = 0; | 55 | u64 csum_offset = 0; |
56 | int csums_in_item; | ||
60 | 57 | ||
61 | file_key.objectid = objectid; | 58 | file_key.objectid = objectid; |
62 | file_key.offset = offset; | 59 | file_key.offset = offset; |
@@ -79,9 +76,11 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | |||
79 | } | 76 | } |
80 | csum_offset = (offset - found_key.offset) >> | 77 | csum_offset = (offset - found_key.offset) >> |
81 | root->fs_info->sb->s_blocksize_bits; | 78 | root->fs_info->sb->s_blocksize_bits; |
82 | if (csum_offset >= | 79 | csums_in_item = btrfs_item_size(leaf->items + path->slots[0]); |
83 | btrfs_item_size(leaf->items + path->slots[0]) / | 80 | csums_in_item /= sizeof(struct btrfs_csum_item); |
84 | sizeof(struct btrfs_csum_item)) { | 81 | |
82 | if (csum_offset >= csums_in_item) { | ||
83 | ret = -EFBIG; | ||
85 | goto fail; | 84 | goto fail; |
86 | } | 85 | } |
87 | } | 86 | } |
@@ -128,16 +127,36 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
128 | 127 | ||
129 | path = btrfs_alloc_path(); | 128 | path = btrfs_alloc_path(); |
130 | BUG_ON(!path); | 129 | BUG_ON(!path); |
131 | btrfs_init_path(path); | ||
132 | 130 | ||
133 | item = btrfs_lookup_csum(trans, root, path, objectid, offset, 0); | ||
134 | if (!IS_ERR(item)) | ||
135 | goto found; | ||
136 | btrfs_release_path(root, path); | ||
137 | file_key.objectid = objectid; | 131 | file_key.objectid = objectid; |
138 | file_key.offset = offset; | 132 | file_key.offset = offset; |
139 | file_key.flags = 0; | 133 | file_key.flags = 0; |
140 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 134 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); |
135 | |||
136 | item = btrfs_lookup_csum(trans, root, path, objectid, offset, 1); | ||
137 | if (!IS_ERR(item)) | ||
138 | goto found; | ||
139 | ret = PTR_ERR(item); | ||
140 | if (ret == -EFBIG) { | ||
141 | u32 item_size; | ||
142 | /* we found one, but it isn't big enough yet */ | ||
143 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
144 | item_size = btrfs_item_size(leaf->items + path->slots[0]); | ||
145 | if ((item_size / sizeof(struct btrfs_csum_item)) >= | ||
146 | MAX_CSUM_ITEMS(root)) { | ||
147 | /* already at max size, make a new one */ | ||
148 | goto insert; | ||
149 | } | ||
150 | } else { | ||
151 | /* we didn't find a csum item, insert one */ | ||
152 | goto insert; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * at this point, we know the tree has an item, but it isn't big | ||
157 | * enough yet to put our csum in. Grow it | ||
158 | */ | ||
159 | btrfs_release_path(root, path); | ||
141 | ret = btrfs_search_slot(trans, root, &file_key, path, | 160 | ret = btrfs_search_slot(trans, root, &file_key, path, |
142 | sizeof(struct btrfs_csum_item), 1); | 161 | sizeof(struct btrfs_csum_item), 1); |
143 | if (ret < 0) | 162 | if (ret < 0) |
@@ -146,7 +165,6 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
146 | BUG(); | 165 | BUG(); |
147 | } | 166 | } |
148 | if (path->slots[0] == 0) { | 167 | if (path->slots[0] == 0) { |
149 | btrfs_release_path(root, path); | ||
150 | goto insert; | 168 | goto insert; |
151 | } | 169 | } |
152 | path->slots[0]--; | 170 | path->slots[0]--; |
@@ -157,29 +175,36 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
157 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 175 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || |
158 | found_key.objectid != objectid || | 176 | found_key.objectid != objectid || |
159 | csum_offset >= MAX_CSUM_ITEMS(root)) { | 177 | csum_offset >= MAX_CSUM_ITEMS(root)) { |
160 | btrfs_release_path(root, path); | 178 | WARN_ON(1); |
161 | goto insert; | 179 | goto insert; |
162 | } | 180 | } |
163 | if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / | 181 | if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / |
164 | sizeof(struct btrfs_csum_item)) { | 182 | sizeof(struct btrfs_csum_item)) { |
165 | ret = btrfs_extend_item(trans, root, path, | 183 | u32 diff = (csum_offset + 1) * sizeof(struct btrfs_csum_item); |
166 | sizeof(struct btrfs_csum_item)); | 184 | diff = diff - btrfs_item_size(leaf->items + path->slots[0]); |
185 | WARN_ON(diff != sizeof(struct btrfs_csum_item)); | ||
186 | ret = btrfs_extend_item(trans, root, path, diff); | ||
167 | BUG_ON(ret); | 187 | BUG_ON(ret); |
168 | goto csum; | 188 | goto csum; |
169 | } | 189 | } |
170 | 190 | ||
171 | insert: | 191 | insert: |
192 | btrfs_release_path(root, path); | ||
172 | csum_offset = 0; | 193 | csum_offset = 0; |
173 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, | 194 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, |
174 | sizeof(struct btrfs_csum_item)); | 195 | sizeof(struct btrfs_csum_item)); |
175 | if (ret != 0 && ret != -EEXIST) | 196 | if (ret != 0) { |
197 | printk("at insert for %Lu %u %Lu ret is %d\n", file_key.objectid, file_key.flags, file_key.offset, ret); | ||
198 | WARN_ON(1); | ||
176 | goto fail; | 199 | goto fail; |
200 | } | ||
177 | csum: | 201 | csum: |
178 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | 202 | item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], |
179 | struct btrfs_csum_item); | 203 | struct btrfs_csum_item); |
180 | ret = 0; | 204 | ret = 0; |
181 | item += csum_offset; | 205 | item += csum_offset; |
182 | found: | 206 | found: |
207 | btrfs_check_bounds(item->csum, BTRFS_CSUM_SIZE, path->nodes[0]->b_data, root->fs_info->sb->s_blocksize); | ||
183 | ret = btrfs_csum_data(root, data, len, item->csum); | 208 | ret = btrfs_csum_data(root, data, len, item->csum); |
184 | btrfs_mark_buffer_dirty(path->nodes[0]); | 209 | btrfs_mark_buffer_dirty(path->nodes[0]); |
185 | fail: | 210 | fail: |
@@ -210,6 +235,9 @@ int btrfs_csum_verify_file_block(struct btrfs_root *root, | |||
210 | item = btrfs_lookup_csum(NULL, root, path, objectid, offset, 0); | 235 | item = btrfs_lookup_csum(NULL, root, path, objectid, offset, 0); |
211 | if (IS_ERR(item)) { | 236 | if (IS_ERR(item)) { |
212 | ret = PTR_ERR(item); | 237 | ret = PTR_ERR(item); |
238 | /* a csum that isn't present is a preallocated region. */ | ||
239 | if (ret == -ENOENT || ret == -EFBIG) | ||
240 | ret = 1; | ||
213 | goto fail; | 241 | goto fail; |
214 | } | 242 | } |
215 | 243 | ||
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index 0732a2fbb23a..1e7038b070ae 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
@@ -19,7 +19,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
19 | for (i = 0 ; i < nr ; i++) { | 19 | for (i = 0 ; i < nr ; i++) { |
20 | item = l->items + i; | 20 | item = l->items + i; |
21 | type = btrfs_disk_key_type(&item->key); | 21 | type = btrfs_disk_key_type(&item->key); |
22 | printk("\titem %d key (%Lu %u %Lu) itemoff %d itemsize %d\n", | 22 | printk("\titem %d key (%Lu %x %Lu) itemoff %d itemsize %d\n", |
23 | i, | 23 | i, |
24 | btrfs_disk_key_objectid(&item->key), | 24 | btrfs_disk_key_objectid(&item->key), |
25 | btrfs_disk_key_flags(&item->key), | 25 | btrfs_disk_key_flags(&item->key), |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index b2a2220d1352..583cd87a62e2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -150,11 +150,6 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
150 | BUG_ON(ret); | 150 | BUG_ON(ret); |
151 | 151 | ||
152 | btrfs_release_path(root, path); | 152 | btrfs_release_path(root, path); |
153 | ret = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, | ||
154 | objectid, -1); | ||
155 | BUG_ON(ret); | ||
156 | ret = btrfs_del_item(trans, root, path); | ||
157 | BUG_ON(ret); | ||
158 | dentry->d_inode->i_ctime = dir->i_ctime; | 153 | dentry->d_inode->i_ctime = dir->i_ctime; |
159 | err: | 154 | err: |
160 | btrfs_release_path(root, path); | 155 | btrfs_release_path(root, path); |
@@ -329,8 +324,9 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
329 | extent_start = btrfs_file_extent_disk_blocknr(fi); | 324 | extent_start = btrfs_file_extent_disk_blocknr(fi); |
330 | extent_num_blocks = | 325 | extent_num_blocks = |
331 | btrfs_file_extent_disk_num_blocks(fi); | 326 | btrfs_file_extent_disk_num_blocks(fi); |
327 | /* FIXME blocksize != 4096 */ | ||
332 | inode->i_blocks -= | 328 | inode->i_blocks -= |
333 | btrfs_file_extent_num_blocks(fi) >> 9; | 329 | btrfs_file_extent_num_blocks(fi) << 3; |
334 | found_extent = 1; | 330 | found_extent = 1; |
335 | } else { | 331 | } else { |
336 | found_extent = 0; | 332 | found_extent = 0; |
@@ -562,7 +558,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
562 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) | 558 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) |
563 | break; | 559 | break; |
564 | if (btrfs_disk_key_type(&item->key) != key_type) | 560 | if (btrfs_disk_key_type(&item->key) != key_type) |
565 | continue; | 561 | break; |
566 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) | 562 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) |
567 | continue; | 563 | continue; |
568 | filp->f_pos = btrfs_disk_key_offset(&item->key); | 564 | filp->f_pos = btrfs_disk_key_offset(&item->key); |
@@ -1285,29 +1281,27 @@ static int drop_extents(struct btrfs_trans_handle *trans, | |||
1285 | struct btrfs_path *path; | 1281 | struct btrfs_path *path; |
1286 | u64 search_start = start; | 1282 | u64 search_start = start; |
1287 | int bookend; | 1283 | int bookend; |
1288 | |||
1289 | path = btrfs_alloc_path(); | 1284 | path = btrfs_alloc_path(); |
1290 | if (!path) | 1285 | if (!path) |
1291 | return -ENOMEM; | 1286 | return -ENOMEM; |
1292 | search_again: | 1287 | while(1) { |
1293 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, | 1288 | btrfs_release_path(root, path); |
1294 | search_start, -1); | 1289 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, |
1295 | if (ret < 0) | 1290 | search_start, -1); |
1296 | goto out; | 1291 | if (ret < 0) |
1297 | if (ret > 0) { | ||
1298 | if (path->slots[0] == 0) { | ||
1299 | ret = -ENOENT; | ||
1300 | goto out; | 1292 | goto out; |
1293 | if (ret > 0) { | ||
1294 | if (path->slots[0] == 0) { | ||
1295 | ret = -ENOENT; | ||
1296 | goto out; | ||
1297 | } | ||
1298 | path->slots[0]--; | ||
1301 | } | 1299 | } |
1302 | path->slots[0]--; | ||
1303 | } | ||
1304 | while(1) { | ||
1305 | keep = 0; | 1300 | keep = 0; |
1306 | bookend = 0; | 1301 | bookend = 0; |
1307 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 1302 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
1308 | slot = path->slots[0]; | 1303 | slot = path->slots[0]; |
1309 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | 1304 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); |
1310 | |||
1311 | extent = btrfs_item_ptr(leaf, slot, | 1305 | extent = btrfs_item_ptr(leaf, slot, |
1312 | struct btrfs_file_extent_item); | 1306 | struct btrfs_file_extent_item); |
1313 | extent_end = key.offset + | 1307 | extent_end = key.offset + |
@@ -1318,7 +1312,10 @@ search_again: | |||
1318 | goto out; | 1312 | goto out; |
1319 | } | 1313 | } |
1320 | if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) | 1314 | if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) |
1321 | goto next_leaf; | 1315 | goto out; |
1316 | if (search_start >= extent_end) | ||
1317 | goto out; | ||
1318 | search_start = extent_end; | ||
1322 | 1319 | ||
1323 | if (end < extent_end && end >= key.offset) { | 1320 | if (end < extent_end && end >= key.offset) { |
1324 | memcpy(&old, extent, sizeof(old)); | 1321 | memcpy(&old, extent, sizeof(old)); |
@@ -1331,10 +1328,13 @@ search_again: | |||
1331 | 1328 | ||
1332 | if (start > key.offset) { | 1329 | if (start > key.offset) { |
1333 | u64 new_num; | 1330 | u64 new_num; |
1331 | u64 old_num; | ||
1334 | /* truncate existing extent */ | 1332 | /* truncate existing extent */ |
1335 | keep = 1; | 1333 | keep = 1; |
1336 | WARN_ON(start & (root->blocksize - 1)); | 1334 | WARN_ON(start & (root->blocksize - 1)); |
1337 | new_num = (start - key.offset) >> inode->i_blkbits; | 1335 | new_num = (start - key.offset) >> inode->i_blkbits; |
1336 | old_num = btrfs_file_extent_num_blocks(extent); | ||
1337 | inode->i_blocks -= (old_num - new_num) << 3; | ||
1338 | btrfs_set_file_extent_num_blocks(extent, new_num); | 1338 | btrfs_set_file_extent_num_blocks(extent, new_num); |
1339 | mark_buffer_dirty(path->nodes[0]); | 1339 | mark_buffer_dirty(path->nodes[0]); |
1340 | } | 1340 | } |
@@ -1344,13 +1344,11 @@ search_again: | |||
1344 | disk_blocknr = btrfs_file_extent_disk_blocknr(extent); | 1344 | disk_blocknr = btrfs_file_extent_disk_blocknr(extent); |
1345 | disk_num_blocks = | 1345 | disk_num_blocks = |
1346 | btrfs_file_extent_disk_num_blocks(extent); | 1346 | btrfs_file_extent_disk_num_blocks(extent); |
1347 | search_start = key.offset + | ||
1348 | (btrfs_file_extent_num_blocks(extent) << | ||
1349 | inode->i_blkbits); | ||
1350 | ret = btrfs_del_item(trans, root, path); | 1347 | ret = btrfs_del_item(trans, root, path); |
1351 | BUG_ON(ret); | 1348 | BUG_ON(ret); |
1349 | inode->i_blocks -= | ||
1350 | btrfs_file_extent_num_blocks(extent) << 3; | ||
1352 | btrfs_release_path(root, path); | 1351 | btrfs_release_path(root, path); |
1353 | |||
1354 | ret = btrfs_free_extent(trans, root, disk_blocknr, | 1352 | ret = btrfs_free_extent(trans, root, disk_blocknr, |
1355 | disk_num_blocks, 0); | 1353 | disk_num_blocks, 0); |
1356 | 1354 | ||
@@ -1360,7 +1358,7 @@ search_again: | |||
1360 | goto out; | 1358 | goto out; |
1361 | } | 1359 | } |
1362 | if (!bookend) | 1360 | if (!bookend) |
1363 | goto search_again; | 1361 | continue; |
1364 | } | 1362 | } |
1365 | if (bookend) { | 1363 | if (bookend) { |
1366 | /* create bookend */ | 1364 | /* create bookend */ |
@@ -1395,21 +1393,12 @@ search_again: | |||
1395 | btrfs_set_file_extent_generation(extent, | 1393 | btrfs_set_file_extent_generation(extent, |
1396 | btrfs_file_extent_generation(&old)); | 1394 | btrfs_file_extent_generation(&old)); |
1397 | btrfs_mark_buffer_dirty(path->nodes[0]); | 1395 | btrfs_mark_buffer_dirty(path->nodes[0]); |
1396 | inode->i_blocks += | ||
1397 | btrfs_file_extent_num_blocks(extent) << 3; | ||
1398 | ret = 0; | 1398 | ret = 0; |
1399 | goto out; | 1399 | goto out; |
1400 | } | 1400 | } |
1401 | next_leaf: | ||
1402 | if (slot >= btrfs_header_nritems(&leaf->header) - 1) { | ||
1403 | ret = btrfs_next_leaf(root, path); | ||
1404 | if (ret) { | ||
1405 | ret = 0; | ||
1406 | goto out; | ||
1407 | } | ||
1408 | } else { | ||
1409 | path->slots[0]++; | ||
1410 | } | ||
1411 | } | 1401 | } |
1412 | |||
1413 | out: | 1402 | out: |
1414 | btrfs_free_path(path); | 1403 | btrfs_free_path(path); |
1415 | return ret; | 1404 | return ret; |
@@ -1445,15 +1434,6 @@ static int prepare_pages(struct btrfs_root *root, | |||
1445 | } | 1434 | } |
1446 | offset = pos & (PAGE_CACHE_SIZE -1); | 1435 | offset = pos & (PAGE_CACHE_SIZE -1); |
1447 | this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); | 1436 | this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); |
1448 | #if 0 | ||
1449 | if ((pages[i]->index == first_index || | ||
1450 | pages[i]->index == last_index) && pos < isize && | ||
1451 | !PageUptodate(pages[i])) { | ||
1452 | ret = mpage_readpage(pages[i], btrfs_get_block); | ||
1453 | BUG_ON(ret); | ||
1454 | lock_page(pages[i]); | ||
1455 | } | ||
1456 | #endif | ||
1457 | create_empty_buffers(pages[i], root->fs_info->sb->s_blocksize, | 1437 | create_empty_buffers(pages[i], root->fs_info->sb->s_blocksize, |
1458 | (1 << BH_Uptodate)); | 1438 | (1 << BH_Uptodate)); |
1459 | head = page_buffers(pages[i]); | 1439 | head = page_buffers(pages[i]); |
@@ -1494,6 +1474,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1494 | struct inode *inode = file->f_path.dentry->d_inode; | 1474 | struct inode *inode = file->f_path.dentry->d_inode; |
1495 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1475 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1496 | struct page *pages[8]; | 1476 | struct page *pages[8]; |
1477 | struct page *pinned[2] = { NULL, NULL }; | ||
1497 | unsigned long first_index; | 1478 | unsigned long first_index; |
1498 | unsigned long last_index; | 1479 | unsigned long last_index; |
1499 | u64 start_pos; | 1480 | u64 start_pos; |
@@ -1505,14 +1486,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1505 | if (file->f_flags & O_DIRECT) | 1486 | if (file->f_flags & O_DIRECT) |
1506 | return -EINVAL; | 1487 | return -EINVAL; |
1507 | pos = *ppos; | 1488 | pos = *ppos; |
1508 | |||
1509 | start_pos = pos & ~(root->blocksize - 1); | ||
1510 | /* FIXME */ | ||
1511 | if (start_pos != pos) | ||
1512 | return -EINVAL; | ||
1513 | num_blocks = (count + pos - start_pos + root->blocksize - 1) >> | ||
1514 | inode->i_blkbits; | ||
1515 | |||
1516 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 1489 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
1517 | current->backing_dev_info = inode->i_mapping->backing_dev_info; | 1490 | current->backing_dev_info = inode->i_mapping->backing_dev_info; |
1518 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); | 1491 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); |
@@ -1524,10 +1497,37 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1524 | if (err) | 1497 | if (err) |
1525 | goto out; | 1498 | goto out; |
1526 | file_update_time(file); | 1499 | file_update_time(file); |
1500 | |||
1501 | start_pos = pos & ~((u64)PAGE_CACHE_SIZE - 1); | ||
1502 | num_blocks = (count + pos - start_pos + root->blocksize - 1) >> | ||
1503 | inode->i_blkbits; | ||
1504 | |||
1527 | mutex_lock(&inode->i_mutex); | 1505 | mutex_lock(&inode->i_mutex); |
1528 | first_index = pos >> PAGE_CACHE_SHIFT; | 1506 | first_index = pos >> PAGE_CACHE_SHIFT; |
1529 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; | 1507 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; |
1530 | 1508 | ||
1509 | if ((first_index << PAGE_CACHE_SHIFT) < inode->i_size && | ||
1510 | (pos & (PAGE_CACHE_SIZE - 1))) { | ||
1511 | pinned[0] = grab_cache_page(inode->i_mapping, first_index); | ||
1512 | if (!PageUptodate(pinned[0])) { | ||
1513 | ret = mpage_readpage(pinned[0], btrfs_get_block); | ||
1514 | BUG_ON(ret); | ||
1515 | } else { | ||
1516 | unlock_page(pinned[0]); | ||
1517 | } | ||
1518 | } | ||
1519 | if (first_index != last_index && | ||
1520 | (last_index << PAGE_CACHE_SHIFT) < inode->i_size && | ||
1521 | (count & (PAGE_CACHE_SIZE - 1))) { | ||
1522 | pinned[1] = grab_cache_page(inode->i_mapping, last_index); | ||
1523 | if (!PageUptodate(pinned[1])) { | ||
1524 | ret = mpage_readpage(pinned[1], btrfs_get_block); | ||
1525 | BUG_ON(ret); | ||
1526 | } else { | ||
1527 | unlock_page(pinned[1]); | ||
1528 | } | ||
1529 | } | ||
1530 | |||
1531 | mutex_lock(&root->fs_info->fs_mutex); | 1531 | mutex_lock(&root->fs_info->fs_mutex); |
1532 | trans = btrfs_start_transaction(root, 1); | 1532 | trans = btrfs_start_transaction(root, 1); |
1533 | if (!trans) { | 1533 | if (!trans) { |
@@ -1535,11 +1535,14 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1535 | mutex_unlock(&root->fs_info->fs_mutex); | 1535 | mutex_unlock(&root->fs_info->fs_mutex); |
1536 | goto out_unlock; | 1536 | goto out_unlock; |
1537 | } | 1537 | } |
1538 | /* FIXME blocksize != 4096 */ | ||
1539 | inode->i_blocks += num_blocks << 3; | ||
1538 | if (start_pos < inode->i_size) { | 1540 | if (start_pos < inode->i_size) { |
1541 | /* FIXME blocksize != pagesize */ | ||
1539 | ret = drop_extents(trans, root, inode, | 1542 | ret = drop_extents(trans, root, inode, |
1540 | start_pos, | 1543 | start_pos, |
1541 | (pos + count + root->blocksize -1) & | 1544 | (pos + count + root->blocksize -1) & |
1542 | ~(root->blocksize - 1)); | 1545 | ~((u64)root->blocksize - 1)); |
1543 | } | 1546 | } |
1544 | ret = btrfs_alloc_extent(trans, root, num_blocks, 1, | 1547 | ret = btrfs_alloc_extent(trans, root, num_blocks, 1, |
1545 | (u64)-1, &ins); | 1548 | (u64)-1, &ins); |
@@ -1585,8 +1588,13 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1585 | out_unlock: | 1588 | out_unlock: |
1586 | mutex_unlock(&inode->i_mutex); | 1589 | mutex_unlock(&inode->i_mutex); |
1587 | out: | 1590 | out: |
1591 | if (pinned[0]) | ||
1592 | page_cache_release(pinned[0]); | ||
1593 | if (pinned[1]) | ||
1594 | page_cache_release(pinned[1]); | ||
1588 | *ppos = pos; | 1595 | *ppos = pos; |
1589 | current->backing_dev_info = NULL; | 1596 | current->backing_dev_info = NULL; |
1597 | mark_inode_dirty(inode); | ||
1590 | return num_written ? num_written : err; | 1598 | return num_written ? num_written : err; |
1591 | } | 1599 | } |
1592 | 1600 | ||