Commit 8a78cb1f1b98e5ea970674e0f049832d19e76ace
Committed by
Darrick J. Wong
1 parent
b84e772299
fs: move page_cache_seek_hole_data to iomap.c
This function is only used by the iomap code, depends on being called from it, and will soon stop poking into buffer head internals. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Showing 3 changed files with 116 additions and 116 deletions Side-by-side Diff
fs/buffer.c
... | ... | @@ -3427,120 +3427,6 @@ |
3427 | 3427 | } |
3428 | 3428 | EXPORT_SYMBOL(bh_submit_read); |
3429 | 3429 | |
3430 | -/* | |
3431 | - * Seek for SEEK_DATA / SEEK_HOLE within @page, starting at @lastoff. | |
3432 | - * | |
3433 | - * Returns the offset within the file on success, and -ENOENT otherwise. | |
3434 | - */ | |
3435 | -static loff_t | |
3436 | -page_seek_hole_data(struct page *page, loff_t lastoff, int whence) | |
3437 | -{ | |
3438 | - loff_t offset = page_offset(page); | |
3439 | - struct buffer_head *bh, *head; | |
3440 | - bool seek_data = whence == SEEK_DATA; | |
3441 | - | |
3442 | - if (lastoff < offset) | |
3443 | - lastoff = offset; | |
3444 | - | |
3445 | - bh = head = page_buffers(page); | |
3446 | - do { | |
3447 | - offset += bh->b_size; | |
3448 | - if (lastoff >= offset) | |
3449 | - continue; | |
3450 | - | |
3451 | - /* | |
3452 | - * Unwritten extents that have data in the page cache covering | |
3453 | - * them can be identified by the BH_Unwritten state flag. | |
3454 | - * Pages with multiple buffers might have a mix of holes, data | |
3455 | - * and unwritten extents - any buffer with valid data in it | |
3456 | - * should have BH_Uptodate flag set on it. | |
3457 | - */ | |
3458 | - | |
3459 | - if ((buffer_unwritten(bh) || buffer_uptodate(bh)) == seek_data) | |
3460 | - return lastoff; | |
3461 | - | |
3462 | - lastoff = offset; | |
3463 | - } while ((bh = bh->b_this_page) != head); | |
3464 | - return -ENOENT; | |
3465 | -} | |
3466 | - | |
3467 | -/* | |
3468 | - * Seek for SEEK_DATA / SEEK_HOLE in the page cache. | |
3469 | - * | |
3470 | - * Within unwritten extents, the page cache determines which parts are holes | |
3471 | - * and which are data: unwritten and uptodate buffer heads count as data; | |
3472 | - * everything else counts as a hole. | |
3473 | - * | |
3474 | - * Returns the resulting offset on successs, and -ENOENT otherwise. | |
3475 | - */ | |
3476 | -loff_t | |
3477 | -page_cache_seek_hole_data(struct inode *inode, loff_t offset, loff_t length, | |
3478 | - int whence) | |
3479 | -{ | |
3480 | - pgoff_t index = offset >> PAGE_SHIFT; | |
3481 | - pgoff_t end = DIV_ROUND_UP(offset + length, PAGE_SIZE); | |
3482 | - loff_t lastoff = offset; | |
3483 | - struct pagevec pvec; | |
3484 | - | |
3485 | - if (length <= 0) | |
3486 | - return -ENOENT; | |
3487 | - | |
3488 | - pagevec_init(&pvec); | |
3489 | - | |
3490 | - do { | |
3491 | - unsigned nr_pages, i; | |
3492 | - | |
3493 | - nr_pages = pagevec_lookup_range(&pvec, inode->i_mapping, &index, | |
3494 | - end - 1); | |
3495 | - if (nr_pages == 0) | |
3496 | - break; | |
3497 | - | |
3498 | - for (i = 0; i < nr_pages; i++) { | |
3499 | - struct page *page = pvec.pages[i]; | |
3500 | - | |
3501 | - /* | |
3502 | - * At this point, the page may be truncated or | |
3503 | - * invalidated (changing page->mapping to NULL), or | |
3504 | - * even swizzled back from swapper_space to tmpfs file | |
3505 | - * mapping. However, page->index will not change | |
3506 | - * because we have a reference on the page. | |
3507 | - * | |
3508 | - * If current page offset is beyond where we've ended, | |
3509 | - * we've found a hole. | |
3510 | - */ | |
3511 | - if (whence == SEEK_HOLE && | |
3512 | - lastoff < page_offset(page)) | |
3513 | - goto check_range; | |
3514 | - | |
3515 | - lock_page(page); | |
3516 | - if (likely(page->mapping == inode->i_mapping) && | |
3517 | - page_has_buffers(page)) { | |
3518 | - lastoff = page_seek_hole_data(page, lastoff, whence); | |
3519 | - if (lastoff >= 0) { | |
3520 | - unlock_page(page); | |
3521 | - goto check_range; | |
3522 | - } | |
3523 | - } | |
3524 | - unlock_page(page); | |
3525 | - lastoff = page_offset(page) + PAGE_SIZE; | |
3526 | - } | |
3527 | - pagevec_release(&pvec); | |
3528 | - } while (index < end); | |
3529 | - | |
3530 | - /* When no page at lastoff and we are not done, we found a hole. */ | |
3531 | - if (whence != SEEK_HOLE) | |
3532 | - goto not_found; | |
3533 | - | |
3534 | -check_range: | |
3535 | - if (lastoff < offset + length) | |
3536 | - goto out; | |
3537 | -not_found: | |
3538 | - lastoff = -ENOENT; | |
3539 | -out: | |
3540 | - pagevec_release(&pvec); | |
3541 | - return lastoff; | |
3542 | -} | |
3543 | - | |
3544 | 3430 | void __init buffer_init(void) |
3545 | 3431 | { |
3546 | 3432 | unsigned long nrpages; |
fs/iomap.c
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | #include <linux/mm.h> |
21 | 21 | #include <linux/swap.h> |
22 | 22 | #include <linux/pagemap.h> |
23 | +#include <linux/pagevec.h> | |
23 | 24 | #include <linux/file.h> |
24 | 25 | #include <linux/uio.h> |
25 | 26 | #include <linux/backing-dev.h> |
... | ... | @@ -591,6 +592,121 @@ |
591 | 592 | return 0; |
592 | 593 | } |
593 | 594 | EXPORT_SYMBOL_GPL(iomap_fiemap); |
595 | + | |
596 | +/* | |
597 | + * Seek for SEEK_DATA / SEEK_HOLE within @page, starting at @lastoff. | |
598 | + * | |
599 | + * Returns the offset within the file on success, and -ENOENT otherwise. | |
600 | + */ | |
601 | +static loff_t | |
602 | +page_seek_hole_data(struct page *page, loff_t lastoff, int whence) | |
603 | +{ | |
604 | + loff_t offset = page_offset(page); | |
605 | + struct buffer_head *bh, *head; | |
606 | + bool seek_data = whence == SEEK_DATA; | |
607 | + | |
608 | + if (lastoff < offset) | |
609 | + lastoff = offset; | |
610 | + | |
611 | + bh = head = page_buffers(page); | |
612 | + do { | |
613 | + offset += bh->b_size; | |
614 | + if (lastoff >= offset) | |
615 | + continue; | |
616 | + | |
617 | + /* | |
618 | + * Unwritten extents that have data in the page cache covering | |
619 | + * them can be identified by the BH_Unwritten state flag. | |
620 | + * Pages with multiple buffers might have a mix of holes, data | |
621 | + * and unwritten extents - any buffer with valid data in it | |
622 | + * should have BH_Uptodate flag set on it. | |
623 | + */ | |
624 | + | |
625 | + if ((buffer_unwritten(bh) || buffer_uptodate(bh)) == seek_data) | |
626 | + return lastoff; | |
627 | + | |
628 | + lastoff = offset; | |
629 | + } while ((bh = bh->b_this_page) != head); | |
630 | + return -ENOENT; | |
631 | +} | |
632 | + | |
633 | +/* | |
634 | + * Seek for SEEK_DATA / SEEK_HOLE in the page cache. | |
635 | + * | |
636 | + * Within unwritten extents, the page cache determines which parts are holes | |
637 | + * and which are data: unwritten and uptodate buffer heads count as data; | |
638 | + * everything else counts as a hole. | |
639 | + * | |
640 | + * Returns the resulting offset on successs, and -ENOENT otherwise. | |
641 | + */ | |
642 | +static loff_t | |
643 | +page_cache_seek_hole_data(struct inode *inode, loff_t offset, loff_t length, | |
644 | + int whence) | |
645 | +{ | |
646 | + pgoff_t index = offset >> PAGE_SHIFT; | |
647 | + pgoff_t end = DIV_ROUND_UP(offset + length, PAGE_SIZE); | |
648 | + loff_t lastoff = offset; | |
649 | + struct pagevec pvec; | |
650 | + | |
651 | + if (length <= 0) | |
652 | + return -ENOENT; | |
653 | + | |
654 | + pagevec_init(&pvec); | |
655 | + | |
656 | + do { | |
657 | + unsigned nr_pages, i; | |
658 | + | |
659 | + nr_pages = pagevec_lookup_range(&pvec, inode->i_mapping, &index, | |
660 | + end - 1); | |
661 | + if (nr_pages == 0) | |
662 | + break; | |
663 | + | |
664 | + for (i = 0; i < nr_pages; i++) { | |
665 | + struct page *page = pvec.pages[i]; | |
666 | + | |
667 | + /* | |
668 | + * At this point, the page may be truncated or | |
669 | + * invalidated (changing page->mapping to NULL), or | |
670 | + * even swizzled back from swapper_space to tmpfs file | |
671 | + * mapping. However, page->index will not change | |
672 | + * because we have a reference on the page. | |
673 | + * | |
674 | + * If current page offset is beyond where we've ended, | |
675 | + * we've found a hole. | |
676 | + */ | |
677 | + if (whence == SEEK_HOLE && | |
678 | + lastoff < page_offset(page)) | |
679 | + goto check_range; | |
680 | + | |
681 | + lock_page(page); | |
682 | + if (likely(page->mapping == inode->i_mapping) && | |
683 | + page_has_buffers(page)) { | |
684 | + lastoff = page_seek_hole_data(page, lastoff, whence); | |
685 | + if (lastoff >= 0) { | |
686 | + unlock_page(page); | |
687 | + goto check_range; | |
688 | + } | |
689 | + } | |
690 | + unlock_page(page); | |
691 | + lastoff = page_offset(page) + PAGE_SIZE; | |
692 | + } | |
693 | + pagevec_release(&pvec); | |
694 | + } while (index < end); | |
695 | + | |
696 | + /* When no page at lastoff and we are not done, we found a hole. */ | |
697 | + if (whence != SEEK_HOLE) | |
698 | + goto not_found; | |
699 | + | |
700 | +check_range: | |
701 | + if (lastoff < offset + length) | |
702 | + goto out; | |
703 | +not_found: | |
704 | + lastoff = -ENOENT; | |
705 | +out: | |
706 | + pagevec_release(&pvec); | |
707 | + return lastoff; | |
708 | +} | |
709 | + | |
594 | 710 | |
595 | 711 | static loff_t |
596 | 712 | iomap_seek_hole_actor(struct inode *inode, loff_t offset, loff_t length, |
include/linux/buffer_head.h
... | ... | @@ -205,8 +205,6 @@ |
205 | 205 | sector_t bblock, unsigned blocksize); |
206 | 206 | int bh_uptodate_or_lock(struct buffer_head *bh); |
207 | 207 | int bh_submit_read(struct buffer_head *bh); |
208 | -loff_t page_cache_seek_hole_data(struct inode *inode, loff_t offset, | |
209 | - loff_t length, int whence); | |
210 | 208 | |
211 | 209 | extern int buffer_heads_over_limit; |
212 | 210 |