From patchwork Wed May 30 10:02:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 922680 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-ext4-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="cp+lRaBs"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40wmNZ364Fz9s1R for ; Wed, 30 May 2018 20:02:22 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751801AbeE3KCU (ORCPT ); Wed, 30 May 2018 06:02:20 -0400 Received: from bombadil.infradead.org ([198.137.202.133]:38684 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751336AbeE3KCQ (ORCPT ); Wed, 30 May 2018 06:02:16 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=DqEXFCpffDbioSH1biz8hSU19B/fMKnHzNzNhIlU7ug=; b=cp+lRaBspvAcWExcQyuqwW3V/ /4bDG02WSx6A2KOS1wbMNy2cBQY3Uq4wWVGtAAaWokYrISIRc+kURf5bhHa8uaYB/k/e0e3XVfsUo JV5NwqWaugvToqe/kfLtdk9bsrh1pODOJDTky/93Y964Otq/nHJYm/0s0diVY5lauaOFPz3cccGTz lQMkz7hWvDVXp7MvP3mQ9tp8BI2azeaG0PCOm2I0o5ZkYfndeCNlrMx8xH9ejucv47AuHnbvtU5DG tuCADPy5i2aPf50W0gNxv893xUktJS9c3f5J+tpH5DSXRJZZDPDDHfnw8I9YlwU+RzzBmibnzrwY3 E0RR72q5w==; Received: from 213-225-38-123.nat.highway.a1.net ([213.225.38.123] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.90_1 #2 (Red Hat Linux)) id 1fNxvr-0000O2-Bo; Wed, 30 May 2018 10:02:15 +0000 From: Christoph Hellwig To: linux-xfs@vger.kernel.org Cc: Andreas Gruenbacher , linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org Subject: [PATCH 1/3] fs: move page_cache_seek_hole_data to iomap.c Date: Wed, 30 May 2018 12:02:06 +0200 Message-Id: <20180530100208.31490-2-hch@lst.de> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180530100208.31490-1-hch@lst.de> References: <20180530100208.31490-1-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org 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 Reviewed-by: Dave Chinner --- fs/buffer.c | 114 ----------------------------------- fs/iomap.c | 116 ++++++++++++++++++++++++++++++++++++ include/linux/buffer_head.h | 2 - 3 files changed, 116 insertions(+), 116 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) } EXPORT_SYMBOL(bh_submit_read); -/* - * Seek for SEEK_DATA / SEEK_HOLE within @page, starting at @lastoff. - * - * Returns the offset within the file on success, and -ENOENT otherwise. - */ -static loff_t -page_seek_hole_data(struct page *page, loff_t lastoff, int whence) -{ - loff_t offset = page_offset(page); - struct buffer_head *bh, *head; - bool seek_data = whence == SEEK_DATA; - - if (lastoff < offset) - lastoff = offset; - - bh = head = page_buffers(page); - do { - offset += bh->b_size; - if (lastoff >= offset) - continue; - - /* - * Unwritten extents that have data in the page cache covering - * them can be identified by the BH_Unwritten state flag. - * Pages with multiple buffers might have a mix of holes, data - * and unwritten extents - any buffer with valid data in it - * should have BH_Uptodate flag set on it. - */ - - if ((buffer_unwritten(bh) || buffer_uptodate(bh)) == seek_data) - return lastoff; - - lastoff = offset; - } while ((bh = bh->b_this_page) != head); - return -ENOENT; -} - -/* - * Seek for SEEK_DATA / SEEK_HOLE in the page cache. - * - * Within unwritten extents, the page cache determines which parts are holes - * and which are data: unwritten and uptodate buffer heads count as data; - * everything else counts as a hole. - * - * Returns the resulting offset on successs, and -ENOENT otherwise. - */ -loff_t -page_cache_seek_hole_data(struct inode *inode, loff_t offset, loff_t length, - int whence) -{ - pgoff_t index = offset >> PAGE_SHIFT; - pgoff_t end = DIV_ROUND_UP(offset + length, PAGE_SIZE); - loff_t lastoff = offset; - struct pagevec pvec; - - if (length <= 0) - return -ENOENT; - - pagevec_init(&pvec); - - do { - unsigned nr_pages, i; - - nr_pages = pagevec_lookup_range(&pvec, inode->i_mapping, &index, - end - 1); - if (nr_pages == 0) - break; - - for (i = 0; i < nr_pages; i++) { - struct page *page = pvec.pages[i]; - - /* - * At this point, the page may be truncated or - * invalidated (changing page->mapping to NULL), or - * even swizzled back from swapper_space to tmpfs file - * mapping. However, page->index will not change - * because we have a reference on the page. - * - * If current page offset is beyond where we've ended, - * we've found a hole. - */ - if (whence == SEEK_HOLE && - lastoff < page_offset(page)) - goto check_range; - - lock_page(page); - if (likely(page->mapping == inode->i_mapping) && - page_has_buffers(page)) { - lastoff = page_seek_hole_data(page, lastoff, whence); - if (lastoff >= 0) { - unlock_page(page); - goto check_range; - } - } - unlock_page(page); - lastoff = page_offset(page) + PAGE_SIZE; - } - pagevec_release(&pvec); - } while (index < end); - - /* When no page at lastoff and we are not done, we found a hole. */ - if (whence != SEEK_HOLE) - goto not_found; - -check_range: - if (lastoff < offset + length) - goto out; -not_found: - lastoff = -ENOENT; -out: - pagevec_release(&pvec); - return lastoff; -} - void __init buffer_init(void) { unsigned long nrpages; diff --git a/fs/iomap.c b/fs/iomap.c index 5e5a266e3325..c2d4fd551fed 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -793,6 +794,121 @@ int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi, } EXPORT_SYMBOL_GPL(iomap_fiemap); +/* + * Seek for SEEK_DATA / SEEK_HOLE within @page, starting at @lastoff. + * + * Returns the offset within the file on success, and -ENOENT otherwise. + */ +static loff_t +page_seek_hole_data(struct page *page, loff_t lastoff, int whence) +{ + loff_t offset = page_offset(page); + struct buffer_head *bh, *head; + bool seek_data = whence == SEEK_DATA; + + if (lastoff < offset) + lastoff = offset; + + bh = head = page_buffers(page); + do { + offset += bh->b_size; + if (lastoff >= offset) + continue; + + /* + * Unwritten extents that have data in the page cache covering + * them can be identified by the BH_Unwritten state flag. + * Pages with multiple buffers might have a mix of holes, data + * and unwritten extents - any buffer with valid data in it + * should have BH_Uptodate flag set on it. + */ + + if ((buffer_unwritten(bh) || buffer_uptodate(bh)) == seek_data) + return lastoff; + + lastoff = offset; + } while ((bh = bh->b_this_page) != head); + return -ENOENT; +} + +/* + * Seek for SEEK_DATA / SEEK_HOLE in the page cache. + * + * Within unwritten extents, the page cache determines which parts are holes + * and which are data: unwritten and uptodate buffer heads count as data; + * everything else counts as a hole. + * + * Returns the resulting offset on successs, and -ENOENT otherwise. + */ +static loff_t +page_cache_seek_hole_data(struct inode *inode, loff_t offset, loff_t length, + int whence) +{ + pgoff_t index = offset >> PAGE_SHIFT; + pgoff_t end = DIV_ROUND_UP(offset + length, PAGE_SIZE); + loff_t lastoff = offset; + struct pagevec pvec; + + if (length <= 0) + return -ENOENT; + + pagevec_init(&pvec); + + do { + unsigned nr_pages, i; + + nr_pages = pagevec_lookup_range(&pvec, inode->i_mapping, &index, + end - 1); + if (nr_pages == 0) + break; + + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + + /* + * At this point, the page may be truncated or + * invalidated (changing page->mapping to NULL), or + * even swizzled back from swapper_space to tmpfs file + * mapping. However, page->index will not change + * because we have a reference on the page. + * + * If current page offset is beyond where we've ended, + * we've found a hole. + */ + if (whence == SEEK_HOLE && + lastoff < page_offset(page)) + goto check_range; + + lock_page(page); + if (likely(page->mapping == inode->i_mapping) && + page_has_buffers(page)) { + lastoff = page_seek_hole_data(page, lastoff, whence); + if (lastoff >= 0) { + unlock_page(page); + goto check_range; + } + } + unlock_page(page); + lastoff = page_offset(page) + PAGE_SIZE; + } + pagevec_release(&pvec); + } while (index < end); + + /* When no page at lastoff and we are not done, we found a hole. */ + if (whence != SEEK_HOLE) + goto not_found; + +check_range: + if (lastoff < offset + length) + goto out; +not_found: + lastoff = -ENOENT; +out: + pagevec_release(&pvec); + return lastoff; +} + + static loff_t iomap_seek_hole_actor(struct inode *inode, loff_t offset, loff_t length, void *data, struct iomap *iomap) diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 894e5d125de6..96225a77c112 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -205,8 +205,6 @@ void write_boundary_block(struct block_device *bdev, sector_t bblock, unsigned blocksize); int bh_uptodate_or_lock(struct buffer_head *bh); int bh_submit_read(struct buffer_head *bh); -loff_t page_cache_seek_hole_data(struct inode *inode, loff_t offset, - loff_t length, int whence); extern int buffer_heads_over_limit; From patchwork Wed May 30 10:02:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 922681 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-ext4-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="cw7w4rkD"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40wmNh2kyvz9s1b for ; Wed, 30 May 2018 20:02:28 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751824AbeE3KCZ (ORCPT ); Wed, 30 May 2018 06:02:25 -0400 Received: from bombadil.infradead.org ([198.137.202.133]:38690 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751777AbeE3KCT (ORCPT ); Wed, 30 May 2018 06:02:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=ir9IkKbcHto2kbnj+JszU8aUXnLjeM2Mf4adp1C8vxk=; b=cw7w4rkDs3imL/yxGeXQRqOkv Zr80CX8pvOrOyWCDaBrNiXRkkpgtCcG+Ummv+6z2xlYb2y2lnlZIIbE/ZrNTXWtUSw2iBDWjXQUjm edh997I23ps02dvjSd6mM/IiUuliWY0JJf3rETdQ2JrOue7TRH3jOz/uE2k6Bjl5Zjm9UguB+ve1n yehoy3x+gBzQ0berSNe9aEzPeK1bhPo/osGweiPRVvMpudeOb6hlt8m08rBouTVh3pXLc3D8G0kc4 xHMvAmrQHQP5q+kwrzTQuB3g0dIp1cYbOIp/iMz3TtGH3hU3T/s3FlGMvXwKkpt6BnWKmbaIQezSA WdWwn+HSg==; Received: from 213-225-38-123.nat.highway.a1.net ([213.225.38.123] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.90_1 #2 (Red Hat Linux)) id 1fNxvu-0000Oo-SJ; Wed, 30 May 2018 10:02:19 +0000 From: Christoph Hellwig To: linux-xfs@vger.kernel.org Cc: Andreas Gruenbacher , linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org Subject: [PATCH 2/3] fs: remove the buffer_unwritten check in page_seek_hole_data Date: Wed, 30 May 2018 12:02:07 +0200 Message-Id: <20180530100208.31490-3-hch@lst.de> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180530100208.31490-1-hch@lst.de> References: <20180530100208.31490-1-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org We only call into this function through the iomap iterators, so we already know the buffer is unwritten. In addition to that we always require the uptodate flag that is ORed with the result anyway. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner --- fs/iomap.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/iomap.c b/fs/iomap.c index c2d4fd551fed..e75153f52748 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -816,14 +816,9 @@ page_seek_hole_data(struct page *page, loff_t lastoff, int whence) continue; /* - * Unwritten extents that have data in the page cache covering - * them can be identified by the BH_Unwritten state flag. - * Pages with multiple buffers might have a mix of holes, data - * and unwritten extents - any buffer with valid data in it - * should have BH_Uptodate flag set on it. + * Any buffer with valid data in it should have BH_Uptodate set. */ - - if ((buffer_unwritten(bh) || buffer_uptodate(bh)) == seek_data) + if (buffer_uptodate(bh) == seek_data) return lastoff; lastoff = offset; @@ -835,8 +830,8 @@ page_seek_hole_data(struct page *page, loff_t lastoff, int whence) * Seek for SEEK_DATA / SEEK_HOLE in the page cache. * * Within unwritten extents, the page cache determines which parts are holes - * and which are data: unwritten and uptodate buffer heads count as data; - * everything else counts as a hole. + * and which are data: uptodate buffer heads count as data; everything else + * counts as a hole. * * Returns the resulting offset on successs, and -ENOENT otherwise. */ From patchwork Wed May 30 10:02:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 922682 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-ext4-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=lst.de Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="iggD1qu4"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40wmNn35gJz9s1R for ; Wed, 30 May 2018 20:02:33 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751827AbeE3KC3 (ORCPT ); Wed, 30 May 2018 06:02:29 -0400 Received: from bombadil.infradead.org ([198.137.202.133]:38700 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751808AbeE3KCY (ORCPT ); Wed, 30 May 2018 06:02:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=PyMNrBRze5BQxkKW3kBGf6v2NU56MpT3rgWrBlvJMmo=; b=iggD1qu4FEDNmA695ivuHPJXo snZJoywg+chlnYACO/UVr/O3rU2tKPItnicF7jPVMuWmeQNIWXXjN0VuBWllhFmmjFXfCn3E4i+uj 0pp6IIXQO6kotFOfKyZwDHe7hVHEY9Km8rZg0DII5gfZcHJrk1c8otYyXEarjFo3pH3geCo8FO/Yl fjeupU2gLddFpa169fzjt2ioN4YY5vxwomGSwxjeI2jXtuRsJ2miaAoMeF4z1TaiC0icr+uonA+Kg Fmv8zojJL5uzHU++r4jtzqUUkbJTo53c+Lm5UMeW2o75GEZifNSJWkFTVfHfwf/s6W9muPsxOJdcw FC20qoQaQ==; Received: from 213-225-38-123.nat.highway.a1.net ([213.225.38.123] helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.90_1 #2 (Red Hat Linux)) id 1fNxvz-0000P6-2g; Wed, 30 May 2018 10:02:23 +0000 From: Christoph Hellwig To: linux-xfs@vger.kernel.org Cc: Andreas Gruenbacher , linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org Subject: [PATCH 3/3] fs: use ->is_partially_uptodate in page_cache_seek_hole_data Date: Wed, 30 May 2018 12:02:08 +0200 Message-Id: <20180530100208.31490-4-hch@lst.de> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180530100208.31490-1-hch@lst.de> References: <20180530100208.31490-1-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org This way the implementation doesn't depend on buffer_head internals. Signed-off-by: Christoph Hellwig Reviewed-by: Andreas Gruenbacher Reviewed-by: Dave Chinner --- fs/iomap.c | 85 +++++++++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/fs/iomap.c b/fs/iomap.c index e75153f52748..5b92243808d3 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -794,36 +794,51 @@ int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi, } EXPORT_SYMBOL_GPL(iomap_fiemap); -/* - * Seek for SEEK_DATA / SEEK_HOLE within @page, starting at @lastoff. - * - * Returns the offset within the file on success, and -ENOENT otherwise. - */ -static loff_t -page_seek_hole_data(struct page *page, loff_t lastoff, int whence) +static bool +page_seek_hole_data(struct inode *inode, struct page *page, loff_t *lastoff, + int whence) { - loff_t offset = page_offset(page); - struct buffer_head *bh, *head; + const struct address_space_operations *ops = inode->i_mapping->a_ops; + unsigned int bsize = i_blocksize(inode), off; bool seek_data = whence == SEEK_DATA; + loff_t poff = page_offset(page); - if (lastoff < offset) - lastoff = offset; - - bh = head = page_buffers(page); - do { - offset += bh->b_size; - if (lastoff >= offset) - continue; + if (WARN_ON_ONCE(*lastoff >= poff + PAGE_SIZE)) + return false; + if (*lastoff < poff) { /* - * Any buffer with valid data in it should have BH_Uptodate set. + * Last offset smaller than the start of the page means we found + * a hole: */ - if (buffer_uptodate(bh) == seek_data) - return lastoff; + if (whence == SEEK_HOLE) + return true; + *lastoff = poff; + } + + /* + * Just check the page unless we can and should check block ranges: + */ + if (bsize == PAGE_SIZE || !ops->is_partially_uptodate) + return PageUptodate(page) == seek_data; - lastoff = offset; - } while ((bh = bh->b_this_page) != head); - return -ENOENT; + lock_page(page); + if (unlikely(page->mapping != inode->i_mapping)) + goto out_unlock_not_found; + + for (off = 0; off < PAGE_SIZE; off += bsize) { + if ((*lastoff & ~PAGE_MASK) >= off + bsize) + continue; + if (ops->is_partially_uptodate(page, off, bsize) == seek_data) { + unlock_page(page); + return true; + } + *lastoff = poff + off + bsize; + } + +out_unlock_not_found: + unlock_page(page); + return false; } /* @@ -860,30 +875,8 @@ page_cache_seek_hole_data(struct inode *inode, loff_t offset, loff_t length, for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; - /* - * At this point, the page may be truncated or - * invalidated (changing page->mapping to NULL), or - * even swizzled back from swapper_space to tmpfs file - * mapping. However, page->index will not change - * because we have a reference on the page. - * - * If current page offset is beyond where we've ended, - * we've found a hole. - */ - if (whence == SEEK_HOLE && - lastoff < page_offset(page)) + if (page_seek_hole_data(inode, page, &lastoff, whence)) goto check_range; - - lock_page(page); - if (likely(page->mapping == inode->i_mapping) && - page_has_buffers(page)) { - lastoff = page_seek_hole_data(page, lastoff, whence); - if (lastoff >= 0) { - unlock_page(page); - goto check_range; - } - } - unlock_page(page); lastoff = page_offset(page) + PAGE_SIZE; } pagevec_release(&pvec);