file-item.c revision 315a9850da2b89c83971b26fe54a60f22bdd91ad
1/* 2 * Copyright (C) 2007 Oracle. All rights reserved. 3 * 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. 7 * 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. 12 * 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. 17 */ 18 19#include <linux/bio.h> 20#include <linux/slab.h> 21#include <linux/pagemap.h> 22#include <linux/highmem.h> 23#include "ctree.h" 24#include "disk-io.h" 25#include "transaction.h" 26#include "print-tree.h" 27 28#define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \ 29 sizeof(struct btrfs_item) * 2) / \ 30 size) - 1)) 31 32#define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \ 33 PAGE_CACHE_SIZE)) 34 35#define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \ 36 sizeof(struct btrfs_ordered_sum)) / \ 37 sizeof(struct btrfs_sector_sum) * \ 38 (r)->sectorsize - (r)->sectorsize) 39 40int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, 41 struct btrfs_root *root, 42 u64 objectid, u64 pos, 43 u64 disk_offset, u64 disk_num_bytes, 44 u64 num_bytes, u64 offset, u64 ram_bytes, 45 u8 compression, u8 encryption, u16 other_encoding) 46{ 47 int ret = 0; 48 struct btrfs_file_extent_item *item; 49 struct btrfs_key file_key; 50 struct btrfs_path *path; 51 struct extent_buffer *leaf; 52 53 path = btrfs_alloc_path(); 54 if (!path) 55 return -ENOMEM; 56 file_key.objectid = objectid; 57 file_key.offset = pos; 58 btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); 59 60 path->leave_spinning = 1; 61 ret = btrfs_insert_empty_item(trans, root, path, &file_key, 62 sizeof(*item)); 63 if (ret < 0) 64 goto out; 65 BUG_ON(ret); /* Can't happen */ 66 leaf = path->nodes[0]; 67 item = btrfs_item_ptr(leaf, path->slots[0], 68 struct btrfs_file_extent_item); 69 btrfs_set_file_extent_disk_bytenr(leaf, item, disk_offset); 70 btrfs_set_file_extent_disk_num_bytes(leaf, item, disk_num_bytes); 71 btrfs_set_file_extent_offset(leaf, item, offset); 72 btrfs_set_file_extent_num_bytes(leaf, item, num_bytes); 73 btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes); 74 btrfs_set_file_extent_generation(leaf, item, trans->transid); 75 btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG); 76 btrfs_set_file_extent_compression(leaf, item, compression); 77 btrfs_set_file_extent_encryption(leaf, item, encryption); 78 btrfs_set_file_extent_other_encoding(leaf, item, other_encoding); 79 80 btrfs_mark_buffer_dirty(leaf); 81out: 82 btrfs_free_path(path); 83 return ret; 84} 85 86struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, 87 struct btrfs_root *root, 88 struct btrfs_path *path, 89 u64 bytenr, int cow) 90{ 91 int ret; 92 struct btrfs_key file_key; 93 struct btrfs_key found_key; 94 struct btrfs_csum_item *item; 95 struct extent_buffer *leaf; 96 u64 csum_offset = 0; 97 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); 98 int csums_in_item; 99 100 file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; 101 file_key.offset = bytenr; 102 btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY); 103 ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); 104 if (ret < 0) 105 goto fail; 106 leaf = path->nodes[0]; 107 if (ret > 0) { 108 ret = 1; 109 if (path->slots[0] == 0) 110 goto fail; 111 path->slots[0]--; 112 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 113 if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY) 114 goto fail; 115 116 csum_offset = (bytenr - found_key.offset) >> 117 root->fs_info->sb->s_blocksize_bits; 118 csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]); 119 csums_in_item /= csum_size; 120 121 if (csum_offset >= csums_in_item) { 122 ret = -EFBIG; 123 goto fail; 124 } 125 } 126 item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); 127 item = (struct btrfs_csum_item *)((unsigned char *)item + 128 csum_offset * csum_size); 129 return item; 130fail: 131 if (ret > 0) 132 ret = -ENOENT; 133 return ERR_PTR(ret); 134} 135 136int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, 137 struct btrfs_root *root, 138 struct btrfs_path *path, u64 objectid, 139 u64 offset, int mod) 140{ 141 int ret; 142 struct btrfs_key file_key; 143 int ins_len = mod < 0 ? -1 : 0; 144 int cow = mod != 0; 145 146 file_key.objectid = objectid; 147 file_key.offset = offset; 148 btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); 149 ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); 150 return ret; 151} 152 153u64 btrfs_file_extent_length(struct btrfs_path *path) 154{ 155 int extent_type; 156 struct btrfs_file_extent_item *fi; 157 u64 len; 158 159 fi = btrfs_item_ptr(path->nodes[0], path->slots[0], 160 struct btrfs_file_extent_item); 161 extent_type = btrfs_file_extent_type(path->nodes[0], fi); 162 163 if (extent_type == BTRFS_FILE_EXTENT_REG || 164 extent_type == BTRFS_FILE_EXTENT_PREALLOC) 165 len = btrfs_file_extent_num_bytes(path->nodes[0], fi); 166 else if (extent_type == BTRFS_FILE_EXTENT_INLINE) 167 len = btrfs_file_extent_inline_len(path->nodes[0], fi); 168 else 169 BUG(); 170 171 return len; 172} 173 174static int __btrfs_lookup_bio_sums(struct btrfs_root *root, 175 struct inode *inode, struct bio *bio, 176 u64 logical_offset, u32 *dst, int dio) 177{ 178 u32 sum; 179 struct bio_vec *bvec = bio->bi_io_vec; 180 int bio_index = 0; 181 u64 offset = 0; 182 u64 item_start_offset = 0; 183 u64 item_last_offset = 0; 184 u64 disk_bytenr; 185 u32 diff; 186 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); 187 int ret; 188 struct btrfs_path *path; 189 struct btrfs_csum_item *item = NULL; 190 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; 191 192 path = btrfs_alloc_path(); 193 if (!path) 194 return -ENOMEM; 195 if (bio->bi_size > PAGE_CACHE_SIZE * 8) 196 path->reada = 2; 197 198 WARN_ON(bio->bi_vcnt <= 0); 199 200 /* 201 * the free space stuff is only read when it hasn't been 202 * updated in the current transaction. So, we can safely 203 * read from the commit root and sidestep a nasty deadlock 204 * between reading the free space cache and updating the csum tree. 205 */ 206 if (btrfs_is_free_space_inode(inode)) { 207 path->search_commit_root = 1; 208 path->skip_locking = 1; 209 } 210 211 disk_bytenr = (u64)bio->bi_sector << 9; 212 if (dio) 213 offset = logical_offset; 214 while (bio_index < bio->bi_vcnt) { 215 if (!dio) 216 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 217 ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum); 218 if (ret == 0) 219 goto found; 220 221 if (!item || disk_bytenr < item_start_offset || 222 disk_bytenr >= item_last_offset) { 223 struct btrfs_key found_key; 224 u32 item_size; 225 226 if (item) 227 btrfs_release_path(path); 228 item = btrfs_lookup_csum(NULL, root->fs_info->csum_root, 229 path, disk_bytenr, 0); 230 if (IS_ERR(item)) { 231 ret = PTR_ERR(item); 232 if (ret == -ENOENT || ret == -EFBIG) 233 ret = 0; 234 sum = 0; 235 if (BTRFS_I(inode)->root->root_key.objectid == 236 BTRFS_DATA_RELOC_TREE_OBJECTID) { 237 set_extent_bits(io_tree, offset, 238 offset + bvec->bv_len - 1, 239 EXTENT_NODATASUM, GFP_NOFS); 240 } else { 241 printk(KERN_INFO "btrfs no csum found " 242 "for inode %llu start %llu\n", 243 (unsigned long long) 244 btrfs_ino(inode), 245 (unsigned long long)offset); 246 } 247 item = NULL; 248 btrfs_release_path(path); 249 goto found; 250 } 251 btrfs_item_key_to_cpu(path->nodes[0], &found_key, 252 path->slots[0]); 253 254 item_start_offset = found_key.offset; 255 item_size = btrfs_item_size_nr(path->nodes[0], 256 path->slots[0]); 257 item_last_offset = item_start_offset + 258 (item_size / csum_size) * 259 root->sectorsize; 260 item = btrfs_item_ptr(path->nodes[0], path->slots[0], 261 struct btrfs_csum_item); 262 } 263 /* 264 * this byte range must be able to fit inside 265 * a single leaf so it will also fit inside a u32 266 */ 267 diff = disk_bytenr - item_start_offset; 268 diff = diff / root->sectorsize; 269 diff = diff * csum_size; 270 271 read_extent_buffer(path->nodes[0], &sum, 272 ((unsigned long)item) + diff, 273 csum_size); 274found: 275 if (dst) 276 *dst++ = sum; 277 else 278 set_state_private(io_tree, offset, sum); 279 disk_bytenr += bvec->bv_len; 280 offset += bvec->bv_len; 281 bio_index++; 282 bvec++; 283 } 284 btrfs_free_path(path); 285 return 0; 286} 287 288int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, 289 struct bio *bio, u32 *dst) 290{ 291 return __btrfs_lookup_bio_sums(root, inode, bio, 0, dst, 0); 292} 293 294int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, 295 struct bio *bio, u64 offset) 296{ 297 return __btrfs_lookup_bio_sums(root, inode, bio, offset, NULL, 1); 298} 299 300int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, 301 struct list_head *list, int search_commit) 302{ 303 struct btrfs_key key; 304 struct btrfs_path *path; 305 struct extent_buffer *leaf; 306 struct btrfs_ordered_sum *sums; 307 struct btrfs_sector_sum *sector_sum; 308 struct btrfs_csum_item *item; 309 LIST_HEAD(tmplist); 310 unsigned long offset; 311 int ret; 312 size_t size; 313 u64 csum_end; 314 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); 315 316 path = btrfs_alloc_path(); 317 if (!path) 318 return -ENOMEM; 319 320 if (search_commit) { 321 path->skip_locking = 1; 322 path->reada = 2; 323 path->search_commit_root = 1; 324 } 325 326 key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; 327 key.offset = start; 328 key.type = BTRFS_EXTENT_CSUM_KEY; 329 330 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 331 if (ret < 0) 332 goto fail; 333 if (ret > 0 && path->slots[0] > 0) { 334 leaf = path->nodes[0]; 335 btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1); 336 if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID && 337 key.type == BTRFS_EXTENT_CSUM_KEY) { 338 offset = (start - key.offset) >> 339 root->fs_info->sb->s_blocksize_bits; 340 if (offset * csum_size < 341 btrfs_item_size_nr(leaf, path->slots[0] - 1)) 342 path->slots[0]--; 343 } 344 } 345 346 while (start <= end) { 347 leaf = path->nodes[0]; 348 if (path->slots[0] >= btrfs_header_nritems(leaf)) { 349 ret = btrfs_next_leaf(root, path); 350 if (ret < 0) 351 goto fail; 352 if (ret > 0) 353 break; 354 leaf = path->nodes[0]; 355 } 356 357 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 358 if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || 359 key.type != BTRFS_EXTENT_CSUM_KEY) 360 break; 361 362 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 363 if (key.offset > end) 364 break; 365 366 if (key.offset > start) 367 start = key.offset; 368 369 size = btrfs_item_size_nr(leaf, path->slots[0]); 370 csum_end = key.offset + (size / csum_size) * root->sectorsize; 371 if (csum_end <= start) { 372 path->slots[0]++; 373 continue; 374 } 375 376 csum_end = min(csum_end, end + 1); 377 item = btrfs_item_ptr(path->nodes[0], path->slots[0], 378 struct btrfs_csum_item); 379 while (start < csum_end) { 380 size = min_t(size_t, csum_end - start, 381 MAX_ORDERED_SUM_BYTES(root)); 382 sums = kzalloc(btrfs_ordered_sum_size(root, size), 383 GFP_NOFS); 384 if (!sums) { 385 ret = -ENOMEM; 386 goto fail; 387 } 388 389 sector_sum = sums->sums; 390 sums->bytenr = start; 391 sums->len = size; 392 393 offset = (start - key.offset) >> 394 root->fs_info->sb->s_blocksize_bits; 395 offset *= csum_size; 396 397 while (size > 0) { 398 read_extent_buffer(path->nodes[0], 399 §or_sum->sum, 400 ((unsigned long)item) + 401 offset, csum_size); 402 sector_sum->bytenr = start; 403 404 size -= root->sectorsize; 405 start += root->sectorsize; 406 offset += csum_size; 407 sector_sum++; 408 } 409 list_add_tail(&sums->list, &tmplist); 410 } 411 path->slots[0]++; 412 } 413 ret = 0; 414fail: 415 while (ret < 0 && !list_empty(&tmplist)) { 416 sums = list_entry(&tmplist, struct btrfs_ordered_sum, list); 417 list_del(&sums->list); 418 kfree(sums); 419 } 420 list_splice_tail(&tmplist, list); 421 422 btrfs_free_path(path); 423 return ret; 424} 425 426int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, 427 struct bio *bio, u64 file_start, int contig) 428{ 429 struct btrfs_ordered_sum *sums; 430 struct btrfs_sector_sum *sector_sum; 431 struct btrfs_ordered_extent *ordered; 432 char *data; 433 struct bio_vec *bvec = bio->bi_io_vec; 434 int bio_index = 0; 435 unsigned long total_bytes = 0; 436 unsigned long this_sum_bytes = 0; 437 u64 offset; 438 u64 disk_bytenr; 439 440 WARN_ON(bio->bi_vcnt <= 0); 441 sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS); 442 if (!sums) 443 return -ENOMEM; 444 445 sector_sum = sums->sums; 446 disk_bytenr = (u64)bio->bi_sector << 9; 447 sums->len = bio->bi_size; 448 INIT_LIST_HEAD(&sums->list); 449 450 if (contig) 451 offset = file_start; 452 else 453 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 454 455 ordered = btrfs_lookup_ordered_extent(inode, offset); 456 BUG_ON(!ordered); /* Logic error */ 457 sums->bytenr = ordered->start; 458 459 while (bio_index < bio->bi_vcnt) { 460 if (!contig) 461 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 462 463 if (!contig && (offset >= ordered->file_offset + ordered->len || 464 offset < ordered->file_offset)) { 465 unsigned long bytes_left; 466 sums->len = this_sum_bytes; 467 this_sum_bytes = 0; 468 btrfs_add_ordered_sum(inode, ordered, sums); 469 btrfs_put_ordered_extent(ordered); 470 471 bytes_left = bio->bi_size - total_bytes; 472 473 sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), 474 GFP_NOFS); 475 BUG_ON(!sums); /* -ENOMEM */ 476 sector_sum = sums->sums; 477 sums->len = bytes_left; 478 ordered = btrfs_lookup_ordered_extent(inode, offset); 479 BUG_ON(!ordered); /* Logic error */ 480 sums->bytenr = ordered->start; 481 } 482 483 data = kmap_atomic(bvec->bv_page); 484 sector_sum->sum = ~(u32)0; 485 sector_sum->sum = btrfs_csum_data(root, 486 data + bvec->bv_offset, 487 sector_sum->sum, 488 bvec->bv_len); 489 kunmap_atomic(data); 490 btrfs_csum_final(sector_sum->sum, 491 (char *)§or_sum->sum); 492 sector_sum->bytenr = disk_bytenr; 493 494 sector_sum++; 495 bio_index++; 496 total_bytes += bvec->bv_len; 497 this_sum_bytes += bvec->bv_len; 498 disk_bytenr += bvec->bv_len; 499 offset += bvec->bv_len; 500 bvec++; 501 } 502 this_sum_bytes = 0; 503 btrfs_add_ordered_sum(inode, ordered, sums); 504 btrfs_put_ordered_extent(ordered); 505 return 0; 506} 507 508/* 509 * helper function for csum removal, this expects the 510 * key to describe the csum pointed to by the path, and it expects 511 * the csum to overlap the range [bytenr, len] 512 * 513 * The csum should not be entirely contained in the range and the 514 * range should not be entirely contained in the csum. 515 * 516 * This calls btrfs_truncate_item with the correct args based on the 517 * overlap, and fixes up the key as required. 518 */ 519static noinline void truncate_one_csum(struct btrfs_trans_handle *trans, 520 struct btrfs_root *root, 521 struct btrfs_path *path, 522 struct btrfs_key *key, 523 u64 bytenr, u64 len) 524{ 525 struct extent_buffer *leaf; 526 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); 527 u64 csum_end; 528 u64 end_byte = bytenr + len; 529 u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits; 530 531 leaf = path->nodes[0]; 532 csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size; 533 csum_end <<= root->fs_info->sb->s_blocksize_bits; 534 csum_end += key->offset; 535 536 if (key->offset < bytenr && csum_end <= end_byte) { 537 /* 538 * [ bytenr - len ] 539 * [ ] 540 * [csum ] 541 * A simple truncate off the end of the item 542 */ 543 u32 new_size = (bytenr - key->offset) >> blocksize_bits; 544 new_size *= csum_size; 545 btrfs_truncate_item(trans, root, path, new_size, 1); 546 } else if (key->offset >= bytenr && csum_end > end_byte && 547 end_byte > key->offset) { 548 /* 549 * [ bytenr - len ] 550 * [ ] 551 * [csum ] 552 * we need to truncate from the beginning of the csum 553 */ 554 u32 new_size = (csum_end - end_byte) >> blocksize_bits; 555 new_size *= csum_size; 556 557 btrfs_truncate_item(trans, root, path, new_size, 0); 558 559 key->offset = end_byte; 560 btrfs_set_item_key_safe(trans, root, path, key); 561 } else { 562 BUG(); 563 } 564} 565 566/* 567 * deletes the csum items from the csum tree for a given 568 * range of bytes. 569 */ 570int btrfs_del_csums(struct btrfs_trans_handle *trans, 571 struct btrfs_root *root, u64 bytenr, u64 len) 572{ 573 struct btrfs_path *path; 574 struct btrfs_key key; 575 u64 end_byte = bytenr + len; 576 u64 csum_end; 577 struct extent_buffer *leaf; 578 int ret; 579 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); 580 int blocksize_bits = root->fs_info->sb->s_blocksize_bits; 581 582 root = root->fs_info->csum_root; 583 584 path = btrfs_alloc_path(); 585 if (!path) 586 return -ENOMEM; 587 588 while (1) { 589 key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; 590 key.offset = end_byte - 1; 591 key.type = BTRFS_EXTENT_CSUM_KEY; 592 593 path->leave_spinning = 1; 594 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 595 if (ret > 0) { 596 if (path->slots[0] == 0) 597 break; 598 path->slots[0]--; 599 } else if (ret < 0) { 600 break; 601 } 602 603 leaf = path->nodes[0]; 604 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 605 606 if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || 607 key.type != BTRFS_EXTENT_CSUM_KEY) { 608 break; 609 } 610 611 if (key.offset >= end_byte) 612 break; 613 614 csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size; 615 csum_end <<= blocksize_bits; 616 csum_end += key.offset; 617 618 /* this csum ends before we start, we're done */ 619 if (csum_end <= bytenr) 620 break; 621 622 /* delete the entire item, it is inside our range */ 623 if (key.offset >= bytenr && csum_end <= end_byte) { 624 ret = btrfs_del_item(trans, root, path); 625 if (ret) 626 goto out; 627 if (key.offset == bytenr) 628 break; 629 } else if (key.offset < bytenr && csum_end > end_byte) { 630 unsigned long offset; 631 unsigned long shift_len; 632 unsigned long item_offset; 633 /* 634 * [ bytenr - len ] 635 * [csum ] 636 * 637 * Our bytes are in the middle of the csum, 638 * we need to split this item and insert a new one. 639 * 640 * But we can't drop the path because the 641 * csum could change, get removed, extended etc. 642 * 643 * The trick here is the max size of a csum item leaves 644 * enough room in the tree block for a single 645 * item header. So, we split the item in place, 646 * adding a new header pointing to the existing 647 * bytes. Then we loop around again and we have 648 * a nicely formed csum item that we can neatly 649 * truncate. 650 */ 651 offset = (bytenr - key.offset) >> blocksize_bits; 652 offset *= csum_size; 653 654 shift_len = (len >> blocksize_bits) * csum_size; 655 656 item_offset = btrfs_item_ptr_offset(leaf, 657 path->slots[0]); 658 659 memset_extent_buffer(leaf, 0, item_offset + offset, 660 shift_len); 661 key.offset = bytenr; 662 663 /* 664 * btrfs_split_item returns -EAGAIN when the 665 * item changed size or key 666 */ 667 ret = btrfs_split_item(trans, root, path, &key, offset); 668 if (ret && ret != -EAGAIN) { 669 btrfs_abort_transaction(trans, root, ret); 670 goto out; 671 } 672 673 key.offset = end_byte - 1; 674 } else { 675 truncate_one_csum(trans, root, path, &key, bytenr, len); 676 if (key.offset < bytenr) 677 break; 678 } 679 btrfs_release_path(path); 680 } 681 ret = 0; 682out: 683 btrfs_free_path(path); 684 return ret; 685} 686 687int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, 688 struct btrfs_root *root, 689 struct btrfs_ordered_sum *sums) 690{ 691 u64 bytenr; 692 int ret; 693 struct btrfs_key file_key; 694 struct btrfs_key found_key; 695 u64 next_offset; 696 u64 total_bytes = 0; 697 int found_next; 698 struct btrfs_path *path; 699 struct btrfs_csum_item *item; 700 struct btrfs_csum_item *item_end; 701 struct extent_buffer *leaf = NULL; 702 u64 csum_offset; 703 struct btrfs_sector_sum *sector_sum; 704 u32 nritems; 705 u32 ins_size; 706 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); 707 708 path = btrfs_alloc_path(); 709 if (!path) 710 return -ENOMEM; 711 712 sector_sum = sums->sums; 713 trans->adding_csums = 1; 714again: 715 next_offset = (u64)-1; 716 found_next = 0; 717 file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; 718 file_key.offset = sector_sum->bytenr; 719 bytenr = sector_sum->bytenr; 720 btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY); 721 722 item = btrfs_lookup_csum(trans, root, path, sector_sum->bytenr, 1); 723 if (!IS_ERR(item)) { 724 leaf = path->nodes[0]; 725 ret = 0; 726 goto found; 727 } 728 ret = PTR_ERR(item); 729 if (ret != -EFBIG && ret != -ENOENT) 730 goto fail_unlock; 731 732 if (ret == -EFBIG) { 733 u32 item_size; 734 /* we found one, but it isn't big enough yet */ 735 leaf = path->nodes[0]; 736 item_size = btrfs_item_size_nr(leaf, path->slots[0]); 737 if ((item_size / csum_size) >= 738 MAX_CSUM_ITEMS(root, csum_size)) { 739 /* already at max size, make a new one */ 740 goto insert; 741 } 742 } else { 743 int slot = path->slots[0] + 1; 744 /* we didn't find a csum item, insert one */ 745 nritems = btrfs_header_nritems(path->nodes[0]); 746 if (path->slots[0] >= nritems - 1) { 747 ret = btrfs_next_leaf(root, path); 748 if (ret == 1) 749 found_next = 1; 750 if (ret != 0) 751 goto insert; 752 slot = 0; 753 } 754 btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); 755 if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || 756 found_key.type != BTRFS_EXTENT_CSUM_KEY) { 757 found_next = 1; 758 goto insert; 759 } 760 next_offset = found_key.offset; 761 found_next = 1; 762 goto insert; 763 } 764 765 /* 766 * at this point, we know the tree has an item, but it isn't big 767 * enough yet to put our csum in. Grow it 768 */ 769 btrfs_release_path(path); 770 ret = btrfs_search_slot(trans, root, &file_key, path, 771 csum_size, 1); 772 if (ret < 0) 773 goto fail_unlock; 774 775 if (ret > 0) { 776 if (path->slots[0] == 0) 777 goto insert; 778 path->slots[0]--; 779 } 780 781 leaf = path->nodes[0]; 782 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 783 csum_offset = (bytenr - found_key.offset) >> 784 root->fs_info->sb->s_blocksize_bits; 785 786 if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY || 787 found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || 788 csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) { 789 goto insert; 790 } 791 792 if (csum_offset >= btrfs_item_size_nr(leaf, path->slots[0]) / 793 csum_size) { 794 u32 diff = (csum_offset + 1) * csum_size; 795 796 /* 797 * is the item big enough already? we dropped our lock 798 * before and need to recheck 799 */ 800 if (diff < btrfs_item_size_nr(leaf, path->slots[0])) 801 goto csum; 802 803 diff = diff - btrfs_item_size_nr(leaf, path->slots[0]); 804 if (diff != csum_size) 805 goto insert; 806 807 btrfs_extend_item(trans, root, path, diff); 808 goto csum; 809 } 810 811insert: 812 btrfs_release_path(path); 813 csum_offset = 0; 814 if (found_next) { 815 u64 tmp = total_bytes + root->sectorsize; 816 u64 next_sector = sector_sum->bytenr; 817 struct btrfs_sector_sum *next = sector_sum + 1; 818 819 while (tmp < sums->len) { 820 if (next_sector + root->sectorsize != next->bytenr) 821 break; 822 tmp += root->sectorsize; 823 next_sector = next->bytenr; 824 next++; 825 } 826 tmp = min(tmp, next_offset - file_key.offset); 827 tmp >>= root->fs_info->sb->s_blocksize_bits; 828 tmp = max((u64)1, tmp); 829 tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size)); 830 ins_size = csum_size * tmp; 831 } else { 832 ins_size = csum_size; 833 } 834 path->leave_spinning = 1; 835 ret = btrfs_insert_empty_item(trans, root, path, &file_key, 836 ins_size); 837 path->leave_spinning = 0; 838 if (ret < 0) 839 goto fail_unlock; 840 if (ret != 0) { 841 WARN_ON(1); 842 goto fail_unlock; 843 } 844csum: 845 leaf = path->nodes[0]; 846 item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); 847 ret = 0; 848 item = (struct btrfs_csum_item *)((unsigned char *)item + 849 csum_offset * csum_size); 850found: 851 item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); 852 item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + 853 btrfs_item_size_nr(leaf, path->slots[0])); 854next_sector: 855 856 write_extent_buffer(leaf, §or_sum->sum, (unsigned long)item, csum_size); 857 858 total_bytes += root->sectorsize; 859 sector_sum++; 860 if (total_bytes < sums->len) { 861 item = (struct btrfs_csum_item *)((char *)item + 862 csum_size); 863 if (item < item_end && bytenr + PAGE_CACHE_SIZE == 864 sector_sum->bytenr) { 865 bytenr = sector_sum->bytenr; 866 goto next_sector; 867 } 868 } 869 870 btrfs_mark_buffer_dirty(path->nodes[0]); 871 if (total_bytes < sums->len) { 872 btrfs_release_path(path); 873 cond_resched(); 874 goto again; 875 } 876out: 877 trans->adding_csums = 0; 878 btrfs_free_path(path); 879 return ret; 880 881fail_unlock: 882 goto out; 883} 884