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.
21 #include "transaction.h"
22 #include "print-tree.h"
24 #define MAX_CSUM_ITEMS(r) ((((BTRFS_LEAF_DATA_SIZE(r) - \
25 sizeof(struct btrfs_item) * 2) / \
26 BTRFS_CRC32_SIZE) - 1))
27 int btrfs_insert_file_extent(struct btrfs_trans_handle
*trans
,
28 struct btrfs_root
*root
,
29 u64 objectid
, u64 pos
,
30 u64 offset
, u64 disk_num_bytes
,
34 struct btrfs_file_extent_item
*item
;
35 struct btrfs_key file_key
;
36 struct btrfs_path
*path
;
37 struct extent_buffer
*leaf
;
39 path
= btrfs_alloc_path();
41 file_key
.objectid
= objectid
;
42 file_key
.offset
= pos
;
43 btrfs_set_key_type(&file_key
, BTRFS_EXTENT_DATA_KEY
);
45 ret
= btrfs_insert_empty_item(trans
, root
, path
, &file_key
,
50 leaf
= path
->nodes
[0];
51 item
= btrfs_item_ptr(leaf
, path
->slots
[0],
52 struct btrfs_file_extent_item
);
53 btrfs_set_file_extent_disk_bytenr(leaf
, item
, offset
);
54 btrfs_set_file_extent_disk_num_bytes(leaf
, item
, disk_num_bytes
);
55 btrfs_set_file_extent_offset(leaf
, item
, 0);
56 btrfs_set_file_extent_num_bytes(leaf
, item
, num_bytes
);
57 btrfs_set_file_extent_generation(leaf
, item
, trans
->transid
);
58 btrfs_set_file_extent_type(leaf
, item
, BTRFS_FILE_EXTENT_REG
);
59 btrfs_mark_buffer_dirty(leaf
);
61 btrfs_free_path(path
);
65 struct btrfs_csum_item
*btrfs_lookup_csum(struct btrfs_trans_handle
*trans
,
66 struct btrfs_root
*root
,
67 struct btrfs_path
*path
,
68 u64 objectid
, u64 offset
,
72 struct btrfs_key file_key
;
73 struct btrfs_key found_key
;
74 struct btrfs_csum_item
*item
;
75 struct extent_buffer
*leaf
;
79 file_key
.objectid
= objectid
;
80 file_key
.offset
= offset
;
81 btrfs_set_key_type(&file_key
, BTRFS_CSUM_ITEM_KEY
);
82 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
, 0, cow
);
85 leaf
= path
->nodes
[0];
88 if (path
->slots
[0] == 0)
91 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
92 if (btrfs_key_type(&found_key
) != BTRFS_CSUM_ITEM_KEY
||
93 found_key
.objectid
!= objectid
) {
96 csum_offset
= (offset
- found_key
.offset
) >>
97 root
->fs_info
->sb
->s_blocksize_bits
;
98 csums_in_item
= btrfs_item_size_nr(leaf
, path
->slots
[0]);
99 csums_in_item
/= BTRFS_CRC32_SIZE
;
101 if (csum_offset
>= csums_in_item
) {
106 item
= btrfs_item_ptr(leaf
, path
->slots
[0], struct btrfs_csum_item
);
107 item
= (struct btrfs_csum_item
*)((unsigned char *)item
+
108 csum_offset
* BTRFS_CRC32_SIZE
);
117 int btrfs_lookup_file_extent(struct btrfs_trans_handle
*trans
,
118 struct btrfs_root
*root
,
119 struct btrfs_path
*path
, u64 objectid
,
123 struct btrfs_key file_key
;
124 int ins_len
= mod
< 0 ? -1 : 0;
127 file_key
.objectid
= objectid
;
128 file_key
.offset
= offset
;
129 btrfs_set_key_type(&file_key
, BTRFS_EXTENT_DATA_KEY
);
130 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
, ins_len
, cow
);
134 int btrfs_csum_file_block(struct btrfs_trans_handle
*trans
,
135 struct btrfs_root
*root
,
136 u64 objectid
, u64 offset
,
137 char *data
, size_t len
)
142 struct btrfs_key file_key
;
143 struct btrfs_key found_key
;
144 struct btrfs_path
*path
;
145 struct btrfs_csum_item
*item
;
146 struct extent_buffer
*leaf
;
149 path
= btrfs_alloc_path();
152 file_key
.objectid
= objectid
;
153 file_key
.offset
= offset
;
155 btrfs_set_key_type(&file_key
, BTRFS_CSUM_ITEM_KEY
);
157 item
= btrfs_lookup_csum(trans
, root
, path
, objectid
, offset
, 1);
163 /* we found one, but it isn't big enough yet */
164 leaf
= path
->nodes
[0];
165 item_size
= btrfs_item_size_nr(leaf
, path
->slots
[0]);
166 if ((item_size
/ BTRFS_CRC32_SIZE
) >= MAX_CSUM_ITEMS(root
)) {
167 /* already at max size, make a new one */
171 /* we didn't find a csum item, insert one */
176 * at this point, we know the tree has an item, but it isn't big
177 * enough yet to put our csum in. Grow it
179 btrfs_release_path(root
, path
);
180 ret
= btrfs_search_slot(trans
, root
, &file_key
, path
,
181 BTRFS_CRC32_SIZE
, 1);
187 if (path
->slots
[0] == 0) {
191 leaf
= path
->nodes
[0];
192 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
193 csum_offset
= (offset
- found_key
.offset
) >>
194 root
->fs_info
->sb
->s_blocksize_bits
;
195 if (btrfs_key_type(&found_key
) != BTRFS_CSUM_ITEM_KEY
||
196 found_key
.objectid
!= objectid
||
197 csum_offset
>= MAX_CSUM_ITEMS(root
)) {
200 if (csum_offset
>= btrfs_item_size_nr(leaf
, path
->slots
[0]) /
202 u32 diff
= (csum_offset
+ 1) * BTRFS_CRC32_SIZE
;
203 diff
= diff
- btrfs_item_size_nr(leaf
, path
->slots
[0]);
204 if (diff
!= BTRFS_CRC32_SIZE
)
206 ret
= btrfs_extend_item(trans
, root
, path
, diff
);
212 btrfs_release_path(root
, path
);
214 ret
= btrfs_insert_empty_item(trans
, root
, path
, &file_key
,
223 leaf
= path
->nodes
[0];
224 item
= btrfs_item_ptr(leaf
, path
->slots
[0], struct btrfs_csum_item
);
226 item
= (struct btrfs_csum_item
*)((unsigned char *)item
+
227 csum_offset
* BTRFS_CRC32_SIZE
);
229 /* FIXME!!!!!!!!!!!! */
230 ret
= btrfs_csum_data(root
, data
, len
, &item
->csum
);
231 btrfs_mark_buffer_dirty(path
->nodes
[0]);
233 btrfs_release_path(root
, path
);
234 btrfs_free_path(path
);
239 int btrfs_csum_truncate(struct btrfs_trans_handle
*trans
,
240 struct btrfs_root
*root
, struct btrfs_path
*path
,
243 struct btrfs_key key
;
244 struct extent_buffer
*leaf
= path
->nodes
[0];
245 int slot
= path
->slots
[0];
251 btrfs_item_key_to_cpu(leaf
, &key
, slot
);
252 if (isize
<= key
.offset
)
254 new_item_span
= isize
- key
.offset
;
255 blocks
= (new_item_span
+ root
->sectorsize
- 1) >>
256 root
->fs_info
->sb
->s_blocksize_bits
;
257 new_item_size
= blocks
* BTRFS_CRC32_SIZE
;
258 if (new_item_size
>= btrfs_item_size_nr(leaf
, slot
))
260 ret
= btrfs_truncate_item(trans
, root
, path
, new_item_size
);
This page took 0.04764 seconds and 5 git commands to generate.