diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-17 15:39:32 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-17 15:39:32 -0400 |
commit | 70b2befd0c8a4064715d8b340270650cc9d15af8 (patch) | |
tree | 81171607c9ddf501e5c0233dc24d20d1a5b19858 /fs | |
parent | b18c6685810af8e6763760711aece31ccc7a8ea8 (diff) |
Btrfs: rework csums and extent item ordering
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.c | 9 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 17 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 28 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 26 | ||||
-rw-r--r-- | fs/btrfs/super.c | 123 |
6 files changed, 37 insertions, 168 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 43d4779abdd1..5c160c236773 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -115,14 +115,14 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2) | |||
115 | return 1; | 115 | return 1; |
116 | if (k1.objectid < k2->objectid) | 116 | if (k1.objectid < k2->objectid) |
117 | return -1; | 117 | return -1; |
118 | if (k1.offset > k2->offset) | ||
119 | return 1; | ||
120 | if (k1.offset < k2->offset) | ||
121 | return -1; | ||
122 | if (k1.flags > k2->flags) | 118 | if (k1.flags > k2->flags) |
123 | return 1; | 119 | return 1; |
124 | if (k1.flags < k2->flags) | 120 | if (k1.flags < k2->flags) |
125 | return -1; | 121 | return -1; |
122 | if (k1.offset > k2->offset) | ||
123 | return 1; | ||
124 | if (k1.offset < k2->offset) | ||
125 | return -1; | ||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
@@ -1292,7 +1292,6 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans, | |||
1292 | ioff + size_diff); | 1292 | ioff + size_diff); |
1293 | } | 1293 | } |
1294 | /* shift the data */ | 1294 | /* shift the data */ |
1295 | printk("truncate item, new_size %u old_size %u, diff %u, bufp %p, dst, %p, num %u, old_data_start %u, data_end %u\n", new_size, old_size, size_diff, leaf, btrfs_leaf_data(leaf) + data_end + size_diff, old_data_start-data_end, old_data_start, data_end); | ||
1296 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + | 1295 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + |
1297 | data_end + size_diff, btrfs_leaf_data(leaf) + | 1296 | data_end + size_diff, btrfs_leaf_data(leaf) + |
1298 | data_end, old_data_start + new_size - data_end); | 1297 | data_end, old_data_start + new_size - data_end); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index ca3ab160f460..d75a4d5bc010 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -44,14 +44,14 @@ extern struct kmem_cache *btrfs_path_cachep; | |||
44 | */ | 44 | */ |
45 | struct btrfs_disk_key { | 45 | struct btrfs_disk_key { |
46 | __le64 objectid; | 46 | __le64 objectid; |
47 | __le64 offset; | ||
48 | __le32 flags; | 47 | __le32 flags; |
48 | __le64 offset; | ||
49 | } __attribute__ ((__packed__)); | 49 | } __attribute__ ((__packed__)); |
50 | 50 | ||
51 | struct btrfs_key { | 51 | struct btrfs_key { |
52 | u64 objectid; | 52 | u64 objectid; |
53 | u64 offset; | ||
54 | u32 flags; | 53 | u32 flags; |
54 | u64 offset; | ||
55 | } __attribute__ ((__packed__)); | 55 | } __attribute__ ((__packed__)); |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -227,7 +227,6 @@ struct btrfs_file_extent_item { | |||
227 | } __attribute__ ((__packed__)); | 227 | } __attribute__ ((__packed__)); |
228 | 228 | ||
229 | struct btrfs_csum_item { | 229 | struct btrfs_csum_item { |
230 | __le64 extent_offset; | ||
231 | u8 csum[BTRFS_CSUM_SIZE]; | 230 | u8 csum[BTRFS_CSUM_SIZE]; |
232 | } __attribute__ ((__packed__)); | 231 | } __attribute__ ((__packed__)); |
233 | 232 | ||
@@ -925,17 +924,6 @@ static inline void btrfs_set_file_extent_num_blocks(struct | |||
925 | e->num_blocks = cpu_to_le64(val); | 924 | e->num_blocks = cpu_to_le64(val); |
926 | } | 925 | } |
927 | 926 | ||
928 | static inline u64 btrfs_csum_extent_offset(struct btrfs_csum_item *c) | ||
929 | { | ||
930 | return le64_to_cpu(c->extent_offset); | ||
931 | } | ||
932 | |||
933 | static inline void btrfs_set_csum_extent_offset(struct btrfs_csum_item *c, | ||
934 | u64 val) | ||
935 | { | ||
936 | c->extent_offset = cpu_to_le64(val); | ||
937 | } | ||
938 | |||
939 | static inline u16 btrfs_device_pathlen(struct btrfs_device_item *d) | 927 | static inline u16 btrfs_device_pathlen(struct btrfs_device_item *d) |
940 | { | 928 | { |
941 | return le16_to_cpu(d->pathlen); | 929 | return le16_to_cpu(d->pathlen); |
@@ -1091,7 +1079,6 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
1091 | int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | 1079 | int btrfs_csum_file_block(struct btrfs_trans_handle *trans, |
1092 | struct btrfs_root *root, | 1080 | struct btrfs_root *root, |
1093 | u64 objectid, u64 offset, | 1081 | u64 objectid, u64 offset, |
1094 | u64 extent_offset, | ||
1095 | char *data, size_t len); | 1082 | char *data, size_t len); |
1096 | int btrfs_csum_verify_file_block(struct btrfs_root *root, | 1083 | int btrfs_csum_verify_file_block(struct btrfs_root *root, |
1097 | u64 objectid, u64 offset, | 1084 | u64 objectid, u64 offset, |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 0ba46bc0da9a..cd4137a8b87e 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -103,7 +103,7 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
103 | key.objectid = dir; | 103 | key.objectid = dir; |
104 | key.flags = 0; | 104 | key.flags = 0; |
105 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | 105 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); |
106 | btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX - 1); | 106 | // btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX - 1); |
107 | ret = btrfs_name_hash(name, name_len, &key.offset); | 107 | ret = btrfs_name_hash(name, name_len, &key.offset); |
108 | BUG_ON(ret); | 108 | BUG_ON(ret); |
109 | while(1) { | 109 | while(1) { |
@@ -146,19 +146,29 @@ int btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, | |||
146 | int cow = mod != 0; | 146 | int cow = mod != 0; |
147 | struct btrfs_disk_key *found_key; | 147 | struct btrfs_disk_key *found_key; |
148 | struct btrfs_leaf *leaf; | 148 | struct btrfs_leaf *leaf; |
149 | int overflow = 0; | ||
149 | 150 | ||
150 | key.objectid = dir; | 151 | key.objectid = dir; |
151 | key.flags = 0; | 152 | key.flags = 0; |
152 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); | 153 | btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); |
153 | btrfs_set_key_overflow(&key, BTRFS_KEY_OVERFLOW_MAX - 1); | ||
154 | key.offset = objectid; | 154 | key.offset = objectid; |
155 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); | 155 | |
156 | if (ret < 0) | 156 | while(1) { |
157 | return ret; | 157 | btrfs_set_key_overflow(&key, overflow); |
158 | if (ret > 0) { | 158 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); |
159 | if (path->slots[0] == 0) | 159 | if (ret < 0) |
160 | return 1; | 160 | return ret; |
161 | path->slots[0]--; | 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 | } | ||
162 | } | 172 | } |
163 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 173 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
164 | found_key = &leaf->items[path->slots[0]].key; | 174 | found_key = &leaf->items[path->slots[0]].key; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 06b969c14625..a2a3f529cada 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -24,7 +24,6 @@ int btrfs_insert_dev_radix(struct btrfs_root *root, | |||
24 | u64 num_blocks) | 24 | u64 num_blocks) |
25 | { | 25 | { |
26 | struct dev_lookup *lookup; | 26 | struct dev_lookup *lookup; |
27 | char b[BDEVNAME_SIZE]; | ||
28 | int ret; | 27 | int ret; |
29 | 28 | ||
30 | lookup = kmalloc(sizeof(*lookup), GFP_NOFS); | 29 | lookup = kmalloc(sizeof(*lookup), GFP_NOFS); |
@@ -34,7 +33,6 @@ int btrfs_insert_dev_radix(struct btrfs_root *root, | |||
34 | lookup->num_blocks = num_blocks; | 33 | lookup->num_blocks = num_blocks; |
35 | lookup->bdev = bdev; | 34 | lookup->bdev = bdev; |
36 | lookup->device_id = device_id; | 35 | lookup->device_id = device_id; |
37 | printk("inserting %s into dev radix %Lu %Lu\n", bdevname(bdev, b), block_start, num_blocks); | ||
38 | 36 | ||
39 | ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + | 37 | ret = radix_tree_insert(&root->fs_info->dev_radix, block_start + |
40 | num_blocks - 1, lookup); | 38 | num_blocks - 1, lookup); |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index f49968ad0a07..ff8f3339c684 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -62,23 +62,19 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | |||
62 | file_key.offset = offset; | 62 | file_key.offset = offset; |
63 | file_key.flags = 0; | 63 | file_key.flags = 0; |
64 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 64 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); |
65 | printk("__lookup for %Lu\n", offset); | ||
66 | ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); | 65 | ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); |
67 | if (ret < 0) | 66 | if (ret < 0) |
68 | goto fail; | 67 | goto fail; |
69 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 68 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
70 | if (ret > 0) { | 69 | if (ret > 0) { |
71 | ret = 1; | 70 | ret = 1; |
72 | if (path->slots[0] == 0) { | 71 | if (path->slots[0] == 0) |
73 | printk("fail1\n"); | ||
74 | goto fail; | 72 | goto fail; |
75 | } | ||
76 | path->slots[0]--; | 73 | path->slots[0]--; |
77 | btrfs_disk_key_to_cpu(&found_key, | 74 | btrfs_disk_key_to_cpu(&found_key, |
78 | &leaf->items[path->slots[0]].key); | 75 | &leaf->items[path->slots[0]].key); |
79 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 76 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || |
80 | found_key.objectid != objectid) { | 77 | found_key.objectid != objectid) { |
81 | printk("fail2 type %u %Lu %Lu\n", btrfs_key_type(&found_key), found_key.objectid, objectid); | ||
82 | goto fail; | 78 | goto fail; |
83 | } | 79 | } |
84 | csum_offset = (offset - found_key.offset) >> | 80 | csum_offset = (offset - found_key.offset) >> |
@@ -86,7 +82,6 @@ printk("fail2 type %u %Lu %Lu\n", btrfs_key_type(&found_key), found_key.objectid | |||
86 | if (csum_offset >= | 82 | if (csum_offset >= |
87 | btrfs_item_size(leaf->items + path->slots[0]) / | 83 | btrfs_item_size(leaf->items + path->slots[0]) / |
88 | sizeof(struct btrfs_csum_item)) { | 84 | sizeof(struct btrfs_csum_item)) { |
89 | printk("fail3, csum offset %lu size %u\n", csum_offset, btrfs_item_size(leaf->items + path->slots[0]) / sizeof(struct btrfs_csum_item)); | ||
90 | goto fail; | 85 | goto fail; |
91 | } | 86 | } |
92 | } | 87 | } |
@@ -109,26 +104,18 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
109 | struct btrfs_key file_key; | 104 | struct btrfs_key file_key; |
110 | int ins_len = mod < 0 ? -1 : 0; | 105 | int ins_len = mod < 0 ? -1 : 0; |
111 | int cow = mod != 0; | 106 | int cow = mod != 0; |
112 | struct btrfs_csum_item *csum_item; | ||
113 | 107 | ||
114 | csum_item = btrfs_lookup_csum(trans, root, path, objectid, offset, 0); | ||
115 | if (IS_ERR(csum_item)) | ||
116 | return PTR_ERR(csum_item); | ||
117 | file_key.objectid = objectid; | 108 | file_key.objectid = objectid; |
118 | file_key.offset = btrfs_csum_extent_offset(csum_item); | 109 | file_key.offset = offset; |
119 | file_key.flags = 0; | 110 | file_key.flags = 0; |
120 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); | 111 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); |
121 | btrfs_release_path(root, path); | ||
122 | printk("lookup file extent searches for %Lu\n", file_key.offset); | ||
123 | ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); | 112 | ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); |
124 | printk("ret is %d\n", ret); | ||
125 | return ret; | 113 | return ret; |
126 | } | 114 | } |
127 | 115 | ||
128 | int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | 116 | int btrfs_csum_file_block(struct btrfs_trans_handle *trans, |
129 | struct btrfs_root *root, | 117 | struct btrfs_root *root, |
130 | u64 objectid, u64 offset, | 118 | u64 objectid, u64 offset, |
131 | u64 extent_offset, | ||
132 | char *data, size_t len) | 119 | char *data, size_t len) |
133 | { | 120 | { |
134 | int ret; | 121 | int ret; |
@@ -151,10 +138,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
151 | file_key.offset = offset; | 138 | file_key.offset = offset; |
152 | file_key.flags = 0; | 139 | file_key.flags = 0; |
153 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 140 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); |
154 | printk("searching for csum %Lu %Lu\n", objectid, offset); | ||
155 | ret = btrfs_search_slot(trans, root, &file_key, path, | 141 | ret = btrfs_search_slot(trans, root, &file_key, path, |
156 | sizeof(struct btrfs_csum_item), 1); | 142 | sizeof(struct btrfs_csum_item), 1); |
157 | printk("ret %d\n", ret); | ||
158 | if (ret < 0) | 143 | if (ret < 0) |
159 | goto fail; | 144 | goto fail; |
160 | if (ret == 0) { | 145 | if (ret == 0) { |
@@ -167,15 +152,12 @@ printk("ret %d\n", ret); | |||
167 | path->slots[0]--; | 152 | path->slots[0]--; |
168 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 153 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
169 | btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key); | 154 | btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key); |
170 | printk("found key %Lu %Lu %u\n", found_key.objectid, found_key.offset, found_key.flags); | ||
171 | csum_offset = (offset - found_key.offset) >> | 155 | csum_offset = (offset - found_key.offset) >> |
172 | root->fs_info->sb->s_blocksize_bits; | 156 | root->fs_info->sb->s_blocksize_bits; |
173 | printk("csum_offset %Lu\n", csum_offset); | ||
174 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 157 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || |
175 | found_key.objectid != objectid || | 158 | found_key.objectid != objectid || |
176 | csum_offset >= MAX_CSUM_ITEMS(root)) { | 159 | csum_offset >= MAX_CSUM_ITEMS(root)) { |
177 | btrfs_release_path(root, path); | 160 | btrfs_release_path(root, path); |
178 | printk("insert1\n"); | ||
179 | goto insert; | 161 | goto insert; |
180 | } | 162 | } |
181 | if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / | 163 | if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / |
@@ -183,13 +165,11 @@ printk("insert1\n"); | |||
183 | ret = btrfs_extend_item(trans, root, path, | 165 | ret = btrfs_extend_item(trans, root, path, |
184 | sizeof(struct btrfs_csum_item)); | 166 | sizeof(struct btrfs_csum_item)); |
185 | BUG_ON(ret); | 167 | BUG_ON(ret); |
186 | printk("item extended\n"); | ||
187 | goto csum; | 168 | goto csum; |
188 | } | 169 | } |
189 | 170 | ||
190 | insert: | 171 | insert: |
191 | csum_offset = 0; | 172 | csum_offset = 0; |
192 | printk("inserting item %Lu %Lu %u\n", file_key.objectid, file_key.offset, file_key.flags); | ||
193 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, | 173 | ret = btrfs_insert_empty_item(trans, root, path, &file_key, |
194 | sizeof(struct btrfs_csum_item)); | 174 | sizeof(struct btrfs_csum_item)); |
195 | if (ret != 0 && ret != -EEXIST) | 175 | if (ret != 0 && ret != -EEXIST) |
@@ -201,12 +181,10 @@ csum: | |||
201 | item += csum_offset; | 181 | item += csum_offset; |
202 | found: | 182 | found: |
203 | ret = btrfs_csum_data(root, data, len, item->csum); | 183 | ret = btrfs_csum_data(root, data, len, item->csum); |
204 | btrfs_set_csum_extent_offset(item, extent_offset); | ||
205 | btrfs_mark_buffer_dirty(path->nodes[0]); | 184 | btrfs_mark_buffer_dirty(path->nodes[0]); |
206 | fail: | 185 | fail: |
207 | btrfs_release_path(root, path); | 186 | btrfs_release_path(root, path); |
208 | btrfs_free_path(path); | 187 | btrfs_free_path(path); |
209 | printk("return ret %d\n", ret); | ||
210 | return ret; | 188 | return ret; |
211 | } | 189 | } |
212 | 190 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 6a56416147e6..b2a2220d1352 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -524,7 +524,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
524 | int advance; | 524 | int advance; |
525 | unsigned char d_type = DT_UNKNOWN; | 525 | unsigned char d_type = DT_UNKNOWN; |
526 | int over = 0; | 526 | int over = 0; |
527 | int key_type = BTRFS_DIR_INDEX_KEY; | 527 | int key_type = BTRFS_DIR_ITEM_KEY; |
528 | 528 | ||
529 | /* FIXME, use a real flag for deciding about the key type */ | 529 | /* FIXME, use a real flag for deciding about the key type */ |
530 | if (root->fs_info->tree_root == root) | 530 | if (root->fs_info->tree_root == root) |
@@ -561,9 +561,6 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
561 | item = leaf->items + slot; | 561 | item = leaf->items + slot; |
562 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) | 562 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) |
563 | break; | 563 | break; |
564 | if (key_type == BTRFS_DIR_INDEX_KEY && | ||
565 | btrfs_disk_key_offset(&item->key) > root->highest_inode) | ||
566 | break; | ||
567 | if (btrfs_disk_key_type(&item->key) != key_type) | 564 | if (btrfs_disk_key_type(&item->key) != key_type) |
568 | continue; | 565 | continue; |
569 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) | 566 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) |
@@ -1119,7 +1116,6 @@ allocate: | |||
1119 | out: | 1116 | out: |
1120 | btrfs_release_path(root, path); | 1117 | btrfs_release_path(root, path); |
1121 | btrfs_free_path(path); | 1118 | btrfs_free_path(path); |
1122 | printk("mapping iblock %lu to %lu\n", iblock, result->b_blocknr); | ||
1123 | if (trans) | 1119 | if (trans) |
1124 | btrfs_end_transaction(trans, root); | 1120 | btrfs_end_transaction(trans, root); |
1125 | return err; | 1121 | return err; |
@@ -1233,7 +1229,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
1233 | struct file *file, | 1229 | struct file *file, |
1234 | struct page **pages, | 1230 | struct page **pages, |
1235 | size_t num_pages, | 1231 | size_t num_pages, |
1236 | u64 extent_offset, | ||
1237 | loff_t pos, | 1232 | loff_t pos, |
1238 | size_t write_bytes) | 1233 | size_t write_bytes) |
1239 | { | 1234 | { |
@@ -1253,7 +1248,6 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
1253 | trans = btrfs_start_transaction(root, 1); | 1248 | trans = btrfs_start_transaction(root, 1); |
1254 | btrfs_csum_file_block(trans, root, inode->i_ino, | 1249 | btrfs_csum_file_block(trans, root, inode->i_ino, |
1255 | pages[i]->index << PAGE_CACHE_SHIFT, | 1250 | pages[i]->index << PAGE_CACHE_SHIFT, |
1256 | extent_offset, | ||
1257 | kmap(pages[i]), PAGE_CACHE_SIZE); | 1251 | kmap(pages[i]), PAGE_CACHE_SIZE); |
1258 | kunmap(pages[i]); | 1252 | kunmap(pages[i]); |
1259 | SetPageChecked(pages[i]); | 1253 | SetPageChecked(pages[i]); |
@@ -1275,86 +1269,6 @@ failed: | |||
1275 | return err; | 1269 | return err; |
1276 | } | 1270 | } |
1277 | 1271 | ||
1278 | static int drop_csums(struct btrfs_trans_handle *trans, | ||
1279 | struct btrfs_root *root, | ||
1280 | struct inode *inode, | ||
1281 | u64 start, u64 end) | ||
1282 | { | ||
1283 | struct btrfs_path *path; | ||
1284 | struct btrfs_leaf *leaf; | ||
1285 | struct btrfs_key key; | ||
1286 | int slot; | ||
1287 | struct btrfs_csum_item *item; | ||
1288 | char *old_block = NULL; | ||
1289 | u64 cur = start; | ||
1290 | u64 found_end; | ||
1291 | u64 num_csums; | ||
1292 | u64 item_size; | ||
1293 | int ret; | ||
1294 | |||
1295 | path = btrfs_alloc_path(); | ||
1296 | if (!path) | ||
1297 | return -ENOMEM; | ||
1298 | while(cur < end) { | ||
1299 | item = btrfs_lookup_csum(trans, root, path, | ||
1300 | inode->i_ino, cur, 1); | ||
1301 | if (IS_ERR(item)) { | ||
1302 | cur += root->blocksize; | ||
1303 | continue; | ||
1304 | } | ||
1305 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
1306 | slot = path->slots[0]; | ||
1307 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | ||
1308 | item_size = btrfs_item_size(leaf->items + slot); | ||
1309 | num_csums = item_size / sizeof(struct btrfs_csum_item); | ||
1310 | found_end = key.offset + (num_csums << inode->i_blkbits); | ||
1311 | cur = found_end; | ||
1312 | |||
1313 | if (found_end > end) { | ||
1314 | char *src; | ||
1315 | old_block = kmalloc(root->blocksize, GFP_NOFS); | ||
1316 | src = btrfs_item_ptr(leaf, slot, char); | ||
1317 | memcpy(old_block, src, item_size); | ||
1318 | } | ||
1319 | if (key.offset < start) { | ||
1320 | u64 new_size = (start - key.offset) >> | ||
1321 | inode->i_blkbits; | ||
1322 | new_size *= sizeof(struct btrfs_csum_item); | ||
1323 | ret = btrfs_truncate_item(trans, root, path, new_size); | ||
1324 | BUG_ON(ret); | ||
1325 | } else { | ||
1326 | btrfs_del_item(trans, root, path); | ||
1327 | } | ||
1328 | btrfs_release_path(root, path); | ||
1329 | if (found_end > end) { | ||
1330 | char *dst; | ||
1331 | int i; | ||
1332 | int new_size; | ||
1333 | |||
1334 | num_csums = (found_end - end) >> inode->i_blkbits; | ||
1335 | new_size = num_csums * sizeof(struct btrfs_csum_item); | ||
1336 | key.offset = end; | ||
1337 | ret = btrfs_insert_empty_item(trans, root, path, | ||
1338 | &key, new_size); | ||
1339 | BUG_ON(ret); | ||
1340 | dst = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), | ||
1341 | path->slots[0], char); | ||
1342 | memcpy(dst, old_block + item_size - new_size, | ||
1343 | new_size); | ||
1344 | item = (struct btrfs_csum_item *)dst; | ||
1345 | for (i = 0; i < num_csums; i++) { | ||
1346 | btrfs_set_csum_extent_offset(item, end); | ||
1347 | item++; | ||
1348 | } | ||
1349 | mark_buffer_dirty(path->nodes[0]); | ||
1350 | kfree(old_block); | ||
1351 | break; | ||
1352 | } | ||
1353 | } | ||
1354 | btrfs_free_path(path); | ||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | static int drop_extents(struct btrfs_trans_handle *trans, | 1272 | static int drop_extents(struct btrfs_trans_handle *trans, |
1359 | struct btrfs_root *root, | 1273 | struct btrfs_root *root, |
1360 | struct inode *inode, | 1274 | struct inode *inode, |
@@ -1376,12 +1290,16 @@ static int drop_extents(struct btrfs_trans_handle *trans, | |||
1376 | if (!path) | 1290 | if (!path) |
1377 | return -ENOMEM; | 1291 | return -ENOMEM; |
1378 | search_again: | 1292 | search_again: |
1379 | printk("drop extent inode %lu start %Lu end %Lu\n", inode->i_ino, start, end); | ||
1380 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, | 1293 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, |
1381 | search_start, -1); | 1294 | search_start, -1); |
1382 | if (ret != 0) { | 1295 | if (ret < 0) |
1383 | printk("lookup failed\n"); | ||
1384 | goto out; | 1296 | goto out; |
1297 | if (ret > 0) { | ||
1298 | if (path->slots[0] == 0) { | ||
1299 | ret = -ENOENT; | ||
1300 | goto out; | ||
1301 | } | ||
1302 | path->slots[0]--; | ||
1385 | } | 1303 | } |
1386 | while(1) { | 1304 | while(1) { |
1387 | keep = 0; | 1305 | keep = 0; |
@@ -1390,14 +1308,11 @@ printk("lookup failed\n"); | |||
1390 | slot = path->slots[0]; | 1308 | slot = path->slots[0]; |
1391 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | 1309 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); |
1392 | 1310 | ||
1393 | printk("found key %Lu %Lu %u\n", key.objectid, key.offset, key.flags); | ||
1394 | |||
1395 | extent = btrfs_item_ptr(leaf, slot, | 1311 | extent = btrfs_item_ptr(leaf, slot, |
1396 | struct btrfs_file_extent_item); | 1312 | struct btrfs_file_extent_item); |
1397 | extent_end = key.offset + | 1313 | extent_end = key.offset + |
1398 | (btrfs_file_extent_num_blocks(extent) << | 1314 | (btrfs_file_extent_num_blocks(extent) << |
1399 | inode->i_blkbits); | 1315 | inode->i_blkbits); |
1400 | printk("extent end is %Lu\n", extent_end); | ||
1401 | if (key.offset >= end || key.objectid != inode->i_ino) { | 1316 | if (key.offset >= end || key.objectid != inode->i_ino) { |
1402 | ret = 0; | 1317 | ret = 0; |
1403 | goto out; | 1318 | goto out; |
@@ -1420,16 +1335,12 @@ printk("extent end is %Lu\n", extent_end); | |||
1420 | keep = 1; | 1335 | keep = 1; |
1421 | WARN_ON(start & (root->blocksize - 1)); | 1336 | WARN_ON(start & (root->blocksize - 1)); |
1422 | new_num = (start - key.offset) >> inode->i_blkbits; | 1337 | new_num = (start - key.offset) >> inode->i_blkbits; |
1423 | printk("truncating existing extent, was %Lu ", btrfs_file_extent_num_blocks(extent)); | ||
1424 | btrfs_set_file_extent_num_blocks(extent, new_num); | 1338 | btrfs_set_file_extent_num_blocks(extent, new_num); |
1425 | printk("now %Lu\n", btrfs_file_extent_num_blocks(extent)); | ||
1426 | |||
1427 | mark_buffer_dirty(path->nodes[0]); | 1339 | mark_buffer_dirty(path->nodes[0]); |
1428 | } | 1340 | } |
1429 | if (!keep) { | 1341 | if (!keep) { |
1430 | u64 disk_blocknr; | 1342 | u64 disk_blocknr; |
1431 | u64 disk_num_blocks; | 1343 | u64 disk_num_blocks; |
1432 | printk("del old\n"); | ||
1433 | disk_blocknr = btrfs_file_extent_disk_blocknr(extent); | 1344 | disk_blocknr = btrfs_file_extent_disk_blocknr(extent); |
1434 | disk_num_blocks = | 1345 | disk_num_blocks = |
1435 | btrfs_file_extent_disk_num_blocks(extent); | 1346 | btrfs_file_extent_disk_num_blocks(extent); |
@@ -1454,15 +1365,12 @@ printk("del old\n"); | |||
1454 | if (bookend) { | 1365 | if (bookend) { |
1455 | /* create bookend */ | 1366 | /* create bookend */ |
1456 | struct btrfs_key ins; | 1367 | struct btrfs_key ins; |
1457 | printk("bookend! extent end %Lu\n", extent_end); | ||
1458 | ins.objectid = inode->i_ino; | 1368 | ins.objectid = inode->i_ino; |
1459 | ins.offset = end; | 1369 | ins.offset = end; |
1460 | ins.flags = 0; | 1370 | ins.flags = 0; |
1461 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); | 1371 | btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY); |
1462 | 1372 | ||
1463 | btrfs_release_path(root, path); | 1373 | btrfs_release_path(root, path); |
1464 | ret = drop_csums(trans, root, inode, start, end); | ||
1465 | BUG_ON(ret); | ||
1466 | ret = btrfs_insert_empty_item(trans, root, path, &ins, | 1374 | ret = btrfs_insert_empty_item(trans, root, path, &ins, |
1467 | sizeof(*extent)); | 1375 | sizeof(*extent)); |
1468 | BUG_ON(ret); | 1376 | BUG_ON(ret); |
@@ -1486,10 +1394,9 @@ printk("bookend! extent end %Lu\n", extent_end); | |||
1486 | 1394 | ||
1487 | btrfs_set_file_extent_generation(extent, | 1395 | btrfs_set_file_extent_generation(extent, |
1488 | btrfs_file_extent_generation(&old)); | 1396 | btrfs_file_extent_generation(&old)); |
1489 | printk("new bookend at offset %Lu, file_extent_offset %Lu, file_extent_num_blocks %Lu\n", end, btrfs_file_extent_offset(extent), btrfs_file_extent_num_blocks(extent)); | ||
1490 | btrfs_mark_buffer_dirty(path->nodes[0]); | 1397 | btrfs_mark_buffer_dirty(path->nodes[0]); |
1491 | ret = 0; | 1398 | ret = 0; |
1492 | goto out_nocsum; | 1399 | goto out; |
1493 | } | 1400 | } |
1494 | next_leaf: | 1401 | next_leaf: |
1495 | if (slot >= btrfs_header_nritems(&leaf->header) - 1) { | 1402 | if (slot >= btrfs_header_nritems(&leaf->header) - 1) { |
@@ -1504,10 +1411,6 @@ next_leaf: | |||
1504 | } | 1411 | } |
1505 | 1412 | ||
1506 | out: | 1413 | out: |
1507 | ret = drop_csums(trans, root, inode, start, end); | ||
1508 | BUG_ON(ret); | ||
1509 | |||
1510 | out_nocsum: | ||
1511 | btrfs_free_path(path); | 1414 | btrfs_free_path(path); |
1512 | return ret; | 1415 | return ret; |
1513 | } | 1416 | } |
@@ -1556,7 +1459,6 @@ static int prepare_pages(struct btrfs_root *root, | |||
1556 | head = page_buffers(pages[i]); | 1459 | head = page_buffers(pages[i]); |
1557 | bh = head; | 1460 | bh = head; |
1558 | do { | 1461 | do { |
1559 | printk("mapping page %lu to block %Lu\n", pages[i]->index, alloc_extent_start); | ||
1560 | err = btrfs_map_bh_to_logical(root, bh, | 1462 | err = btrfs_map_bh_to_logical(root, bh, |
1561 | alloc_extent_start); | 1463 | alloc_extent_start); |
1562 | BUG_ON(err); | 1464 | BUG_ON(err); |
@@ -1597,7 +1499,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1597 | u64 start_pos; | 1499 | u64 start_pos; |
1598 | u64 num_blocks; | 1500 | u64 num_blocks; |
1599 | u64 alloc_extent_start; | 1501 | u64 alloc_extent_start; |
1600 | u64 orig_extent_start; | ||
1601 | struct btrfs_trans_handle *trans; | 1502 | struct btrfs_trans_handle *trans; |
1602 | struct btrfs_key ins; | 1503 | struct btrfs_key ins; |
1603 | 1504 | ||
@@ -1640,7 +1541,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1640 | (pos + count + root->blocksize -1) & | 1541 | (pos + count + root->blocksize -1) & |
1641 | ~(root->blocksize - 1)); | 1542 | ~(root->blocksize - 1)); |
1642 | } | 1543 | } |
1643 | orig_extent_start = start_pos; | ||
1644 | ret = btrfs_alloc_extent(trans, root, num_blocks, 1, | 1544 | ret = btrfs_alloc_extent(trans, root, num_blocks, 1, |
1645 | (u64)-1, &ins); | 1545 | (u64)-1, &ins); |
1646 | BUG_ON(ret); | 1546 | BUG_ON(ret); |
@@ -1656,7 +1556,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1656 | size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); | 1556 | size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); |
1657 | size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> | 1557 | size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> |
1658 | PAGE_CACHE_SHIFT; | 1558 | PAGE_CACHE_SHIFT; |
1659 | printk("num_pages is %lu\n", num_pages); | ||
1660 | 1559 | ||
1661 | memset(pages, 0, sizeof(pages)); | 1560 | memset(pages, 0, sizeof(pages)); |
1662 | ret = prepare_pages(root, file, pages, num_pages, | 1561 | ret = prepare_pages(root, file, pages, num_pages, |
@@ -1670,10 +1569,8 @@ printk("num_pages is %lu\n", num_pages); | |||
1670 | write_bytes, pages, buf); | 1569 | write_bytes, pages, buf); |
1671 | BUG_ON(ret); | 1570 | BUG_ON(ret); |
1672 | 1571 | ||
1673 | printk("2num_pages is %lu\n", num_pages); | ||
1674 | ret = dirty_and_release_pages(NULL, root, file, pages, | 1572 | ret = dirty_and_release_pages(NULL, root, file, pages, |
1675 | num_pages, orig_extent_start, | 1573 | num_pages, pos, write_bytes); |
1676 | pos, write_bytes); | ||
1677 | BUG_ON(ret); | 1574 | BUG_ON(ret); |
1678 | btrfs_drop_pages(pages, num_pages); | 1575 | btrfs_drop_pages(pages, num_pages); |
1679 | 1576 | ||