blob: 0e9ebf9f7c23de69bad2cce11210a95893ed06e7 [file] [log] [blame]
From ed130be225046b3c469744265f8c3526deebbafd Mon Sep 17 00:00:00 2001
From: Dan Williams <>
Date: Mon, 21 Oct 2019 09:29:20 -0700
Subject: [PATCH] fs/dax: Fix pmd vs pte conflict detection
commit 6370740e5f8ef12de7f9a9bf48a0393d202cd827 upstream.
Users reported a v5.3 performance regression and inability to establish
huge page mappings. A revised version of the ndctl "" huge page
unit test identifies commit 23c84eb78375 "dax: Fix missed wakeup with
PMD faults" as the source.
Update get_unlocked_entry() to check for NULL entries before checking
the entry order, otherwise NULL is misinterpreted as a present pte
conflict. The 'order' check needs to happen before the locked check as
an unlocked entry at the wrong order must fallback to lookup the correct
Reported-by: Jeff Smits <>
Reported-by: Doug Nelson <>
Cc: <>
Fixes: 23c84eb78375 ("dax: Fix missed wakeup with PMD faults")
Reviewed-by: Jan Kara <>
Cc: Jeff Moyer <>
Cc: Matthew Wilcox (Oracle) <>
Reviewed-by: Johannes Thumshirn <>
Signed-off-by: Dan Williams <>
Signed-off-by: Paul Gortmaker <>
diff --git a/fs/dax.c b/fs/dax.c
index 4f42b852375b..36538f5ecc31 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -221,10 +221,11 @@ static void *get_unlocked_entry(struct xa_state *xas, unsigned int order)
for (;;) {
entry = xas_find_conflict(xas);
+ if (!entry || WARN_ON_ONCE(!xa_is_value(entry)))
+ return entry;
if (dax_entry_order(entry) < order)
- if (!entry || WARN_ON_ONCE(!xa_is_value(entry)) ||
- !dax_is_locked(entry))
+ if (!dax_is_locked(entry))
return entry;
wq = dax_entry_waitqueue(xas, entry, &ewait.key);