file-item.c revision 17d217fe970d34720f4f1633dca73a6aa2f3d9d1
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/pagemap.h> 21#include <linux/highmem.h> 22#include "ctree.h" 23#include "disk-io.h" 24#include "transaction.h" 25#include "print-tree.h" 26 27#define MAX_CSUM_ITEMS(r,size) ((((BTRFS_LEAF_DATA_SIZE(r) - \ 28 sizeof(struct btrfs_item) * 2) / \ 29 size) - 1)) 30int 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, u64 ram_bytes, 35 u8 compression, u8 encryption, u16 other_encoding) 36{ 37 int ret = 0; 38 struct btrfs_file_extent_item *item; 39 struct btrfs_key file_key; 40 struct btrfs_path *path; 41 struct extent_buffer *leaf; 42 43 path = btrfs_alloc_path(); 44 BUG_ON(!path); 45 file_key.objectid = objectid; 46 file_key.offset = pos; 47 btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); 48 49 ret = btrfs_insert_empty_item(trans, root, path, &file_key, 50 sizeof(*item)); 51 if (ret < 0) 52 goto out; 53 BUG_ON(ret); 54 leaf = path->nodes[0]; 55 item = btrfs_item_ptr(leaf, path->slots[0], 56 struct btrfs_file_extent_item); 57 btrfs_set_file_extent_disk_bytenr(leaf, item, disk_offset); 58 btrfs_set_file_extent_disk_num_bytes(leaf, item, disk_num_bytes); 59 btrfs_set_file_extent_offset(leaf, item, offset); 60 btrfs_set_file_extent_num_bytes(leaf, item, num_bytes); 61 btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes); 62 btrfs_set_file_extent_generation(leaf, item, trans->transid); 63 btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG); 64 btrfs_set_file_extent_compression(leaf, item, compression); 65 btrfs_set_file_extent_encryption(leaf, item, encryption); 66 btrfs_set_file_extent_other_encoding(leaf, item, other_encoding); 67 68 btrfs_mark_buffer_dirty(leaf); 69out: 70 btrfs_free_path(path); 71 return ret; 72} 73 74struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, 75 struct btrfs_root *root, 76 struct btrfs_path *path, 77 u64 bytenr, int cow) 78{ 79 int ret; 80 struct btrfs_key file_key; 81 struct btrfs_key found_key; 82 struct btrfs_csum_item *item; 83 struct extent_buffer *leaf; 84 u64 csum_offset = 0; 85 u16 csum_size = 86 btrfs_super_csum_size(&root->fs_info->super_copy); 87 int csums_in_item; 88 89 file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; 90 file_key.offset = bytenr; 91 btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY); 92 ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); 93 if (ret < 0) 94 goto fail; 95 leaf = path->nodes[0]; 96 if (ret > 0) { 97 ret = 1; 98 if (path->slots[0] == 0) 99 goto fail; 100 path->slots[0]--; 101 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 102 if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY) 103 goto fail; 104 105 csum_offset = (bytenr - found_key.offset) >> 106 root->fs_info->sb->s_blocksize_bits; 107 csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]); 108 csums_in_item /= csum_size; 109 110 if (csum_offset >= csums_in_item) { 111 ret = -EFBIG; 112 goto fail; 113 } 114 } 115 item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); 116 item = (struct btrfs_csum_item *)((unsigned char *)item + 117 csum_offset * csum_size); 118 return item; 119fail: 120 if (ret > 0) 121 ret = -ENOENT; 122 return ERR_PTR(ret); 123} 124 125 126int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, 127 struct btrfs_root *root, 128 struct btrfs_path *path, u64 objectid, 129 u64 offset, int mod) 130{ 131 int ret; 132 struct btrfs_key file_key; 133 int ins_len = mod < 0 ? -1 : 0; 134 int cow = mod != 0; 135 136 file_key.objectid = objectid; 137 file_key.offset = offset; 138 btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); 139 ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); 140 return ret; 141} 142 143 144int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, 145 struct bio *bio, u32 *dst) 146{ 147 u32 sum; 148 struct bio_vec *bvec = bio->bi_io_vec; 149 int bio_index = 0; 150 u64 offset; 151 u64 item_start_offset = 0; 152 u64 item_last_offset = 0; 153 u64 disk_bytenr; 154 u32 diff; 155 u16 csum_size = 156 btrfs_super_csum_size(&root->fs_info->super_copy); 157 int ret; 158 struct btrfs_path *path; 159 struct btrfs_csum_item *item = NULL; 160 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; 161 162 path = btrfs_alloc_path(); 163 if (bio->bi_size > PAGE_CACHE_SIZE * 8) 164 path->reada = 2; 165 166 WARN_ON(bio->bi_vcnt <= 0); 167 168 disk_bytenr = (u64)bio->bi_sector << 9; 169 while(bio_index < bio->bi_vcnt) { 170 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 171 ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum); 172 if (ret == 0) 173 goto found; 174 175 if (!item || disk_bytenr < item_start_offset || 176 disk_bytenr >= item_last_offset) { 177 struct btrfs_key found_key; 178 u32 item_size; 179 180 if (item) 181 btrfs_release_path(root, path); 182 item = btrfs_lookup_csum(NULL, root->fs_info->csum_root, 183 path, disk_bytenr, 0); 184 if (IS_ERR(item)) { 185 ret = PTR_ERR(item); 186 if (ret == -ENOENT || ret == -EFBIG) 187 ret = 0; 188 sum = 0; 189 if (BTRFS_I(inode)->root->root_key.objectid == 190 BTRFS_DATA_RELOC_TREE_OBJECTID) { 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 } 199 item = NULL; 200 btrfs_release_path(root, path); 201 goto found; 202 } 203 btrfs_item_key_to_cpu(path->nodes[0], &found_key, 204 path->slots[0]); 205 206 item_start_offset = found_key.offset; 207 item_size = btrfs_item_size_nr(path->nodes[0], 208 path->slots[0]); 209 item_last_offset = item_start_offset + 210 (item_size / csum_size) * 211 root->sectorsize; 212 item = btrfs_item_ptr(path->nodes[0], path->slots[0], 213 struct btrfs_csum_item); 214 } 215 /* 216 * this byte range must be able to fit inside 217 * a single leaf so it will also fit inside a u32 218 */ 219 diff = disk_bytenr - item_start_offset; 220 diff = diff / root->sectorsize; 221 diff = diff * csum_size; 222 223 read_extent_buffer(path->nodes[0], &sum, 224 ((unsigned long)item) + diff, 225 csum_size); 226found: 227 if (dst) 228 *dst++ = sum; 229 else 230 set_state_private(io_tree, offset, sum); 231 disk_bytenr += bvec->bv_len; 232 bio_index++; 233 bvec++; 234 } 235 btrfs_free_path(path); 236 return 0; 237} 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], §or_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 339int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, 340 struct bio *bio, u64 file_start, int contig) 341{ 342 struct btrfs_ordered_sum *sums; 343 struct btrfs_sector_sum *sector_sum; 344 struct btrfs_ordered_extent *ordered; 345 char *data; 346 struct bio_vec *bvec = bio->bi_io_vec; 347 int bio_index = 0; 348 unsigned long total_bytes = 0; 349 unsigned long this_sum_bytes = 0; 350 u64 offset; 351 u64 disk_bytenr; 352 353 WARN_ON(bio->bi_vcnt <= 0); 354 sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS); 355 if (!sums) 356 return -ENOMEM; 357 358 sector_sum = sums->sums; 359 disk_bytenr = (u64)bio->bi_sector << 9; 360 sums->len = bio->bi_size; 361 INIT_LIST_HEAD(&sums->list); 362 363 if (contig) 364 offset = file_start; 365 else 366 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 367 368 ordered = btrfs_lookup_ordered_extent(inode, offset); 369 BUG_ON(!ordered); 370 sums->bytenr = ordered->start; 371 372 while(bio_index < bio->bi_vcnt) { 373 if (!contig) 374 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 375 376 if (!contig && (offset >= ordered->file_offset + ordered->len || 377 offset < ordered->file_offset)) { 378 unsigned long bytes_left; 379 sums->len = this_sum_bytes; 380 this_sum_bytes = 0; 381 btrfs_add_ordered_sum(inode, ordered, sums); 382 btrfs_put_ordered_extent(ordered); 383 384 bytes_left = bio->bi_size - total_bytes; 385 386 sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), 387 GFP_NOFS); 388 BUG_ON(!sums); 389 sector_sum = sums->sums; 390 sums->len = bytes_left; 391 ordered = btrfs_lookup_ordered_extent(inode, offset); 392 BUG_ON(!ordered); 393 sums->bytenr = ordered->start; 394 } 395 396 data = kmap_atomic(bvec->bv_page, KM_USER0); 397 sector_sum->sum = ~(u32)0; 398 sector_sum->sum = btrfs_csum_data(root, 399 data + bvec->bv_offset, 400 sector_sum->sum, 401 bvec->bv_len); 402 kunmap_atomic(data, KM_USER0); 403 btrfs_csum_final(sector_sum->sum, 404 (char *)§or_sum->sum); 405 sector_sum->bytenr = disk_bytenr; 406 407 sector_sum++; 408 bio_index++; 409 total_bytes += bvec->bv_len; 410 this_sum_bytes += bvec->bv_len; 411 disk_bytenr += bvec->bv_len; 412 offset += bvec->bv_len; 413 bvec++; 414 } 415 this_sum_bytes = 0; 416 btrfs_add_ordered_sum(inode, ordered, sums); 417 btrfs_put_ordered_extent(ordered); 418 return 0; 419} 420 421/* 422 * helper function for csum removal, this expects the 423 * key to describe the csum pointed to by the path, and it expects 424 * the csum to overlap the range [bytenr, len] 425 * 426 * The csum should not be entirely contained in the range and the 427 * range should not be entirely contained in the csum. 428 * 429 * This calls btrfs_truncate_item with the correct args based on the 430 * overlap, and fixes up the key as required. 431 */ 432static noinline int truncate_one_csum(struct btrfs_trans_handle *trans, 433 struct btrfs_root *root, 434 struct btrfs_path *path, 435 struct btrfs_key *key, 436 u64 bytenr, u64 len) 437{ 438 struct extent_buffer *leaf; 439 u16 csum_size = 440 btrfs_super_csum_size(&root->fs_info->super_copy); 441 u64 csum_end; 442 u64 end_byte = bytenr + len; 443 u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits; 444 int ret; 445 446 leaf = path->nodes[0]; 447 csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size; 448 csum_end <<= root->fs_info->sb->s_blocksize_bits; 449 csum_end += key->offset; 450 451 if (key->offset < bytenr && csum_end <= end_byte) { 452 /* 453 * [ bytenr - len ] 454 * [ ] 455 * [csum ] 456 * A simple truncate off the end of the item 457 */ 458 u32 new_size = (bytenr - key->offset) >> blocksize_bits; 459 new_size *= csum_size; 460 ret = btrfs_truncate_item(trans, root, path, new_size, 1); 461 BUG_ON(ret); 462 } else if (key->offset >= bytenr && csum_end > end_byte && 463 end_byte > key->offset) { 464 /* 465 * [ bytenr - len ] 466 * [ ] 467 * [csum ] 468 * we need to truncate from the beginning of the csum 469 */ 470 u32 new_size = (csum_end - end_byte) >> blocksize_bits; 471 new_size *= csum_size; 472 473 ret = btrfs_truncate_item(trans, root, path, new_size, 0); 474 BUG_ON(ret); 475 476 key->offset = end_byte; 477 ret = btrfs_set_item_key_safe(trans, root, path, key); 478 BUG_ON(ret); 479 } else { 480 BUG(); 481 } 482 return 0; 483} 484 485/* 486 * deletes the csum items from the csum tree for a given 487 * range of bytes. 488 */ 489int btrfs_del_csums(struct btrfs_trans_handle *trans, 490 struct btrfs_root *root, u64 bytenr, u64 len) 491{ 492 struct btrfs_path *path; 493 struct btrfs_key key; 494 u64 end_byte = bytenr + len; 495 u64 csum_end; 496 struct extent_buffer *leaf; 497 int ret; 498 u16 csum_size = 499 btrfs_super_csum_size(&root->fs_info->super_copy); 500 int blocksize_bits = root->fs_info->sb->s_blocksize_bits; 501 502 root = root->fs_info->csum_root; 503 504 path = btrfs_alloc_path(); 505 506 while(1) { 507 key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; 508 key.offset = end_byte - 1; 509 key.type = BTRFS_EXTENT_CSUM_KEY; 510 511 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 512 if (ret > 0) { 513 if (path->slots[0] == 0) 514 goto out; 515 path->slots[0]--; 516 } 517 leaf = path->nodes[0]; 518 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 519 520 if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || 521 key.type != BTRFS_EXTENT_CSUM_KEY) { 522 break; 523 } 524 525 if (key.offset >= end_byte) 526 break; 527 528 csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size; 529 csum_end <<= blocksize_bits; 530 csum_end += key.offset; 531 532 /* this csum ends before we start, we're done */ 533 if (csum_end <= bytenr) 534 break; 535 536 /* delete the entire item, it is inside our range */ 537 if (key.offset >= bytenr && csum_end <= end_byte) { 538 ret = btrfs_del_item(trans, root, path); 539 BUG_ON(ret); 540 } else if (key.offset < bytenr && csum_end > end_byte) { 541 unsigned long offset; 542 unsigned long shift_len; 543 unsigned long item_offset; 544 /* 545 * [ bytenr - len ] 546 * [csum ] 547 * 548 * Our bytes are in the middle of the csum, 549 * we need to split this item and insert a new one. 550 * 551 * But we can't drop the path because the 552 * csum could change, get removed, extended etc. 553 * 554 * The trick here is the max size of a csum item leaves 555 * enough room in the tree block for a single 556 * item header. So, we split the item in place, 557 * adding a new header pointing to the existing 558 * bytes. Then we loop around again and we have 559 * a nicely formed csum item that we can neatly 560 * truncate. 561 */ 562 offset = (bytenr - key.offset) >> blocksize_bits; 563 offset *= csum_size; 564 565 shift_len = (len >> blocksize_bits) * csum_size; 566 567 item_offset = btrfs_item_ptr_offset(leaf, 568 path->slots[0]); 569 570 memset_extent_buffer(leaf, 0, item_offset + offset, 571 shift_len); 572 key.offset = bytenr; 573 574 /* 575 * btrfs_split_item returns -EAGAIN when the 576 * item changed size or key 577 */ 578 ret = btrfs_split_item(trans, root, path, &key, offset); 579 BUG_ON(ret && ret != -EAGAIN); 580 581 key.offset = end_byte - 1; 582 } else { 583 ret = truncate_one_csum(trans, root, path, 584 &key, bytenr, len); 585 BUG_ON(ret); 586 } 587 btrfs_release_path(root, path); 588 } 589out: 590 btrfs_free_path(path); 591 return 0; 592} 593 594int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, 595 struct btrfs_root *root, 596 struct btrfs_ordered_sum *sums) 597{ 598 u64 bytenr; 599 int ret; 600 struct btrfs_key file_key; 601 struct btrfs_key found_key; 602 u64 next_offset; 603 u64 total_bytes = 0; 604 int found_next; 605 struct btrfs_path *path; 606 struct btrfs_csum_item *item; 607 struct btrfs_csum_item *item_end; 608 struct extent_buffer *leaf = NULL; 609 u64 csum_offset; 610 struct btrfs_sector_sum *sector_sum; 611 u32 nritems; 612 u32 ins_size; 613 char *eb_map; 614 char *eb_token; 615 unsigned long map_len; 616 unsigned long map_start; 617 u16 csum_size = 618 btrfs_super_csum_size(&root->fs_info->super_copy); 619 620 path = btrfs_alloc_path(); 621 BUG_ON(!path); 622 sector_sum = sums->sums; 623again: 624 next_offset = (u64)-1; 625 found_next = 0; 626 file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; 627 file_key.offset = sector_sum->bytenr; 628 bytenr = sector_sum->bytenr; 629 btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY); 630 631 item = btrfs_lookup_csum(trans, root, path, sector_sum->bytenr, 1); 632 if (!IS_ERR(item)) { 633 leaf = path->nodes[0]; 634 ret = 0; 635 goto found; 636 } 637 ret = PTR_ERR(item); 638 if (ret == -EFBIG) { 639 u32 item_size; 640 /* we found one, but it isn't big enough yet */ 641 leaf = path->nodes[0]; 642 item_size = btrfs_item_size_nr(leaf, path->slots[0]); 643 if ((item_size / csum_size) >= 644 MAX_CSUM_ITEMS(root, csum_size)) { 645 /* already at max size, make a new one */ 646 goto insert; 647 } 648 } else { 649 int slot = path->slots[0] + 1; 650 /* we didn't find a csum item, insert one */ 651 nritems = btrfs_header_nritems(path->nodes[0]); 652 if (path->slots[0] >= nritems - 1) { 653 ret = btrfs_next_leaf(root, path); 654 if (ret == 1) 655 found_next = 1; 656 if (ret != 0) 657 goto insert; 658 slot = 0; 659 } 660 btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); 661 if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || 662 found_key.type != BTRFS_EXTENT_CSUM_KEY) { 663 found_next = 1; 664 goto insert; 665 } 666 next_offset = found_key.offset; 667 found_next = 1; 668 goto insert; 669 } 670 671 /* 672 * at this point, we know the tree has an item, but it isn't big 673 * enough yet to put our csum in. Grow it 674 */ 675 btrfs_release_path(root, path); 676 ret = btrfs_search_slot(trans, root, &file_key, path, 677 csum_size, 1); 678 if (ret < 0) 679 goto fail_unlock; 680 681 if (ret > 0) { 682 if (path->slots[0] == 0) 683 goto insert; 684 path->slots[0]--; 685 } 686 687 leaf = path->nodes[0]; 688 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); 689 csum_offset = (bytenr - found_key.offset) >> 690 root->fs_info->sb->s_blocksize_bits; 691 692 if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY || 693 found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || 694 csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) { 695 goto insert; 696 } 697 698 if (csum_offset >= btrfs_item_size_nr(leaf, path->slots[0]) / 699 csum_size) { 700 u32 diff = (csum_offset + 1) * csum_size; 701 702 /* 703 * is the item big enough already? we dropped our lock 704 * before and need to recheck 705 */ 706 if (diff < btrfs_item_size_nr(leaf, path->slots[0])) 707 goto csum; 708 709 diff = diff - btrfs_item_size_nr(leaf, path->slots[0]); 710 if (diff != csum_size) { 711 goto insert; 712 } 713 714 ret = btrfs_extend_item(trans, root, path, diff); 715 BUG_ON(ret); 716 goto csum; 717 } 718 719insert: 720 btrfs_release_path(root, path); 721 csum_offset = 0; 722 if (found_next) { 723 u64 tmp = total_bytes + root->sectorsize; 724 u64 next_sector = sector_sum->bytenr; 725 struct btrfs_sector_sum *next = sector_sum + 1; 726 727 while(tmp < sums->len) { 728 if (next_sector + root->sectorsize != next->bytenr) 729 break; 730 tmp += root->sectorsize; 731 next_sector = next->bytenr; 732 next++; 733 } 734 tmp = min(tmp, next_offset - file_key.offset); 735 tmp >>= root->fs_info->sb->s_blocksize_bits; 736 tmp = max((u64)1, tmp); 737 tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size)); 738 ins_size = csum_size * tmp; 739 } else { 740 ins_size = csum_size; 741 } 742 ret = btrfs_insert_empty_item(trans, root, path, &file_key, 743 ins_size); 744 if (ret < 0) 745 goto fail_unlock; 746 if (ret != 0) { 747 WARN_ON(1); 748 goto fail_unlock; 749 } 750csum: 751 leaf = path->nodes[0]; 752 item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); 753 ret = 0; 754 item = (struct btrfs_csum_item *)((unsigned char *)item + 755 csum_offset * csum_size); 756found: 757 item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); 758 item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + 759 btrfs_item_size_nr(leaf, path->slots[0])); 760 eb_token = NULL; 761 cond_resched(); 762next_sector: 763 764 if (!eb_token || 765 (unsigned long)item + csum_size >= map_start + map_len) { 766 int err; 767 768 if (eb_token) 769 unmap_extent_buffer(leaf, eb_token, KM_USER1); 770 eb_token = NULL; 771 err = map_private_extent_buffer(leaf, (unsigned long)item, 772 csum_size, 773 &eb_token, &eb_map, 774 &map_start, &map_len, KM_USER1); 775 if (err) 776 eb_token = NULL; 777 } 778 if (eb_token) { 779 memcpy(eb_token + ((unsigned long)item & (PAGE_CACHE_SIZE - 1)), 780 §or_sum->sum, csum_size); 781 } else { 782 write_extent_buffer(leaf, §or_sum->sum, 783 (unsigned long)item, csum_size); 784 } 785 786 total_bytes += root->sectorsize; 787 sector_sum++; 788 if (total_bytes < sums->len) { 789 item = (struct btrfs_csum_item *)((char *)item + 790 csum_size); 791 if (item < item_end && bytenr + PAGE_CACHE_SIZE == 792 sector_sum->bytenr) { 793 bytenr = sector_sum->bytenr; 794 goto next_sector; 795 } 796 } 797 if (eb_token) { 798 unmap_extent_buffer(leaf, eb_token, KM_USER1); 799 eb_token = NULL; 800 } 801 btrfs_mark_buffer_dirty(path->nodes[0]); 802 cond_resched(); 803 if (total_bytes < sums->len) { 804 btrfs_release_path(root, path); 805 goto again; 806 } 807out: 808 btrfs_free_path(path); 809 return ret; 810 811fail_unlock: 812 goto out; 813} 814