From patchwork Thu May 31 18:07:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 923532 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="Y32BI9Ob"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40xb66057bz9s0x for ; Fri, 1 Jun 2018 04:07:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756024AbeEaSHf (ORCPT ); Thu, 31 May 2018 14:07:35 -0400 Received: from bombadil.infradead.org ([198.137.202.133]:50838 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755824AbeEaSHb (ORCPT ); Thu, 31 May 2018 14:07:31 -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=mjhwCZnIE57+qgEa7p8QQiWPjGaaZ2hJ+2Uv5ygekt4=; b=Y32BI9ObE4OIL1eL/G9rhb/ZZ zsSG2GkL9czVtkhM4+fQOXshuYWE9St4Gm0PokCmHmF0duU+/6E0EbkanETbaitAHbt7ihNT696vW 7BbaB2nhQimSxqS5RtMlUtOGU/mK1VfnekvSedkFBakY2zBIHTPX4t2eQSn3jiYNKWrGinKBO9VbV qmLyeXFpP2lf5vjKEWLQoZZJcIaAupimAMvLozGCU7+Dv80xpU1cqxyJKqZspaQgSK4hGr3Y5CEQQ +wcovllbDx5ebwQ4c9W4TuPP62ppDWJ5Aen1owAhmDpJUlo3jC8MZbFpLNkOiW3WG6CeOIdQsk1JM liXEVcgsw==; 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 1fORz0-0003ZJ-Lg; Thu, 31 May 2018 18:07:31 +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: Thu, 31 May 2018 20:07:22 +0200 Message-Id: <20180531180724.21573-2-hch@lst.de> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531180724.21573-1-hch@lst.de> References: <20180531180724.21573-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: Andreas Gruenbacher Reviewed-by: Dave Chinner Reviewed-by: Darrick J. Wong --- 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 106720355963..f553a2d8a5fa 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -804,6 +805,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 Thu May 31 18:07:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 923531 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="jHFy6npD"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40xb6306mxz9s0x for ; Fri, 1 Jun 2018 04:07:39 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756028AbeEaSHh (ORCPT ); Thu, 31 May 2018 14:07:37 -0400 Received: from bombadil.infradead.org ([198.137.202.133]:50846 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756013AbeEaSHe (ORCPT ); Thu, 31 May 2018 14:07:34 -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=2r1/MqZvfTzjdc7jHbM4pqQ2B1bMFjNOBQjNjJrOclM=; b=jHFy6npDvyGTaby7I7+/VT1Xe 52S4KKsnuCfCcqGQPBWYNTLUixkGCNoM62f2QIc8KChik7iMX454GQi39lLLlW8+Agayq065KT0pF BGoOthKVrYxn6JVA0rzrjA4k6BGm+KdmAdA1rdNazVDmMvNsb4Qv+BNRZpVpo9XQuUUujIGduESJq oFj71ySAoHLLL8cRm/bcrzxL96jDCWqLw2pZ0x72fnwFzEcBoCcYH011Sb0CLp5hHOpbBGlBWC2h1 I3nexhGnyQVNk/iPoxBxF12/XftHZ1JR2shO6MWS3vH1dh4+Tl0ZmRyQVg503yIk3iTvM+vJ+kyeg j0ygdQtgA==; 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 1fORz3-0003aA-TS; Thu, 31 May 2018 18:07:34 +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: Thu, 31 May 2018 20:07:23 +0200 Message-Id: <20180531180724.21573-3-hch@lst.de> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531180724.21573-1-hch@lst.de> References: <20180531180724.21573-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: Andreas Gruenbacher Reviewed-by: Darrick J. Wong 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 f553a2d8a5fa..e93bd4eb7fa7 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -827,14 +827,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; @@ -846,8 +841,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 Thu May 31 18:07:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 923533 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="o3mxwzic"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 40xb694T0Cz9s0x for ; Fri, 1 Jun 2018 04:07:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756036AbeEaSHl (ORCPT ); Thu, 31 May 2018 14:07:41 -0400 Received: from bombadil.infradead.org ([198.137.202.133]:50856 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756013AbeEaSHh (ORCPT ); Thu, 31 May 2018 14:07:37 -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=5hGvpZn97uorpyzHYXvgIUe50l3rhcTjfX6q5Kml/1g=; b=o3mxwzicEjf/7tczsr3CZCaxQ U8+7VV6JPCPm1VuhC+r1lCXuyap9/38L8ZxAAZYUXE/zc7TjIWTxMhJ4wMUIam4i3u9PUM7FOe078 qvtwQkM+MfaRQBPS16AUkL469n7JlxvhZifFtmZTxgoJ4HKH/IH+8L/HfgzVJlf7+cYvQlU90S8z/ duYhF+vXl2auBBUlcWyychD32amr/TKJe/OESdncrx688FebbBoG8FzplMZhD17MCVVoLZY86Dax2 QZO8hu6ISYqlqYgGm77tIC3nh3bHjzSVvwqxw5xRbY49XhGDvK/y9haRNlDpXn1xIxuGzs2bUQaX1 fm/PcYatA==; 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 1fORz7-0003aR-23; Thu, 31 May 2018 18:07:37 +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: Thu, 31 May 2018 20:07:24 +0200 Message-Id: <20180531180724.21573-4-hch@lst.de> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531180724.21573-1-hch@lst.de> References: <20180531180724.21573-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 Reviewed-by: Darrick J. Wong --- fs/iomap.c | 83 ++++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/fs/iomap.c b/fs/iomap.c index e93bd4eb7fa7..49119e64edc3 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -807,34 +807,53 @@ 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. + * Returns true if found and updates @lastoff to the offset in file. */ -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; + } - lastoff = offset; - } while ((bh = bh->b_this_page) != head); - return -ENOENT; + /* + * 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; + + 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; } /* @@ -871,30 +890,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);