2 * Copyright (C) 2007 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #include <linux/bio.h>
20 #include <linux/pagemap.h>
21 #include <linux/highmem.h>
24 #include "transaction.h"
25 #include "print-tree.h"
27 #define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \
28 sizeof(struct btrfs_item) * 2) / \
29 BTRFS_CRC32_SIZE) - 1))
30 int btrfs_insert_file_extent(struct btrfs_trans_handle
*trans
,
31 struct btrfs_root
*root
,
32 u64 objectid
, u64 pos
,
33 u64 disk_offset
, u64 disk_num_bytes
,
34 u64 num_bytes
, u64 offset
)
37 struct btrfs_file_extent_item
*item
;
38 struct btrfs_key file_key
;
39 struct btrfs_path
*path
;
40 struct extent_buffer
*leaf
;
42 path
= btrfs_alloc_path();
44 file_key
.objectid
= objectid
;
45 file_key
.offset
= pos
;
46 btrfs_set_key_type(&file_key
, BTRFS_EXTENT_DATA_KEY
);
48 ret
= btrfs_insert_empty_item(trans
, root
, path
, &file_key
,
53 leaf
= path
->nodes
[0];
54 item
= btrfs_item_ptr(leaf
, path
->slots
[0],
55 struct btrfs_file_extent_item
);
56 btrfs_set_file_extent_disk_bytenr(leaf
, item
, disk_offset
);
57 btrfs_set_file_extent_disk_num_bytes(leaf
, item
, disk_num_bytes
);
58 btrfs_set_file_extent_offset(leaf
, item
, offset
);
59 btrfs_set_file_extent_num_bytes(leaf
, item
, num_bytes
);
60 btrfs_set_file_extent_generation(leaf
, item
, trans
->transid
);
61 btrfs_set_file_extent_type(leaf
, item
, BTRFS_FILE_EXTENT_REG
);
62 btrfs_mark_buffer_dirty(leaf
);
64 btrfs_free_path(path
);
68 struct btrfs_csum_item
*btrfs_lookup_csum(struct btrfs_trans_handle
*trans
,
69 struct btrfs_root
*root
,
70 struct btrfs_path
*path
,
71 u64 objectid
, u64 offset
,
75 struct btrfs_key file_key
;
76 struct btrfs_key found_key
;
77 struct btrfs_csum_item
*item
;
78 struct extent_buffer
*leaf
;
82 file_key
.objectid
= objectid
;
83 file_key
.offset
= offset
;
84 btrfs_set_key_type(&file_key
, BTRFS_CSUM_ITEM_KEY
);
85 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
, 0, cow
);
88 leaf
= path
->nodes
[0];
91 if (path
->slots
[0] == 0)
94 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
95 if (btrfs_key_type(&found_key
) != BTRFS_CSUM_ITEM_KEY
||
96 found_key
.objectid
!= objectid
) {
99 csum_offset
= (offset
- found_key
.offset
) >>
100 root
->fs_info
->sb
->s_blocksize_bits
;
101 csums_in_item
= btrfs_item_size_nr(leaf
, path
->slots
[0]);
102 csums_in_item
/= BTRFS_CRC32_SIZE
;
104 if (csum_offset
>= csums_in_item
) {
109 item
= btrfs_item_ptr(leaf
, path
->slots
[0], struct btrfs_csum_item
);
110 item
= (struct btrfs_csum_item
*)((unsigned char *)item
+
111 csum_offset
* BTRFS_CRC32_SIZE
);
120 int btrfs_lookup_file_extent(struct btrfs_trans_handle
*trans
,
121 struct btrfs_root
*root
,
122 struct btrfs_path
*path
, u64 objectid
,
126 struct btrfs_key file_key
;
127 int ins_len
= mod
< 0 ? -1 : 0;
130 file_key
.objectid
= objectid
;
131 file_key
.offset
= offset
;
132 btrfs_set_key_type(&file_key
, BTRFS_EXTENT_DATA_KEY
);
133 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
, ins_len
, cow
);
138 int btrfs_lookup_bio_sums(struct btrfs_root
*root
, struct inode
*inode
,
142 struct bio_vec
*bvec
= bio
->bi_io_vec
;
145 u64 item_start_offset
= 0;
146 u64 item_last_offset
= 0;
149 struct btrfs_path
*path
;
150 struct btrfs_csum_item
*item
= NULL
;
151 struct extent_io_tree
*io_tree
= &BTRFS_I(inode
)->io_tree
;
153 path
= btrfs_alloc_path();
155 WARN_ON(bio
->bi_vcnt
<= 0);
157 while(bio_index
< bio
->bi_vcnt
) {
158 offset
= page_offset(bvec
->bv_page
) + bvec
->bv_offset
;
159 ret
= btrfs_find_ordered_sum(inode
, offset
, &sum
);
163 if (!item
|| offset
< item_start_offset
||
164 offset
>= item_last_offset
) {
165 struct btrfs_key found_key
;
169 btrfs_release_path(root
, path
);
170 item
= btrfs_lookup_csum(NULL
, root
, path
,
171 inode
->i_ino
, offset
, 0);
174 if (ret
== -ENOENT
|| ret
== -EFBIG
)
177 printk("no csum found for inode %lu start "
178 "%llu\n", inode
->i_ino
,
179 (unsigned long long)offset
);
183 btrfs_item_key_to_cpu(path
->nodes
[0], &found_key
,
186 item_start_offset
= found_key
.offset
;
187 item_size
= btrfs_item_size_nr(path
->nodes
[0],
189 item_last_offset
= item_start_offset
+
190 (item_size
/ BTRFS_CRC32_SIZE
) *
192 item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
193 struct btrfs_csum_item
);
196 * this byte range must be able to fit inside
197 * a single leaf so it will also fit inside a u32
199 diff
= offset
- item_start_offset
;
200 diff
= diff
/ root
->sectorsize
;
201 diff
= diff
* BTRFS_CRC32_SIZE
;
203 read_extent_buffer(path
->nodes
[0], &sum
,
204 ((unsigned long)item
) + diff
,
207 set_state_private(io_tree
, offset
, sum
);
211 btrfs_free_path(path
);
216 int btrfs_csum_one_bio(struct btrfs_root
*root
, struct inode
*inode
,
219 struct btrfs_ordered_sum
*sums
;
220 struct btrfs_sector_sum
*sector_sum
;
221 struct btrfs_ordered_extent
*ordered
;
223 struct bio_vec
*bvec
= bio
->bi_io_vec
;
225 unsigned long total_bytes
= 0;
226 unsigned long this_sum_bytes
= 0;
229 WARN_ON(bio
->bi_vcnt
<= 0);
230 sums
= kzalloc(btrfs_ordered_sum_size(root
, bio
->bi_size
), GFP_NOFS
);
234 sector_sum
= sums
->sums
;
235 sums
->file_offset
= page_offset(bvec
->bv_page
) + bvec
->bv_offset
;
236 sums
->len
= bio
->bi_size
;
237 INIT_LIST_HEAD(&sums
->list
);
238 ordered
= btrfs_lookup_ordered_extent(inode
, sums
->file_offset
);
241 while(bio_index
< bio
->bi_vcnt
) {
242 offset
= page_offset(bvec
->bv_page
) + bvec
->bv_offset
;
243 if (offset
>= ordered
->file_offset
+ ordered
->len
||
244 offset
< ordered
->file_offset
) {
245 unsigned long bytes_left
;
246 sums
->len
= this_sum_bytes
;
248 btrfs_add_ordered_sum(inode
, ordered
, sums
);
249 btrfs_put_ordered_extent(ordered
);
251 bytes_left
= bio
->bi_size
- total_bytes
;
253 sums
= kzalloc(btrfs_ordered_sum_size(root
, bytes_left
),
256 sector_sum
= sums
->sums
;
257 sums
->len
= bytes_left
;
258 sums
->file_offset
= offset
;
259 ordered
= btrfs_lookup_ordered_extent(inode
,
264 data
= kmap_atomic(bvec
->bv_page
, KM_USER0
);
265 sector_sum
->sum
= ~(u32
)0;
266 sector_sum
->sum
= btrfs_csum_data(root
,
267 data
+ bvec
->bv_offset
,
270 kunmap_atomic(data
, KM_USER0
);
271 btrfs_csum_final(sector_sum
->sum
,
272 (char *)§or_sum
->sum
);
273 sector_sum
->offset
= page_offset(bvec
->bv_page
) +
278 total_bytes
+= bvec
->bv_len
;
279 this_sum_bytes
+= bvec
->bv_len
;
283 btrfs_add_ordered_sum(inode
, ordered
, sums
);
284 btrfs_put_ordered_extent(ordered
);
288 int btrfs_csum_file_blocks(struct btrfs_trans_handle
*trans
,
289 struct btrfs_root
*root
, struct inode
*inode
,
290 struct btrfs_ordered_sum
*sums
)
292 u64 objectid
= inode
->i_ino
;
295 struct btrfs_key file_key
;
296 struct btrfs_key found_key
;
300 struct btrfs_path
*path
;
301 struct btrfs_csum_item
*item
;
302 struct btrfs_csum_item
*item_end
;
303 struct extent_buffer
*leaf
= NULL
;
305 struct btrfs_sector_sum
*sector_sum
;
310 unsigned long map_len
;
311 unsigned long map_start
;
313 path
= btrfs_alloc_path();
315 sector_sum
= sums
->sums
;
317 next_offset
= (u64
)-1;
319 offset
= sector_sum
->offset
;
320 file_key
.objectid
= objectid
;
321 file_key
.offset
= offset
;
322 btrfs_set_key_type(&file_key
, BTRFS_CSUM_ITEM_KEY
);
324 item
= btrfs_lookup_csum(trans
, root
, path
, objectid
, offset
, 1);
326 leaf
= path
->nodes
[0];
332 /* we found one, but it isn't big enough yet */
333 leaf
= path
->nodes
[0];
334 item_size
= btrfs_item_size_nr(leaf
, path
->slots
[0]);
335 if ((item_size
/ BTRFS_CRC32_SIZE
) >= MAX_CSUM_ITEMS(root
)) {
336 /* already at max size, make a new one */
340 int slot
= path
->slots
[0] + 1;
341 /* we didn't find a csum item, insert one */
342 nritems
= btrfs_header_nritems(path
->nodes
[0]);
343 if (path
->slots
[0] >= nritems
- 1) {
344 ret
= btrfs_next_leaf(root
, path
);
351 btrfs_item_key_to_cpu(path
->nodes
[0], &found_key
, slot
);
352 if (found_key
.objectid
!= objectid
||
353 found_key
.type
!= BTRFS_CSUM_ITEM_KEY
) {
357 next_offset
= found_key
.offset
;
363 * at this point, we know the tree has an item, but it isn't big
364 * enough yet to put our csum in. Grow it
366 btrfs_release_path(root
, path
);
367 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
,
368 BTRFS_CRC32_SIZE
, 1);
374 if (path
->slots
[0] == 0) {
378 leaf
= path
->nodes
[0];
379 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
380 csum_offset
= (offset
- found_key
.offset
) >>
381 root
->fs_info
->sb
->s_blocksize_bits
;
382 if (btrfs_key_type(&found_key
) != BTRFS_CSUM_ITEM_KEY
||
383 found_key
.objectid
!= objectid
||
384 csum_offset
>= MAX_CSUM_ITEMS(root
)) {
387 if (csum_offset
>= btrfs_item_size_nr(leaf
, path
->slots
[0]) /
389 u32 diff
= (csum_offset
+ 1) * BTRFS_CRC32_SIZE
;
390 diff
= diff
- btrfs_item_size_nr(leaf
, path
->slots
[0]);
391 if (diff
!= BTRFS_CRC32_SIZE
)
393 ret
= btrfs_extend_item(trans
, root
, path
, diff
);
399 btrfs_release_path(root
, path
);
402 u64 tmp
= min((u64
)i_size_read(inode
), next_offset
);
403 tmp
-= offset
& ~((u64
)root
->sectorsize
-1);
404 tmp
>>= root
->fs_info
->sb
->s_blocksize_bits
;
405 tmp
= max((u64
)1, tmp
);
406 tmp
= min(tmp
, (u64
)MAX_CSUM_ITEMS(root
));
407 ins_size
= BTRFS_CRC32_SIZE
* tmp
;
409 ins_size
= BTRFS_CRC32_SIZE
;
411 ret
= btrfs_insert_empty_item(trans
, root
, path
, &file_key
,
420 leaf
= path
->nodes
[0];
421 item
= btrfs_item_ptr(leaf
, path
->slots
[0], struct btrfs_csum_item
);
423 item
= (struct btrfs_csum_item
*)((unsigned char *)item
+
424 csum_offset
* BTRFS_CRC32_SIZE
);
426 item_end
= btrfs_item_ptr(leaf
, path
->slots
[0], struct btrfs_csum_item
);
427 item_end
= (struct btrfs_csum_item
*)((unsigned char *)item_end
+
428 btrfs_item_size_nr(leaf
, path
->slots
[0]));
433 (unsigned long)item
+ BTRFS_CRC32_SIZE
>= map_start
+ map_len
) {
437 unmap_extent_buffer(leaf
, eb_token
, KM_USER1
);
439 err
= map_private_extent_buffer(leaf
, (unsigned long)item
,
442 &map_start
, &map_len
, KM_USER1
);
447 memcpy(eb_token
+ ((unsigned long)item
& (PAGE_CACHE_SIZE
- 1)),
448 §or_sum
->sum
, BTRFS_CRC32_SIZE
);
450 write_extent_buffer(leaf
, §or_sum
->sum
,
451 (unsigned long)item
, BTRFS_CRC32_SIZE
);
454 total_bytes
+= root
->sectorsize
;
456 if (total_bytes
< sums
->len
) {
457 item
= (struct btrfs_csum_item
*)((char *)item
+
459 if (item
< item_end
&& offset
+ PAGE_CACHE_SIZE
==
460 sector_sum
->offset
) {
461 offset
= sector_sum
->offset
;
466 unmap_extent_buffer(leaf
, eb_token
, KM_USER1
);
469 btrfs_mark_buffer_dirty(path
->nodes
[0]);
470 if (total_bytes
< sums
->len
) {
471 btrfs_release_path(root
, path
);
475 btrfs_free_path(path
);
479 int btrfs_csum_truncate(struct btrfs_trans_handle
*trans
,
480 struct btrfs_root
*root
, struct btrfs_path
*path
,
483 struct btrfs_key key
;
484 struct extent_buffer
*leaf
= path
->nodes
[0];
485 int slot
= path
->slots
[0];
491 btrfs_item_key_to_cpu(leaf
, &key
, slot
);
492 if (isize
<= key
.offset
)
494 new_item_span
= isize
- key
.offset
;
495 blocks
= (new_item_span
+ root
->sectorsize
- 1) >>
496 root
->fs_info
->sb
->s_blocksize_bits
;
497 new_item_size
= blocks
* BTRFS_CRC32_SIZE
;
498 if (new_item_size
>= btrfs_item_size_nr(leaf
, slot
))
500 ret
= btrfs_truncate_item(trans
, root
, path
, new_item_size
, 1);