1 #include <linux/module.h>
4 #include "transaction.h"
5 #include "print-tree.h"
7 #define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \
8 sizeof(struct btrfs_item) * 2) / \
9 BTRFS_CRC32_SIZE) - 1))
10 int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
11 struct btrfs_root *root,
12 u64 objectid, u64 pos,
13 u64 offset, u64 disk_num_blocks,
17 struct btrfs_file_extent_item *item;
18 struct btrfs_key file_key;
19 struct btrfs_path *path;
21 path = btrfs_alloc_path();
23 btrfs_init_path(path);
24 file_key.objectid = objectid;
25 file_key.offset = pos;
27 btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
29 ret = btrfs_insert_empty_item(trans, root, path, &file_key,
32 printk("failed to insert %Lu %Lu ret %d\n", objectid, pos, ret);
33 btrfs_print_leaf(root, btrfs_buffer_leaf(path->nodes[0]));
36 item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
37 struct btrfs_file_extent_item);
38 btrfs_set_file_extent_disk_blocknr(item, offset);
39 btrfs_set_file_extent_disk_num_blocks(item, disk_num_blocks);
40 btrfs_set_file_extent_offset(item, 0);
41 btrfs_set_file_extent_num_blocks(item, num_blocks);
42 btrfs_set_file_extent_generation(item, trans->transid);
43 btrfs_set_file_extent_type(item, BTRFS_FILE_EXTENT_REG);
44 btrfs_mark_buffer_dirty(path->nodes[0]);
46 btrfs_release_path(root, path);
47 btrfs_free_path(path);
51 struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
52 struct btrfs_root *root,
53 struct btrfs_path *path,
54 u64 objectid, u64 offset,
58 struct btrfs_key file_key;
59 struct btrfs_key found_key;
60 struct btrfs_csum_item *item;
61 struct btrfs_leaf *leaf;
65 file_key.objectid = objectid;
66 file_key.offset = offset;
68 btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
69 ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
72 leaf = btrfs_buffer_leaf(path->nodes[0]);
75 if (path->slots[0] == 0)
78 btrfs_disk_key_to_cpu(&found_key,
79 &leaf->items[path->slots[0]].key);
80 if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
81 found_key.objectid != objectid) {
84 csum_offset = (offset - found_key.offset) >>
85 root->fs_info->sb->s_blocksize_bits;
86 csums_in_item = btrfs_item_size(leaf->items + path->slots[0]);
87 csums_in_item /= BTRFS_CRC32_SIZE;
89 if (csum_offset >= csums_in_item) {
94 item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
95 item = (struct btrfs_csum_item *)((unsigned char *)item +
96 csum_offset * BTRFS_CRC32_SIZE);
105 int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
106 struct btrfs_root *root,
107 struct btrfs_path *path, u64 objectid,
111 struct btrfs_key file_key;
112 int ins_len = mod < 0 ? -1 : 0;
115 file_key.objectid = objectid;
116 file_key.offset = offset;
118 btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
119 ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
123 int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
124 struct btrfs_root *root,
125 u64 objectid, u64 offset,
126 char *data, size_t len)
129 struct btrfs_key file_key;
130 struct btrfs_key found_key;
131 struct btrfs_path *path;
132 struct btrfs_csum_item *item;
133 struct btrfs_leaf *leaf;
136 path = btrfs_alloc_path();
139 file_key.objectid = objectid;
140 file_key.offset = offset;
142 btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
144 item = btrfs_lookup_csum(trans, root, path, objectid, offset, 1);
150 /* we found one, but it isn't big enough yet */
151 leaf = btrfs_buffer_leaf(path->nodes[0]);
152 item_size = btrfs_item_size(leaf->items + path->slots[0]);
153 if ((item_size / BTRFS_CRC32_SIZE) >= MAX_CSUM_ITEMS(root)) {
154 /* already at max size, make a new one */
158 /* we didn't find a csum item, insert one */
163 * at this point, we know the tree has an item, but it isn't big
164 * enough yet to put our csum in. Grow it
166 btrfs_release_path(root, path);
167 ret = btrfs_search_slot(trans, root, &file_key, path,
168 BTRFS_CRC32_SIZE, 1);
174 if (path->slots[0] == 0) {
178 leaf = btrfs_buffer_leaf(path->nodes[0]);
179 btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key);
180 csum_offset = (offset - found_key.offset) >>
181 root->fs_info->sb->s_blocksize_bits;
182 if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
183 found_key.objectid != objectid ||
184 csum_offset >= MAX_CSUM_ITEMS(root)) {
187 if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) /
189 u32 diff = (csum_offset + 1) * BTRFS_CRC32_SIZE;
190 diff = diff - btrfs_item_size(leaf->items + path->slots[0]);
191 if (diff != BTRFS_CRC32_SIZE)
193 ret = btrfs_extend_item(trans, root, path, diff);
199 btrfs_release_path(root, path);
201 ret = btrfs_insert_empty_item(trans, root, path, &file_key,
204 printk("at insert for %Lu %u %Lu ret is %d\n", file_key.objectid, file_key.flags, file_key.offset, ret);
209 item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
210 struct btrfs_csum_item);
212 item = (struct btrfs_csum_item *)((unsigned char *)item +
213 csum_offset * BTRFS_CRC32_SIZE);
215 btrfs_check_bounds(&item->csum, BTRFS_CRC32_SIZE,
216 path->nodes[0]->b_data,
217 root->fs_info->sb->s_blocksize);
218 ret = btrfs_csum_data(root, data, len, &item->csum);
219 btrfs_mark_buffer_dirty(path->nodes[0]);
221 btrfs_release_path(root, path);
222 btrfs_free_path(path);
226 int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
227 struct btrfs_root *root, struct btrfs_path *path,
230 struct btrfs_key key;
231 struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[0]);
232 int slot = path->slots[0];
238 btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key);
239 if (isize <= key.offset)
241 new_item_span = isize - key.offset;
242 blocks = (new_item_span + root->blocksize - 1) >>
243 root->fs_info->sb->s_blocksize_bits;
244 new_item_size = blocks * BTRFS_CRC32_SIZE;
245 if (new_item_size >= btrfs_item_size(leaf->items + slot))
247 ret = btrfs_truncate_item(trans, root, path, new_item_size);
252 int btrfs_csum_verify_file_block(struct btrfs_root *root,
253 u64 objectid, u64 offset,
254 char *data, size_t len)
257 struct btrfs_key file_key;
258 struct btrfs_path *path;
259 struct btrfs_csum_item *item;
260 char result[BTRFS_CRC32_SIZE];
262 path = btrfs_alloc_path();
264 btrfs_init_path(path);
265 file_key.objectid = objectid;
266 file_key.offset = offset;
268 btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
269 mutex_lock(&root->fs_info->fs_mutex);
271 item = btrfs_lookup_csum(NULL, root, path, objectid, offset, 0);
274 /* a csum that isn't present is a preallocated region. */
275 if (ret == -ENOENT || ret == -EFBIG)
280 ret = btrfs_csum_data(root, data, len, result);
282 if (memcmp(result, &item->csum, BTRFS_CRC32_SIZE))
285 btrfs_release_path(root, path);
286 btrfs_free_path(path);
287 mutex_unlock(&root->fs_info->fs_mutex);