.. | .. |
---|
7 | 7 | #include <linux/slab.h> |
---|
8 | 8 | #include <linux/pagemap.h> |
---|
9 | 9 | #include <linux/highmem.h> |
---|
| 10 | +#include <linux/sched/mm.h> |
---|
| 11 | +#include <crypto/hash.h> |
---|
10 | 12 | #include "ctree.h" |
---|
11 | 13 | #include "disk-io.h" |
---|
12 | 14 | #include "transaction.h" |
---|
.. | .. |
---|
21 | 23 | #define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \ |
---|
22 | 24 | PAGE_SIZE)) |
---|
23 | 25 | |
---|
24 | | -#define MAX_ORDERED_SUM_BYTES(fs_info) ((PAGE_SIZE - \ |
---|
25 | | - sizeof(struct btrfs_ordered_sum)) / \ |
---|
26 | | - sizeof(u32) * (fs_info)->sectorsize) |
---|
| 26 | +/** |
---|
| 27 | + * @inode - the inode we want to update the disk_i_size for |
---|
| 28 | + * @new_i_size - the i_size we want to set to, 0 if we use i_size |
---|
| 29 | + * |
---|
| 30 | + * With NO_HOLES set this simply sets the disk_is_size to whatever i_size_read() |
---|
| 31 | + * returns as it is perfectly fine with a file that has holes without hole file |
---|
| 32 | + * extent items. |
---|
| 33 | + * |
---|
| 34 | + * However without NO_HOLES we need to only return the area that is contiguous |
---|
| 35 | + * from the 0 offset of the file. Otherwise we could end up adjust i_size up |
---|
| 36 | + * to an extent that has a gap in between. |
---|
| 37 | + * |
---|
| 38 | + * Finally new_i_size should only be set in the case of truncate where we're not |
---|
| 39 | + * ready to use i_size_read() as the limiter yet. |
---|
| 40 | + */ |
---|
| 41 | +void btrfs_inode_safe_disk_i_size_write(struct inode *inode, u64 new_i_size) |
---|
| 42 | +{ |
---|
| 43 | + struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; |
---|
| 44 | + u64 start, end, i_size; |
---|
| 45 | + int ret; |
---|
| 46 | + |
---|
| 47 | + i_size = new_i_size ?: i_size_read(inode); |
---|
| 48 | + if (btrfs_fs_incompat(fs_info, NO_HOLES)) { |
---|
| 49 | + BTRFS_I(inode)->disk_i_size = i_size; |
---|
| 50 | + return; |
---|
| 51 | + } |
---|
| 52 | + |
---|
| 53 | + spin_lock(&BTRFS_I(inode)->lock); |
---|
| 54 | + ret = find_contiguous_extent_bit(&BTRFS_I(inode)->file_extent_tree, 0, |
---|
| 55 | + &start, &end, EXTENT_DIRTY); |
---|
| 56 | + if (!ret && start == 0) |
---|
| 57 | + i_size = min(i_size, end + 1); |
---|
| 58 | + else |
---|
| 59 | + i_size = 0; |
---|
| 60 | + BTRFS_I(inode)->disk_i_size = i_size; |
---|
| 61 | + spin_unlock(&BTRFS_I(inode)->lock); |
---|
| 62 | +} |
---|
| 63 | + |
---|
| 64 | +/** |
---|
| 65 | + * @inode - the inode we're modifying |
---|
| 66 | + * @start - the start file offset of the file extent we've inserted |
---|
| 67 | + * @len - the logical length of the file extent item |
---|
| 68 | + * |
---|
| 69 | + * Call when we are inserting a new file extent where there was none before. |
---|
| 70 | + * Does not need to call this in the case where we're replacing an existing file |
---|
| 71 | + * extent, however if not sure it's fine to call this multiple times. |
---|
| 72 | + * |
---|
| 73 | + * The start and len must match the file extent item, so thus must be sectorsize |
---|
| 74 | + * aligned. |
---|
| 75 | + */ |
---|
| 76 | +int btrfs_inode_set_file_extent_range(struct btrfs_inode *inode, u64 start, |
---|
| 77 | + u64 len) |
---|
| 78 | +{ |
---|
| 79 | + if (len == 0) |
---|
| 80 | + return 0; |
---|
| 81 | + |
---|
| 82 | + ASSERT(IS_ALIGNED(start + len, inode->root->fs_info->sectorsize)); |
---|
| 83 | + |
---|
| 84 | + if (btrfs_fs_incompat(inode->root->fs_info, NO_HOLES)) |
---|
| 85 | + return 0; |
---|
| 86 | + return set_extent_bits(&inode->file_extent_tree, start, start + len - 1, |
---|
| 87 | + EXTENT_DIRTY); |
---|
| 88 | +} |
---|
| 89 | + |
---|
| 90 | +/** |
---|
| 91 | + * @inode - the inode we're modifying |
---|
| 92 | + * @start - the start file offset of the file extent we've inserted |
---|
| 93 | + * @len - the logical length of the file extent item |
---|
| 94 | + * |
---|
| 95 | + * Called when we drop a file extent, for example when we truncate. Doesn't |
---|
| 96 | + * need to be called for cases where we're replacing a file extent, like when |
---|
| 97 | + * we've COWed a file extent. |
---|
| 98 | + * |
---|
| 99 | + * The start and len must match the file extent item, so thus must be sectorsize |
---|
| 100 | + * aligned. |
---|
| 101 | + */ |
---|
| 102 | +int btrfs_inode_clear_file_extent_range(struct btrfs_inode *inode, u64 start, |
---|
| 103 | + u64 len) |
---|
| 104 | +{ |
---|
| 105 | + if (len == 0) |
---|
| 106 | + return 0; |
---|
| 107 | + |
---|
| 108 | + ASSERT(IS_ALIGNED(start + len, inode->root->fs_info->sectorsize) || |
---|
| 109 | + len == (u64)-1); |
---|
| 110 | + |
---|
| 111 | + if (btrfs_fs_incompat(inode->root->fs_info, NO_HOLES)) |
---|
| 112 | + return 0; |
---|
| 113 | + return clear_extent_bit(&inode->file_extent_tree, start, |
---|
| 114 | + start + len - 1, EXTENT_DIRTY, 0, 0, NULL); |
---|
| 115 | +} |
---|
| 116 | + |
---|
| 117 | +static inline u32 max_ordered_sum_bytes(struct btrfs_fs_info *fs_info, |
---|
| 118 | + u16 csum_size) |
---|
| 119 | +{ |
---|
| 120 | + u32 ncsums = (PAGE_SIZE - sizeof(struct btrfs_ordered_sum)) / csum_size; |
---|
| 121 | + |
---|
| 122 | + return ncsums * fs_info->sectorsize; |
---|
| 123 | +} |
---|
27 | 124 | |
---|
28 | 125 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, |
---|
29 | 126 | struct btrfs_root *root, |
---|
.. | .. |
---|
142 | 239 | return ret; |
---|
143 | 240 | } |
---|
144 | 241 | |
---|
145 | | -static void btrfs_io_bio_endio_readpage(struct btrfs_io_bio *bio, int err) |
---|
146 | | -{ |
---|
147 | | - kfree(bio->csum_allocated); |
---|
148 | | -} |
---|
149 | | - |
---|
150 | | -static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, |
---|
151 | | - u64 logical_offset, u32 *dst, int dio) |
---|
| 242 | +/** |
---|
| 243 | + * btrfs_lookup_bio_sums - Look up checksums for a bio. |
---|
| 244 | + * @inode: inode that the bio is for. |
---|
| 245 | + * @bio: bio to look up. |
---|
| 246 | + * @offset: Unless (u64)-1, look up checksums for this offset in the file. |
---|
| 247 | + * If (u64)-1, use the page offsets from the bio instead. |
---|
| 248 | + * @dst: Buffer of size nblocks * btrfs_super_csum_size() used to return |
---|
| 249 | + * checksum (nblocks = bio->bi_iter.bi_size / fs_info->sectorsize). If |
---|
| 250 | + * NULL, the checksum buffer is allocated and returned in |
---|
| 251 | + * btrfs_io_bio(bio)->csum instead. |
---|
| 252 | + * |
---|
| 253 | + * Return: BLK_STS_RESOURCE if allocating memory fails, BLK_STS_OK otherwise. |
---|
| 254 | + */ |
---|
| 255 | +blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, |
---|
| 256 | + u64 offset, u8 *dst) |
---|
152 | 257 | { |
---|
153 | 258 | struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
---|
154 | 259 | struct bio_vec bvec; |
---|
155 | 260 | struct bvec_iter iter; |
---|
156 | | - struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio); |
---|
157 | 261 | struct btrfs_csum_item *item = NULL; |
---|
158 | 262 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
---|
159 | 263 | struct btrfs_path *path; |
---|
| 264 | + const bool page_offsets = (offset == (u64)-1); |
---|
160 | 265 | u8 *csum; |
---|
161 | | - u64 offset = 0; |
---|
162 | 266 | u64 item_start_offset = 0; |
---|
163 | 267 | u64 item_last_offset = 0; |
---|
164 | 268 | u64 disk_bytenr; |
---|
.. | .. |
---|
174 | 278 | |
---|
175 | 279 | nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits; |
---|
176 | 280 | if (!dst) { |
---|
| 281 | + struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio); |
---|
| 282 | + |
---|
177 | 283 | if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) { |
---|
178 | | - btrfs_bio->csum_allocated = kmalloc_array(nblocks, |
---|
179 | | - csum_size, GFP_NOFS); |
---|
180 | | - if (!btrfs_bio->csum_allocated) { |
---|
| 284 | + btrfs_bio->csum = kmalloc_array(nblocks, csum_size, |
---|
| 285 | + GFP_NOFS); |
---|
| 286 | + if (!btrfs_bio->csum) { |
---|
181 | 287 | btrfs_free_path(path); |
---|
182 | 288 | return BLK_STS_RESOURCE; |
---|
183 | 289 | } |
---|
184 | | - btrfs_bio->csum = btrfs_bio->csum_allocated; |
---|
185 | | - btrfs_bio->end_io = btrfs_io_bio_endio_readpage; |
---|
186 | 290 | } else { |
---|
187 | 291 | btrfs_bio->csum = btrfs_bio->csum_inline; |
---|
188 | 292 | } |
---|
189 | 293 | csum = btrfs_bio->csum; |
---|
190 | 294 | } else { |
---|
191 | | - csum = (u8 *)dst; |
---|
| 295 | + csum = dst; |
---|
192 | 296 | } |
---|
193 | 297 | |
---|
194 | 298 | if (bio->bi_iter.bi_size > PAGE_SIZE * 8) |
---|
.. | .. |
---|
206 | 310 | } |
---|
207 | 311 | |
---|
208 | 312 | disk_bytenr = (u64)bio->bi_iter.bi_sector << 9; |
---|
209 | | - if (dio) |
---|
210 | | - offset = logical_offset; |
---|
211 | 313 | |
---|
212 | 314 | bio_for_each_segment(bvec, bio, iter) { |
---|
213 | 315 | page_bytes_left = bvec.bv_len; |
---|
214 | 316 | if (count) |
---|
215 | 317 | goto next; |
---|
216 | 318 | |
---|
217 | | - if (!dio) |
---|
| 319 | + if (page_offsets) |
---|
218 | 320 | offset = page_offset(bvec.bv_page) + bvec.bv_offset; |
---|
219 | | - count = btrfs_find_ordered_sum(inode, offset, disk_bytenr, |
---|
220 | | - (u32 *)csum, nblocks); |
---|
| 321 | + count = btrfs_find_ordered_sum(BTRFS_I(inode), offset, |
---|
| 322 | + disk_bytenr, csum, nblocks); |
---|
221 | 323 | if (count) |
---|
222 | 324 | goto found; |
---|
223 | 325 | |
---|
.. | .. |
---|
287 | 389 | |
---|
288 | 390 | WARN_ON_ONCE(count); |
---|
289 | 391 | btrfs_free_path(path); |
---|
290 | | - return 0; |
---|
291 | | -} |
---|
292 | | - |
---|
293 | | -blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u32 *dst) |
---|
294 | | -{ |
---|
295 | | - return __btrfs_lookup_bio_sums(inode, bio, 0, dst, 0); |
---|
296 | | -} |
---|
297 | | - |
---|
298 | | -blk_status_t btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio, u64 offset) |
---|
299 | | -{ |
---|
300 | | - return __btrfs_lookup_bio_sums(inode, bio, offset, NULL, 1); |
---|
| 392 | + return BLK_STS_OK; |
---|
301 | 393 | } |
---|
302 | 394 | |
---|
303 | 395 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, |
---|
.. | .. |
---|
381 | 473 | struct btrfs_csum_item); |
---|
382 | 474 | while (start < csum_end) { |
---|
383 | 475 | size = min_t(size_t, csum_end - start, |
---|
384 | | - MAX_ORDERED_SUM_BYTES(fs_info)); |
---|
| 476 | + max_ordered_sum_bytes(fs_info, csum_size)); |
---|
385 | 477 | sums = kzalloc(btrfs_ordered_sum_size(fs_info, size), |
---|
386 | 478 | GFP_NOFS); |
---|
387 | 479 | if (!sums) { |
---|
.. | .. |
---|
420 | 512 | return ret; |
---|
421 | 513 | } |
---|
422 | 514 | |
---|
423 | | -blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio, |
---|
| 515 | +/* |
---|
| 516 | + * btrfs_csum_one_bio - Calculates checksums of the data contained inside a bio |
---|
| 517 | + * @inode: Owner of the data inside the bio |
---|
| 518 | + * @bio: Contains the data to be checksummed |
---|
| 519 | + * @file_start: offset in file this bio begins to describe |
---|
| 520 | + * @contig: Boolean. If true/1 means all bio vecs in this bio are |
---|
| 521 | + * contiguous and they begin at @file_start in the file. False/0 |
---|
| 522 | + * means this bio can contains potentially discontigous bio vecs |
---|
| 523 | + * so the logical offset of each should be calculated separately. |
---|
| 524 | + */ |
---|
| 525 | +blk_status_t btrfs_csum_one_bio(struct btrfs_inode *inode, struct bio *bio, |
---|
424 | 526 | u64 file_start, int contig) |
---|
425 | 527 | { |
---|
426 | | - struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
---|
| 528 | + struct btrfs_fs_info *fs_info = inode->root->fs_info; |
---|
| 529 | + SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); |
---|
427 | 530 | struct btrfs_ordered_sum *sums; |
---|
428 | 531 | struct btrfs_ordered_extent *ordered = NULL; |
---|
429 | 532 | char *data; |
---|
.. | .. |
---|
435 | 538 | unsigned long this_sum_bytes = 0; |
---|
436 | 539 | int i; |
---|
437 | 540 | u64 offset; |
---|
| 541 | + unsigned nofs_flag; |
---|
| 542 | + const u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); |
---|
438 | 543 | |
---|
439 | | - sums = kzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size), |
---|
440 | | - GFP_NOFS); |
---|
| 544 | + nofs_flag = memalloc_nofs_save(); |
---|
| 545 | + sums = kvzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size), |
---|
| 546 | + GFP_KERNEL); |
---|
| 547 | + memalloc_nofs_restore(nofs_flag); |
---|
| 548 | + |
---|
441 | 549 | if (!sums) |
---|
442 | 550 | return BLK_STS_RESOURCE; |
---|
443 | 551 | |
---|
.. | .. |
---|
452 | 560 | sums->bytenr = (u64)bio->bi_iter.bi_sector << 9; |
---|
453 | 561 | index = 0; |
---|
454 | 562 | |
---|
| 563 | + shash->tfm = fs_info->csum_shash; |
---|
| 564 | + |
---|
455 | 565 | bio_for_each_segment(bvec, bio, iter) { |
---|
456 | 566 | if (!contig) |
---|
457 | 567 | offset = page_offset(bvec.bv_page) + bvec.bv_offset; |
---|
458 | 568 | |
---|
459 | 569 | if (!ordered) { |
---|
460 | 570 | ordered = btrfs_lookup_ordered_extent(inode, offset); |
---|
461 | | - BUG_ON(!ordered); /* Logic error */ |
---|
| 571 | + /* |
---|
| 572 | + * The bio range is not covered by any ordered extent, |
---|
| 573 | + * must be a code logic error. |
---|
| 574 | + */ |
---|
| 575 | + if (unlikely(!ordered)) { |
---|
| 576 | + WARN(1, KERN_WARNING |
---|
| 577 | + "no ordered extent for root %llu ino %llu offset %llu\n", |
---|
| 578 | + inode->root->root_key.objectid, |
---|
| 579 | + btrfs_ino(inode), offset); |
---|
| 580 | + kvfree(sums); |
---|
| 581 | + return BLK_STS_IOERR; |
---|
| 582 | + } |
---|
462 | 583 | } |
---|
463 | | - |
---|
464 | | - data = kmap_atomic(bvec.bv_page); |
---|
465 | 584 | |
---|
466 | 585 | nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, |
---|
467 | 586 | bvec.bv_len + fs_info->sectorsize |
---|
468 | 587 | - 1); |
---|
469 | 588 | |
---|
470 | 589 | for (i = 0; i < nr_sectors; i++) { |
---|
471 | | - if (offset >= ordered->file_offset + ordered->len || |
---|
472 | | - offset < ordered->file_offset) { |
---|
| 590 | + if (offset >= ordered->file_offset + ordered->num_bytes || |
---|
| 591 | + offset < ordered->file_offset) { |
---|
473 | 592 | unsigned long bytes_left; |
---|
474 | 593 | |
---|
475 | | - kunmap_atomic(data); |
---|
476 | 594 | sums->len = this_sum_bytes; |
---|
477 | 595 | this_sum_bytes = 0; |
---|
478 | | - btrfs_add_ordered_sum(inode, ordered, sums); |
---|
| 596 | + btrfs_add_ordered_sum(ordered, sums); |
---|
479 | 597 | btrfs_put_ordered_extent(ordered); |
---|
480 | 598 | |
---|
481 | 599 | bytes_left = bio->bi_iter.bi_size - total_bytes; |
---|
482 | 600 | |
---|
483 | | - sums = kzalloc(btrfs_ordered_sum_size(fs_info, bytes_left), |
---|
484 | | - GFP_NOFS); |
---|
485 | | - BUG_ON(!sums); /* -ENOMEM */ |
---|
| 601 | + nofs_flag = memalloc_nofs_save(); |
---|
| 602 | + sums = kvzalloc(btrfs_ordered_sum_size(fs_info, |
---|
| 603 | + bytes_left), GFP_KERNEL); |
---|
| 604 | + memalloc_nofs_restore(nofs_flag); |
---|
| 605 | + if (!sums) |
---|
| 606 | + return BLK_STS_RESOURCE; |
---|
| 607 | + |
---|
486 | 608 | sums->len = bytes_left; |
---|
487 | 609 | ordered = btrfs_lookup_ordered_extent(inode, |
---|
488 | 610 | offset); |
---|
.. | .. |
---|
490 | 612 | sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) |
---|
491 | 613 | + total_bytes; |
---|
492 | 614 | index = 0; |
---|
493 | | - |
---|
494 | | - data = kmap_atomic(bvec.bv_page); |
---|
495 | 615 | } |
---|
496 | 616 | |
---|
497 | | - sums->sums[index] = ~(u32)0; |
---|
498 | | - sums->sums[index] |
---|
499 | | - = btrfs_csum_data(data + bvec.bv_offset |
---|
500 | | - + (i * fs_info->sectorsize), |
---|
501 | | - sums->sums[index], |
---|
502 | | - fs_info->sectorsize); |
---|
503 | | - btrfs_csum_final(sums->sums[index], |
---|
504 | | - (char *)(sums->sums + index)); |
---|
505 | | - index++; |
---|
| 617 | + data = kmap_atomic(bvec.bv_page); |
---|
| 618 | + crypto_shash_digest(shash, data + bvec.bv_offset |
---|
| 619 | + + (i * fs_info->sectorsize), |
---|
| 620 | + fs_info->sectorsize, |
---|
| 621 | + sums->sums + index); |
---|
| 622 | + kunmap_atomic(data); |
---|
| 623 | + index += csum_size; |
---|
506 | 624 | offset += fs_info->sectorsize; |
---|
507 | 625 | this_sum_bytes += fs_info->sectorsize; |
---|
508 | 626 | total_bytes += fs_info->sectorsize; |
---|
509 | 627 | } |
---|
510 | 628 | |
---|
511 | | - kunmap_atomic(data); |
---|
512 | 629 | } |
---|
513 | 630 | this_sum_bytes = 0; |
---|
514 | | - btrfs_add_ordered_sum(inode, ordered, sums); |
---|
| 631 | + btrfs_add_ordered_sum(ordered, sums); |
---|
515 | 632 | btrfs_put_ordered_extent(ordered); |
---|
516 | 633 | return 0; |
---|
517 | 634 | } |
---|
.. | .. |
---|
552 | 669 | */ |
---|
553 | 670 | u32 new_size = (bytenr - key->offset) >> blocksize_bits; |
---|
554 | 671 | new_size *= csum_size; |
---|
555 | | - btrfs_truncate_item(fs_info, path, new_size, 1); |
---|
| 672 | + btrfs_truncate_item(path, new_size, 1); |
---|
556 | 673 | } else if (key->offset >= bytenr && csum_end > end_byte && |
---|
557 | 674 | end_byte > key->offset) { |
---|
558 | 675 | /* |
---|
.. | .. |
---|
564 | 681 | u32 new_size = (csum_end - end_byte) >> blocksize_bits; |
---|
565 | 682 | new_size *= csum_size; |
---|
566 | 683 | |
---|
567 | | - btrfs_truncate_item(fs_info, path, new_size, 0); |
---|
| 684 | + btrfs_truncate_item(path, new_size, 0); |
---|
568 | 685 | |
---|
569 | 686 | key->offset = end_byte; |
---|
570 | 687 | btrfs_set_item_key_safe(fs_info, path, key); |
---|
.. | .. |
---|
767 | 884 | } |
---|
768 | 885 | ret = PTR_ERR(item); |
---|
769 | 886 | if (ret != -EFBIG && ret != -ENOENT) |
---|
770 | | - goto fail_unlock; |
---|
| 887 | + goto out; |
---|
771 | 888 | |
---|
772 | 889 | if (ret == -EFBIG) { |
---|
773 | 890 | u32 item_size; |
---|
.. | .. |
---|
805 | 922 | } |
---|
806 | 923 | |
---|
807 | 924 | /* |
---|
808 | | - * at this point, we know the tree has an item, but it isn't big |
---|
809 | | - * enough yet to put our csum in. Grow it |
---|
| 925 | + * At this point, we know the tree has a checksum item that ends at an |
---|
| 926 | + * offset matching the start of the checksum range we want to insert. |
---|
| 927 | + * We try to extend that item as much as possible and then add as many |
---|
| 928 | + * checksums to it as they fit. |
---|
| 929 | + * |
---|
| 930 | + * First check if the leaf has enough free space for at least one |
---|
| 931 | + * checksum. If it has go directly to the item extension code, otherwise |
---|
| 932 | + * release the path and do a search for insertion before the extension. |
---|
810 | 933 | */ |
---|
| 934 | + if (btrfs_leaf_free_space(leaf) >= csum_size) { |
---|
| 935 | + btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
---|
| 936 | + csum_offset = (bytenr - found_key.offset) >> |
---|
| 937 | + fs_info->sb->s_blocksize_bits; |
---|
| 938 | + goto extend_csum; |
---|
| 939 | + } |
---|
| 940 | + |
---|
811 | 941 | btrfs_release_path(path); |
---|
812 | 942 | ret = btrfs_search_slot(trans, root, &file_key, path, |
---|
813 | 943 | csum_size, 1); |
---|
814 | 944 | if (ret < 0) |
---|
815 | | - goto fail_unlock; |
---|
| 945 | + goto out; |
---|
816 | 946 | |
---|
817 | 947 | if (ret > 0) { |
---|
818 | 948 | if (path->slots[0] == 0) |
---|
.. | .. |
---|
831 | 961 | goto insert; |
---|
832 | 962 | } |
---|
833 | 963 | |
---|
| 964 | +extend_csum: |
---|
834 | 965 | if (csum_offset == btrfs_item_size_nr(leaf, path->slots[0]) / |
---|
835 | 966 | csum_size) { |
---|
836 | 967 | int extend_nr; |
---|
837 | 968 | u64 tmp; |
---|
838 | 969 | u32 diff; |
---|
839 | | - u32 free_space; |
---|
840 | 970 | |
---|
841 | | - if (btrfs_leaf_free_space(fs_info, leaf) < |
---|
842 | | - sizeof(struct btrfs_item) + csum_size * 2) |
---|
843 | | - goto insert; |
---|
844 | | - |
---|
845 | | - free_space = btrfs_leaf_free_space(fs_info, leaf) - |
---|
846 | | - sizeof(struct btrfs_item) - csum_size; |
---|
847 | 971 | tmp = sums->len - total_bytes; |
---|
848 | 972 | tmp >>= fs_info->sb->s_blocksize_bits; |
---|
849 | 973 | WARN_ON(tmp < 1); |
---|
.. | .. |
---|
854 | 978 | MAX_CSUM_ITEMS(fs_info, csum_size) * csum_size); |
---|
855 | 979 | |
---|
856 | 980 | diff = diff - btrfs_item_size_nr(leaf, path->slots[0]); |
---|
857 | | - diff = min(free_space, diff); |
---|
| 981 | + diff = min_t(u32, btrfs_leaf_free_space(leaf), diff); |
---|
858 | 982 | diff /= csum_size; |
---|
859 | 983 | diff *= csum_size; |
---|
860 | 984 | |
---|
861 | | - btrfs_extend_item(fs_info, path, diff); |
---|
| 985 | + btrfs_extend_item(path, diff); |
---|
862 | 986 | ret = 0; |
---|
863 | 987 | goto csum; |
---|
864 | 988 | } |
---|
.. | .. |
---|
885 | 1009 | ins_size); |
---|
886 | 1010 | path->leave_spinning = 0; |
---|
887 | 1011 | if (ret < 0) |
---|
888 | | - goto fail_unlock; |
---|
| 1012 | + goto out; |
---|
889 | 1013 | if (WARN_ON(ret != 0)) |
---|
890 | | - goto fail_unlock; |
---|
| 1014 | + goto out; |
---|
891 | 1015 | leaf = path->nodes[0]; |
---|
892 | 1016 | csum: |
---|
893 | 1017 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); |
---|
.. | .. |
---|
904 | 1028 | write_extent_buffer(leaf, sums->sums + index, (unsigned long)item, |
---|
905 | 1029 | ins_size); |
---|
906 | 1030 | |
---|
| 1031 | + index += ins_size; |
---|
907 | 1032 | ins_size /= csum_size; |
---|
908 | 1033 | total_bytes += ins_size * fs_info->sectorsize; |
---|
909 | | - index += ins_size; |
---|
910 | 1034 | |
---|
911 | 1035 | btrfs_mark_buffer_dirty(path->nodes[0]); |
---|
912 | 1036 | if (total_bytes < sums->len) { |
---|
.. | .. |
---|
917 | 1041 | out: |
---|
918 | 1042 | btrfs_free_path(path); |
---|
919 | 1043 | return ret; |
---|
920 | | - |
---|
921 | | -fail_unlock: |
---|
922 | | - goto out; |
---|
923 | 1044 | } |
---|
924 | 1045 | |
---|
925 | 1046 | void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode, |
---|
.. | .. |
---|
938 | 1059 | u8 type = btrfs_file_extent_type(leaf, fi); |
---|
939 | 1060 | int compress_type = btrfs_file_extent_compression(leaf, fi); |
---|
940 | 1061 | |
---|
941 | | - em->bdev = fs_info->fs_devices->latest_bdev; |
---|
942 | 1062 | btrfs_item_key_to_cpu(leaf, &key, slot); |
---|
943 | 1063 | extent_start = key.offset; |
---|
944 | | - |
---|
945 | | - if (type == BTRFS_FILE_EXTENT_REG || |
---|
946 | | - type == BTRFS_FILE_EXTENT_PREALLOC) { |
---|
947 | | - extent_end = extent_start + |
---|
948 | | - btrfs_file_extent_num_bytes(leaf, fi); |
---|
949 | | - } else if (type == BTRFS_FILE_EXTENT_INLINE) { |
---|
950 | | - size_t size; |
---|
951 | | - size = btrfs_file_extent_ram_bytes(leaf, fi); |
---|
952 | | - extent_end = ALIGN(extent_start + size, |
---|
953 | | - fs_info->sectorsize); |
---|
954 | | - } |
---|
955 | | - |
---|
| 1064 | + extent_end = btrfs_file_extent_end(path); |
---|
956 | 1065 | em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi); |
---|
957 | 1066 | if (type == BTRFS_FILE_EXTENT_REG || |
---|
958 | 1067 | type == BTRFS_FILE_EXTENT_PREALLOC) { |
---|
.. | .. |
---|
999 | 1108 | root->root_key.objectid); |
---|
1000 | 1109 | } |
---|
1001 | 1110 | } |
---|
| 1111 | + |
---|
| 1112 | +/* |
---|
| 1113 | + * Returns the end offset (non inclusive) of the file extent item the given path |
---|
| 1114 | + * points to. If it points to an inline extent, the returned offset is rounded |
---|
| 1115 | + * up to the sector size. |
---|
| 1116 | + */ |
---|
| 1117 | +u64 btrfs_file_extent_end(const struct btrfs_path *path) |
---|
| 1118 | +{ |
---|
| 1119 | + const struct extent_buffer *leaf = path->nodes[0]; |
---|
| 1120 | + const int slot = path->slots[0]; |
---|
| 1121 | + struct btrfs_file_extent_item *fi; |
---|
| 1122 | + struct btrfs_key key; |
---|
| 1123 | + u64 end; |
---|
| 1124 | + |
---|
| 1125 | + btrfs_item_key_to_cpu(leaf, &key, slot); |
---|
| 1126 | + ASSERT(key.type == BTRFS_EXTENT_DATA_KEY); |
---|
| 1127 | + fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); |
---|
| 1128 | + |
---|
| 1129 | + if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) { |
---|
| 1130 | + end = btrfs_file_extent_ram_bytes(leaf, fi); |
---|
| 1131 | + end = ALIGN(key.offset + end, leaf->fs_info->sectorsize); |
---|
| 1132 | + } else { |
---|
| 1133 | + end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); |
---|
| 1134 | + } |
---|
| 1135 | + |
---|
| 1136 | + return end; |
---|
| 1137 | +} |
---|