From: James Simmons <jsimmons@infradead.org>
To: Eric Biggers <ebiggers@google.com>,
Andreas Dilger <adilger@whamcloud.com>, NeilBrown <neilb@suse.de>
Cc: linux-fscrypt@vger.kernel.org,
Patrick Farrell <pfarrell@whamcloud.com>,
James Simmons <jsimmons@infradead.org>
Subject: [PATCH 02/18] lustre: llite: Check vmpage in releasepage
Date: Thu, 9 Jun 2022 08:32:58 -0400 [thread overview]
Message-ID: <1654777994-29806-3-git-send-email-jsimmons@infradead.org> (raw)
In-Reply-To: <1654777994-29806-1-git-send-email-jsimmons@infradead.org>
From: Patrick Farrell <pfarrell@whamcloud.com>
We cannot release a page if the vmpage reference count is
>1, otherwise we will detach a vmpage from Lustre when the
page is still referenced in the VM.
This creates a situation where page discard for lock
cancellation will not find the page, so we can get stale
data reads.
This re-introduces the LU-12587 issue where direct I/O on
a client falls back to buffered I/O if there are pages in
cache, since it cannot flush them. This is annoying but
not a huge problem.
WC-bug-id: https://jira.whamcloud.com/browse/LU-14541
Lustre-commit: c524079f4f59a39b9 ("LU-14541 llite: Check vmpage in releasepage")
Signed-off-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/47262
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
Signed-off-by: James Simmons <jsimmons@infradead.org>
---
fs/lustre/include/cl_object.h | 9 +++++++++
fs/lustre/llite/rw26.c | 19 +++++++++++++------
fs/lustre/osc/osc_page.c | 9 +++++++--
3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/fs/lustre/include/cl_object.h b/fs/lustre/include/cl_object.h
index ab7f0f2..b98109d 100644
--- a/fs/lustre/include/cl_object.h
+++ b/fs/lustre/include/cl_object.h
@@ -91,6 +91,7 @@
#include <linux/uio.h>
#include <lu_object.h>
#include <linux/atomic.h>
+#include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/radix-tree.h>
#include <linux/spinlock.h>
@@ -1071,6 +1072,14 @@ static inline bool __page_in_use(const struct cl_page *page, int refc)
*/
#define cl_page_in_use_noref(pg) __page_in_use(pg, 0)
+/* references: cl_page, page cache, optional + refcount for caller reference
+ * (always 0 or 1 currently)
+ */
+static inline int vmpage_in_use(struct page *vmpage, int refcount)
+{
+ return (page_count(vmpage) - page_mapcount(vmpage) > 2 + refcount);
+}
+
/** @} cl_page */
/** \addtogroup cl_lock cl_lock
diff --git a/fs/lustre/llite/rw26.c b/fs/lustre/llite/rw26.c
index a5cdb01..8b379ca 100644
--- a/fs/lustre/llite/rw26.c
+++ b/fs/lustre/llite/rw26.c
@@ -102,7 +102,7 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask)
{
struct lu_env *env;
struct cl_object *obj;
- struct cl_page *page;
+ struct cl_page *clpage;
struct address_space *mapping;
int result = 0;
@@ -118,16 +118,23 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask)
if (!obj)
return 1;
- page = cl_vmpage_page(vmpage, obj);
- if (!page)
+ clpage = cl_vmpage_page(vmpage, obj);
+ if (!clpage)
return 1;
env = cl_env_percpu_get();
LASSERT(!IS_ERR(env));
- if (!cl_page_in_use(page)) {
+ /* we must not delete the cl_page if the vmpage is in use, otherwise we
+ * disconnect the vmpage from Lustre while it's still alive(!), which
+ * means we won't find it to discard on lock cancellation.
+ *
+ * References here are: caller + cl_page + page cache.
+ * Any other references are potentially transient and must be ignored.
+ */
+ if (!cl_page_in_use(clpage) && !vmpage_in_use(vmpage, 1)) {
result = 1;
- cl_page_delete(env, page);
+ cl_page_delete(env, clpage);
}
/* To use percpu env array, the call path can not be rescheduled;
@@ -144,7 +151,7 @@ static int ll_releasepage(struct page *vmpage, gfp_t gfp_mask)
* that we won't get into object delete path.
*/
LASSERT(cl_object_refc(obj) > 1);
- cl_page_put(env, page);
+ cl_page_put(env, clpage);
cl_env_percpu_put(env);
return result;
diff --git a/fs/lustre/osc/osc_page.c b/fs/lustre/osc/osc_page.c
index f46b4e7..b56bc1a 100644
--- a/fs/lustre/osc/osc_page.c
+++ b/fs/lustre/osc/osc_page.c
@@ -539,8 +539,13 @@ static inline bool lru_page_busy(struct client_obd *cli, struct cl_page *page)
if (cli->cl_cache->ccc_unstable_check) {
struct page *vmpage = cl_page_vmpage(page);
- /* vmpage have two known users: cl_page and VM page cache */
- if (page_count(vmpage) - page_mapcount(vmpage) > 2)
+ /* this check is racy because the vmpage is not locked, but
+ * that's OK - the code which does the actual page release
+ * checks this again before releasing
+ *
+ * vmpage have two known users: cl_page and VM page cache
+ */
+ if (vmpage_in_use(vmpage, 0))
return true;
}
return false;
--
1.8.3.1
next prev parent reply other threads:[~2022-06-09 12:33 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-09 12:32 [PATCH 00/18] lustre: sync with OpenSFS tree June 8, 2022 James Simmons
2022-06-09 12:32 ` [PATCH 01/18] lustre: llite: reenable fast_read by default James Simmons
2022-06-09 12:32 ` James Simmons [this message]
2022-06-09 12:32 ` [PATCH 03/18] lustre: update version to 2.15.50 James Simmons
2022-06-09 12:33 ` [PATCH 04/18] lustre: llog: read canceled records in llog_backup James Simmons
2022-06-09 12:33 ` [PATCH 05/18] lnet: change LNetPrimaryNID to use struct lnet_nid James Simmons
2022-06-09 12:33 ` [PATCH 06/18] lnet: alter lnet_drop_rule_match() to take lnet_nid James Simmons
2022-06-09 12:33 ` [PATCH 07/18] lnet: Change LNetDist to work with struct lnet_nid James Simmons
2022-06-09 12:33 ` [PATCH 08/18] lnet: convert LNetPut to take 16byte nid and pid James Simmons
2022-06-09 12:33 ` [PATCH 09/18] lnet: change LNetGet " James Simmons
2022-06-09 12:33 ` [PATCH 10/18] lnet: socklnd: pass large processid to ksocknal_add_peer James Simmons
2022-06-09 12:33 ` [PATCH 11/18] lnet: socklnd: large processid for ksocknal_get_peer_info James Simmons
2022-06-09 12:33 ` [PATCH 12/18] lnet: socklnd: switch ksocknal_del_peer to lnet_processid James Simmons
2022-06-09 12:33 ` [PATCH 13/18] lustre: llite: access lli_lsm_md with lock in all places James Simmons
2022-06-09 12:33 ` [PATCH 14/18] lustre: quota: fallocate does not increase projectid usage James Simmons
2022-06-09 12:33 ` [PATCH 15/18] lnet: selftest: improve lnet_selftest speed James Simmons
2022-06-09 12:33 ` [PATCH 16/18] lustre: mdc: Use early cancels for hsm requests James Simmons
2022-06-09 12:33 ` [PATCH 17/18] lustre: ptlrpc: send disconnected events James Simmons
2022-06-09 12:33 ` [PATCH 18/18] lnet: Avoid redundant peer NI lookups James Simmons
2022-06-10 0:09 ` [PATCH 00/18] lustre: sync with OpenSFS tree June 8, 2022 Eric Biggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1654777994-29806-3-git-send-email-jsimmons@infradead.org \
--to=jsimmons@infradead.org \
--cc=adilger@whamcloud.com \
--cc=ebiggers@google.com \
--cc=linux-fscrypt@vger.kernel.org \
--cc=neilb@suse.de \
--cc=pfarrell@whamcloud.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox