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 item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
33 struct btrfs_file_extent_item);
34 btrfs_set_file_extent_disk_blocknr(item, offset);
35 btrfs_set_file_extent_disk_num_blocks(item, disk_num_blocks);
36 btrfs_set_file_extent_offset(item, 0);
37 btrfs_set_file_extent_num_blocks(item, num_blocks);
38 btrfs_set_file_extent_generation(item, trans->transid);
39 btrfs_set_file_extent_type(item, BTRFS_FILE_EXTENT_REG);
40 btrfs_mark_buffer_dirty(path->nodes[0]);
42 btrfs_release_path(root, path);
43 btrfs_free_path(path);
47 struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
48 struct btrfs_root *root,
49 struct btrfs_path *path,
50 u64 objectid, u64 offset,
54 struct btrfs_key file_key;
55 struct btrfs_key found_key;
56 struct btrfs_csum_item *item;
57 struct btrfs_leaf *leaf;
61 file_key.objectid = objectid;
62 file_key.offset = offset;
64 btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
65 ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
68 leaf = btrfs_buffer_leaf(path->nodes[0]);
71 if (path->slots[0] == 0)
74 btrfs_disk_key_to_cpu(&found_key,
75 &leaf->items[path->slots[0]].key);
76 if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
77 found_key.objectid != objectid) {
80 csum_offset = (offset - found_key.offset) >>
81 root->fs_info->sb->s_blocksize_bits;
82 csums_in_item = btrfs_item_size(leaf->items + path->slots[0]);
83 csums_in_item /= BTRFS_CRC32_SIZE;
85 if (csum_offset >= csums_in_item) {
90 item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
91 item = (struct btrfs_csum_item *)((unsigned char *)item +
92 csum_offset * BTRFS_CRC32_SIZE);
101 int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
102 struct btrfs_root *root,
103 struct btrfs_path *path, u64 objectid,
107 struct btrfs_key file_key;
108 int ins_len = mod < 0 ? -1 : 0;
111 file_key.objectid = objectid;
112 file_key.offset = offset;
114 btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
115 ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
119 int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
120 struct btrfs_root *root,
121 u64 objectid, u64 offset,
122 char *data, size_t len)
125 struct btrfs_key file_key;
126 struct btrfs_key found_key;
127 struct btrfs_path *path;
128 struct btrfs_csum_item *item;
129 struct btrfs_leaf *leaf;
132 path = btrfs_alloc_path();
135 file_key.objectid = objectid;
136 file_key.offset = offset;
138 btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
140 item = btrfs_lookup_csum(trans, root, path, objectid, offset, 1);
146 /* we found one, but it isn't big enough yet */
147 leaf = btrfs_buffer_leaf(path->nodes[0]);
148 item_size = btrfs_item_size(leaf->items + path->slots[0]);
149 if ((item_size / BTRFS_CRC32_SIZE) >= MAX_CSUM_ITEMS(root)) {
150 /* already at max size, make a new one */
154 /* we didn't find a csum item, insert one */
159 * at this point, we know the tree has an item, but it isn't big
160 * enough yet to put our csum in. Grow it
162 btrfs_release_path(root, path);
163 ret = btrfs_search_slot(trans, root, &file_key, path,
164 BTRFS_CRC32_SIZE, 1);
170 if (path->slots[0] == 0) {
174 leaf = btrfs_buffer_leaf(path->nodes[0]);
175 btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key);
176 csum_offset = (offset - found_key.offset) >>
177 root->fs_info->sb->s_blocksize_bits;
178 if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
179 found_key.objectid != objectid ||
180 csum_offset >= MAX_CSUM_ITEMS(root)) {
183 if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) /
185 u32 diff = (csum_offset + 1) * BTRFS_CRC32_SIZE;
186 diff = diff - btrfs_item_size(leaf->items + path->slots[0]);
187 if (diff != BTRFS_CRC32_SIZE)
189 ret = btrfs_extend_item(trans, root, path, diff);
195 btrfs_release_path(root, path);
197 ret = btrfs_insert_empty_item(trans, root, path, &file_key,
204 item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
205 struct btrfs_csum_item);
207 item = (struct btrfs_csum_item *)((unsigned char *)item +
208 csum_offset * BTRFS_CRC32_SIZE);
210 btrfs_check_bounds(&item->csum, BTRFS_CRC32_SIZE,
211 path->nodes[0]->b_data,
212 root->fs_info->sb->s_blocksize);
213 ret = btrfs_csum_data(root, data, len, &item->csum);
214 btrfs_mark_buffer_dirty(path->nodes[0]);
216 btrfs_release_path(root, path);
217 btrfs_free_path(path);
221 int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
222 struct btrfs_root *root, struct btrfs_path *path,
225 struct btrfs_key key;
226 struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[0]);
227 int slot = path->slots[0];
233 btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key);
234 if (isize <= key.offset)
236 new_item_span = isize - key.offset;
237 blocks = (new_item_span + root->blocksize - 1) >>
238 root->fs_info->sb->s_blocksize_bits;
239 new_item_size = blocks * BTRFS_CRC32_SIZE;
240 if (new_item_size >= btrfs_item_size(leaf->items + slot))
242 ret = btrfs_truncate_item(trans, root, path, new_item_size);
247 int btrfs_csum_verify_file_block(struct btrfs_root *root,
248 u64 objectid, u64 offset,
249 char *data, size_t len)
252 struct btrfs_key file_key;
253 struct btrfs_path *path;
254 struct btrfs_csum_item *item;
255 char result[BTRFS_CRC32_SIZE];
257 path = btrfs_alloc_path();
259 btrfs_init_path(path);
260 file_key.objectid = objectid;
261 file_key.offset = offset;
263 btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
264 mutex_lock(&root->fs_info->fs_mutex);
266 item = btrfs_lookup_csum(NULL, root, path, objectid, offset, 0);
269 /* a csum that isn't present is a preallocated region. */
270 if (ret == -ENOENT || ret == -EFBIG)
275 ret = btrfs_csum_data(root, data, len, result);
277 if (memcmp(result, &item->csum, BTRFS_CRC32_SIZE))
280 btrfs_release_path(root, path);
281 btrfs_free_path(path);
282 mutex_unlock(&root->fs_info->fs_mutex);