[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200929124251.GB20115@casper.infradead.org>
Date: Tue, 29 Sep 2020 13:42:51 +0100
From: Matthew Wilcox <willy@...radead.org>
To: Jan Kara <jack@...e.cz>
Cc: linux-mm@...ck.org, Andrew Morton <akpm@...ux-foundation.org>,
Hugh Dickins <hughd@...gle.com>,
William Kucharski <william.kucharski@...cle.com>,
Johannes Weiner <hannes@...xchg.org>,
Yang Shi <yang.shi@...ux.alibaba.com>,
Dave Chinner <dchinner@...hat.com>,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH v2 04/12] mm/filemap: Add mapping_seek_hole_data
On Tue, Sep 29, 2020 at 10:46:53AM +0200, Jan Kara wrote:
> On Mon 14-09-20 14:00:34, Matthew Wilcox (Oracle) wrote:
> > Rewrite shmem_seek_hole_data() and move it to filemap.c.
> >
> > + rcu_read_lock();
> > + while ((page = xas_find_get_entry(&xas, max, XA_PRESENT))) {
> > + loff_t pos = xas.xa_index * PAGE_SIZE;
>
> OK, but for ordinary filesystems this could be problematic because of
> exceptional entries?
For ordinary filesystems, I have this queued up on top:
http://git.infradead.org/users/willy/pagecache.git/commitdiff/02c740b215bab901f95a560759b3bd906648da08
which handles exceptional entries. It treats shadow/swap/DAX entries
the same -- there's definitely data there, it's just not in a struct
page right now.
> Also for shmem you've dropped the PageUptodate check which I'm not sure is
> safe?
That was unintentional. I did run xfstests against this patch (just did
it again ... it passes), so I suspect it doesn't create a !Uptodate page.
I'll see if I can enhance the existing xfstests to catch this case.
The patch I link to above also doesn't handle !Uptodate pages on shmem
filesystems the same way that the current code does. So ... on top of
this patch, I propose doing this:
@@ -2416,6 +2416,14 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_ite
r *iter)
}
EXPORT_SYMBOL(generic_file_read_iter);
+static inline loff_t page_seek_hole_data(struct page *page,
+ loff_t start, loff_t end, bool seek_data)
+{
+ if (xa_is_value(page) || PageUptodate(page))
+ return seek_data ? start : end;
+ return seek_data ? end : start;
+}
+
static inline
unsigned int seek_page_size(struct xa_state *xas, struct page *page)
{
@@ -2463,10 +2471,10 @@ loff_t mapping_seek_hole_data(struct address_space *mapping, loff_t start,
start = pos;
}
- if (seek_data)
+ pos += seek_page_size(&xas, page);
+ start = page_seek_hole_data(page, start, pos, seek_data);
+ if (start < pos)
goto unlock;
-
- start = pos + seek_page_size(&xas, page);
}
rcu_read_unlock();
... and then rebasing the other patch on top of this works out nicely.
Here's the result:
http://git.infradead.org/users/willy/pagecache.git/commitdiff/9eb3f496b7cdcdcae83026e861e148f46921c367
http://git.infradead.org/users/willy/pagecache.git/commitdiff/7d93274088f0872d849a906d783dc260bee106b9
Powered by blists - more mailing lists