aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-04-18 16:15:28 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-04-18 16:15:28 -0400
commita429e51371eee3c989160c003ee40bc3947c6a76 (patch)
tree863b55de8823be579264260a51407cd90aac103d
parent70b2befd0c8a4064715d8b340270650cc9d15af8 (diff)
Btrfs: working file_write, reorganized key flags
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.c30
-rw-r--r--fs/btrfs/ctree.h52
-rw-r--r--fs/btrfs/dir-item.c70
-rw-r--r--fs/btrfs/extent-tree.c4
-rw-r--r--fs/btrfs/file-item.c66
-rw-r--r--fs/btrfs/print-tree.c2
-rw-r--r--fs/btrfs/super.c118
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
589static inline u32 btrfs_key_overflow(struct btrfs_key *key) 590static 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
595static inline void btrfs_set_key_overflow(struct btrfs_key *key, u32 over) 595static 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
602static inline u32 btrfs_key_type(struct btrfs_key *key) 605static 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
607static inline u32 btrfs_disk_key_type(struct btrfs_disk_key *key) 610static 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
612static inline void btrfs_set_key_type(struct btrfs_key *key, u32 type) 617static 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
618static inline void btrfs_set_disk_key_type(struct btrfs_disk_key *key, u32 type) 622static 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
626static inline u32 btrfs_disk_key_overflow(struct btrfs_disk_key *key) 628static 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
632static inline void btrfs_set_disK_key_overflow(struct btrfs_disk_key *key, 633static 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]);
85out: 61out:
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
138int 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
184int btrfs_match_dir_item_name(struct btrfs_root *root, 114int 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) {
39printk("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))
9int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, 9int 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
171insert: 191insert:
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 }
177csum: 201csum:
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;
182found: 206found:
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]);
185fail: 210fail:
@@ -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;
159err: 154err:
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;
1292search_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 }
1401next_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
1413out: 1402out:
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,
1585out_unlock: 1588out_unlock:
1586 mutex_unlock(&inode->i_mutex); 1589 mutex_unlock(&inode->i_mutex);
1587out: 1590out:
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