aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file-item.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r--fs/btrfs/file-item.c114
1 files changed, 111 insertions, 3 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 3ebef871ee6c..df0447632dbd 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -140,6 +140,7 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
140 return ret; 140 return ret;
141} 141}
142 142
143
143int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, 144int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
144 struct bio *bio, u32 *dst) 145 struct bio *bio, u32 *dst)
145{ 146{
@@ -185,9 +186,16 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
185 if (ret == -ENOENT || ret == -EFBIG) 186 if (ret == -ENOENT || ret == -EFBIG)
186 ret = 0; 187 ret = 0;
187 sum = 0; 188 sum = 0;
188 printk("no csum found for inode %lu start " 189 if (BTRFS_I(inode)->root->root_key.objectid ==
189 "%llu\n", inode->i_ino, 190 BTRFS_DATA_RELOC_TREE_OBJECTID) {
190 (unsigned long long)offset); 191 set_extent_bits(io_tree, offset,
192 offset + bvec->bv_len - 1,
193 EXTENT_NODATASUM, GFP_NOFS);
194 } else {
195 printk("no csum found for inode %lu "
196 "start %llu\n", inode->i_ino,
197 (unsigned long long)offset);
198 }
191 item = NULL; 199 item = NULL;
192 btrfs_release_path(root, path); 200 btrfs_release_path(root, path);
193 goto found; 201 goto found;
@@ -228,6 +236,106 @@ found:
228 return 0; 236 return 0;
229} 237}
230 238
239int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
240 struct list_head *list)
241{
242 struct btrfs_key key;
243 struct btrfs_path *path;
244 struct extent_buffer *leaf;
245 struct btrfs_ordered_sum *sums;
246 struct btrfs_sector_sum *sector_sum;
247 struct btrfs_csum_item *item;
248 unsigned long offset;
249 int ret;
250 size_t size;
251 u64 csum_end;
252 u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy);
253
254 path = btrfs_alloc_path();
255 BUG_ON(!path);
256
257 key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
258 key.offset = start;
259 key.type = BTRFS_EXTENT_CSUM_KEY;
260
261 ret = btrfs_search_slot(NULL, root->fs_info->csum_root,
262 &key, path, 0, 0);
263 if (ret < 0)
264 goto fail;
265 if (ret > 0 && path->slots[0] > 0) {
266 leaf = path->nodes[0];
267 btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
268 if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID &&
269 key.type == BTRFS_EXTENT_CSUM_KEY) {
270 offset = (start - key.offset) >>
271 root->fs_info->sb->s_blocksize_bits;
272 if (offset * csum_size <
273 btrfs_item_size_nr(leaf, path->slots[0] - 1))
274 path->slots[0]--;
275 }
276 }
277
278 while (start <= end) {
279 leaf = path->nodes[0];
280 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
281 ret = btrfs_next_leaf(root->fs_info->csum_root, path);
282 if (ret < 0)
283 goto fail;
284 if (ret > 0)
285 break;
286 leaf = path->nodes[0];
287 }
288
289 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
290 if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
291 key.type != BTRFS_EXTENT_CSUM_KEY)
292 break;
293
294 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
295 if (key.offset > end)
296 break;
297
298 if (key.offset > start)
299 start = key.offset;
300
301 size = btrfs_item_size_nr(leaf, path->slots[0]);
302 csum_end = key.offset + (size / csum_size) * root->sectorsize;
303
304 size = min(csum_end, end + 1) - start;
305 sums = kzalloc(btrfs_ordered_sum_size(root, size), GFP_NOFS);
306 BUG_ON(!sums);
307
308 sector_sum = sums->sums;
309 sums->bytenr = start;
310 sums->len = size;
311
312 offset = (start - key.offset) >>
313 root->fs_info->sb->s_blocksize_bits;
314 offset *= csum_size;
315
316 item = btrfs_item_ptr(path->nodes[0], path->slots[0],
317 struct btrfs_csum_item);
318 while (size > 0) {
319 read_extent_buffer(path->nodes[0], &sector_sum->sum,
320 ((unsigned long)item) + offset,
321 csum_size);
322 sector_sum->bytenr = start;
323
324 size -= root->sectorsize;
325 start += root->sectorsize;
326 offset += csum_size;
327 sector_sum++;
328 }
329 list_add_tail(&sums->list, list);
330
331 path->slots[0]++;
332 }
333 ret = 0;
334fail:
335 btrfs_free_path(path);
336 return ret;
337}
338
231int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, 339int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
232 struct bio *bio, u64 file_start, int contig) 340 struct bio *bio, u64 file_start, int contig)
233{ 341{