1 #include <linux/module.h>
4 #include "transaction.h"
6 #define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \
7 sizeof(struct btrfs_item) * 2) / \
8 sizeof(struct btrfs_csum_item)) - 1))
9 int btrfs_insert_file_extent(struct btrfs_trans_handle
*trans
,
10 struct btrfs_root
*root
,
11 u64 objectid
, u64 pos
,
12 u64 offset
, u64 num_blocks
)
15 struct btrfs_file_extent_item
*item
;
16 struct btrfs_key file_key
;
17 struct btrfs_path
*path
;
19 path
= btrfs_alloc_path();
21 btrfs_init_path(path
);
22 file_key
.objectid
= objectid
;
23 file_key
.offset
= pos
;
25 btrfs_set_key_type(&file_key
, BTRFS_EXTENT_DATA_KEY
);
27 ret
= btrfs_insert_empty_item(trans
, root
, path
, &file_key
,
30 item
= btrfs_item_ptr(btrfs_buffer_leaf(path
->nodes
[0]), path
->slots
[0],
31 struct btrfs_file_extent_item
);
32 btrfs_set_file_extent_disk_blocknr(item
, offset
);
33 btrfs_set_file_extent_disk_num_blocks(item
, num_blocks
);
34 btrfs_set_file_extent_offset(item
, 0);
35 btrfs_set_file_extent_num_blocks(item
, num_blocks
);
36 btrfs_set_file_extent_generation(item
, trans
->transid
);
37 btrfs_mark_buffer_dirty(path
->nodes
[0]);
39 btrfs_release_path(root
, path
);
40 btrfs_free_path(path
);
44 struct btrfs_csum_item
*btrfs_lookup_csum(struct btrfs_trans_handle
*trans
,
45 struct btrfs_root
*root
,
46 struct btrfs_path
*path
,
47 u64 objectid
, u64 offset
,
51 struct btrfs_key file_key
;
52 struct btrfs_key found_key
;
53 struct btrfs_csum_item
*item
;
54 struct btrfs_leaf
*leaf
;
58 file_key
.objectid
= objectid
;
59 file_key
.offset
= offset
;
61 btrfs_set_key_type(&file_key
, BTRFS_CSUM_ITEM_KEY
);
62 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
, 0, cow
);
65 leaf
= btrfs_buffer_leaf(path
->nodes
[0]);
68 if (path
->slots
[0] == 0)
71 btrfs_disk_key_to_cpu(&found_key
,
72 &leaf
->items
[path
->slots
[0]].key
);
73 if (btrfs_key_type(&found_key
) != BTRFS_CSUM_ITEM_KEY
||
74 found_key
.objectid
!= objectid
) {
77 csum_offset
= (offset
- found_key
.offset
) >>
78 root
->fs_info
->sb
->s_blocksize_bits
;
79 csums_in_item
= btrfs_item_size(leaf
->items
+ path
->slots
[0]);
80 csums_in_item
/= sizeof(struct btrfs_csum_item
);
82 if (csum_offset
>= csums_in_item
) {
87 item
= btrfs_item_ptr(leaf
, path
->slots
[0], struct btrfs_csum_item
);
97 int btrfs_lookup_file_extent(struct btrfs_trans_handle
*trans
,
98 struct btrfs_root
*root
,
99 struct btrfs_path
*path
, u64 objectid
,
103 struct btrfs_key file_key
;
104 int ins_len
= mod
< 0 ? -1 : 0;
107 file_key
.objectid
= objectid
;
108 file_key
.offset
= offset
;
110 btrfs_set_key_type(&file_key
, BTRFS_EXTENT_DATA_KEY
);
111 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
, ins_len
, cow
);
115 int btrfs_csum_file_block(struct btrfs_trans_handle
*trans
,
116 struct btrfs_root
*root
,
117 u64 objectid
, u64 offset
,
118 char *data
, size_t len
)
121 struct btrfs_key file_key
;
122 struct btrfs_key found_key
;
123 struct btrfs_path
*path
;
124 struct btrfs_csum_item
*item
;
125 struct btrfs_leaf
*leaf
;
128 path
= btrfs_alloc_path();
131 file_key
.objectid
= objectid
;
132 file_key
.offset
= offset
;
134 btrfs_set_key_type(&file_key
, BTRFS_CSUM_ITEM_KEY
);
136 item
= btrfs_lookup_csum(trans
, root
, path
, objectid
, offset
, 1);
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 */
151 /* we didn't find a csum item, insert one */
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
159 btrfs_release_path(root
, path
);
160 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
,
161 sizeof(struct btrfs_csum_item
), 1);
167 if (path
->slots
[0] == 0) {
171 leaf
= btrfs_buffer_leaf(path
->nodes
[0]);
172 btrfs_disk_key_to_cpu(&found_key
, &leaf
->items
[path
->slots
[0]].key
);
173 csum_offset
= (offset
- found_key
.offset
) >>
174 root
->fs_info
->sb
->s_blocksize_bits
;
175 if (btrfs_key_type(&found_key
) != BTRFS_CSUM_ITEM_KEY
||
176 found_key
.objectid
!= objectid
||
177 csum_offset
>= MAX_CSUM_ITEMS(root
)) {
181 if (csum_offset
>= btrfs_item_size(leaf
->items
+ path
->slots
[0]) /
182 sizeof(struct btrfs_csum_item
)) {
183 u32 diff
= (csum_offset
+ 1) * 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
);
192 btrfs_release_path(root
, path
);
194 ret
= btrfs_insert_empty_item(trans
, root
, path
, &file_key
,
195 sizeof(struct btrfs_csum_item
));
197 printk("at insert for %Lu %u %Lu ret is %d\n", file_key
.objectid
, file_key
.flags
, file_key
.offset
, ret
);
202 item
= btrfs_item_ptr(btrfs_buffer_leaf(path
->nodes
[0]), path
->slots
[0],
203 struct btrfs_csum_item
);
207 btrfs_check_bounds(item
->csum
, BTRFS_CSUM_SIZE
, path
->nodes
[0]->b_data
, root
->fs_info
->sb
->s_blocksize
);
208 ret
= btrfs_csum_data(root
, data
, len
, item
->csum
);
209 btrfs_mark_buffer_dirty(path
->nodes
[0]);
211 btrfs_release_path(root
, path
);
212 btrfs_free_path(path
);
216 int btrfs_csum_verify_file_block(struct btrfs_root
*root
,
217 u64 objectid
, u64 offset
,
218 char *data
, size_t len
)
221 struct btrfs_key file_key
;
222 struct btrfs_path
*path
;
223 struct btrfs_csum_item
*item
;
224 char result
[BTRFS_CSUM_SIZE
];
226 path
= btrfs_alloc_path();
228 btrfs_init_path(path
);
229 file_key
.objectid
= objectid
;
230 file_key
.offset
= offset
;
232 btrfs_set_key_type(&file_key
, BTRFS_CSUM_ITEM_KEY
);
233 mutex_lock(&root
->fs_info
->fs_mutex
);
235 item
= btrfs_lookup_csum(NULL
, root
, path
, objectid
, offset
, 0);
238 /* a csum that isn't present is a preallocated region. */
239 if (ret
== -ENOENT
|| ret
== -EFBIG
)
244 ret
= btrfs_csum_data(root
, data
, len
, result
);
246 if (memcmp(result
, item
->csum
, BTRFS_CSUM_SIZE
))
249 btrfs_release_path(root
, path
);
250 btrfs_free_path(path
);
251 mutex_unlock(&root
->fs_info
->fs_mutex
);
This page took 0.06009 seconds and 6 git commands to generate.