diff options
Diffstat (limited to 'fs/buffer.c')
-rw-r--r-- | fs/buffer.c | 114 |
1 files changed, 0 insertions, 114 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index 249b83fafe48..cabc045f483d 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -3427,120 +3427,6 @@ int bh_submit_read(struct buffer_head *bh) | |||
3427 | } | 3427 | } |
3428 | EXPORT_SYMBOL(bh_submit_read); | 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 | void __init buffer_init(void) | 3430 | void __init buffer_init(void) |
3545 | { | 3431 | { |
3546 | unsigned long nrpages; | 3432 | unsigned long nrpages; |