Skip to content

Commit 393f42f

Browse files
committed
Merge tag 'dax-fixes-5.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull dax fixes from Dan Williams: "A fix for a hang condition due to missed wakeups in the filesystem-dax core when exercised by virtiofs. This bug has been there from the beginning, but the condition has not triggered on other filesystems since they hold a lock over invalidation events" * tag 'dax-fixes-5.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: dax: Wake up all waiters after invalidating dax entry dax: Add a wakeup mode parameter to put_unlocked_entry() dax: Add an enum for specifying dax wakup mode
2 parents 33f85ca + 2373883 commit 393f42f

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

fs/dax.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ struct wait_exceptional_entry_queue {
144144
struct exceptional_entry_key key;
145145
};
146146

147+
/**
148+
* enum dax_wake_mode: waitqueue wakeup behaviour
149+
* @WAKE_ALL: wake all waiters in the waitqueue
150+
* @WAKE_NEXT: wake only the first waiter in the waitqueue
151+
*/
152+
enum dax_wake_mode {
153+
WAKE_ALL,
154+
WAKE_NEXT,
155+
};
156+
147157
static wait_queue_head_t *dax_entry_waitqueue(struct xa_state *xas,
148158
void *entry, struct exceptional_entry_key *key)
149159
{
@@ -182,7 +192,8 @@ static int wake_exceptional_entry_func(wait_queue_entry_t *wait,
182192
* The important information it's conveying is whether the entry at
183193
* this index used to be a PMD entry.
184194
*/
185-
static void dax_wake_entry(struct xa_state *xas, void *entry, bool wake_all)
195+
static void dax_wake_entry(struct xa_state *xas, void *entry,
196+
enum dax_wake_mode mode)
186197
{
187198
struct exceptional_entry_key key;
188199
wait_queue_head_t *wq;
@@ -196,7 +207,7 @@ static void dax_wake_entry(struct xa_state *xas, void *entry, bool wake_all)
196207
* must be in the waitqueue and the following check will see them.
197208
*/
198209
if (waitqueue_active(wq))
199-
__wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key);
210+
__wake_up(wq, TASK_NORMAL, mode == WAKE_ALL ? 0 : 1, &key);
200211
}
201212

202213
/*
@@ -264,11 +275,11 @@ static void wait_entry_unlocked(struct xa_state *xas, void *entry)
264275
finish_wait(wq, &ewait.wait);
265276
}
266277

267-
static void put_unlocked_entry(struct xa_state *xas, void *entry)
278+
static void put_unlocked_entry(struct xa_state *xas, void *entry,
279+
enum dax_wake_mode mode)
268280
{
269-
/* If we were the only waiter woken, wake the next one */
270281
if (entry && !dax_is_conflict(entry))
271-
dax_wake_entry(xas, entry, false);
282+
dax_wake_entry(xas, entry, mode);
272283
}
273284

274285
/*
@@ -286,7 +297,7 @@ static void dax_unlock_entry(struct xa_state *xas, void *entry)
286297
old = xas_store(xas, entry);
287298
xas_unlock_irq(xas);
288299
BUG_ON(!dax_is_locked(old));
289-
dax_wake_entry(xas, entry, false);
300+
dax_wake_entry(xas, entry, WAKE_NEXT);
290301
}
291302

292303
/*
@@ -524,7 +535,7 @@ static void *grab_mapping_entry(struct xa_state *xas,
524535

525536
dax_disassociate_entry(entry, mapping, false);
526537
xas_store(xas, NULL); /* undo the PMD join */
527-
dax_wake_entry(xas, entry, true);
538+
dax_wake_entry(xas, entry, WAKE_ALL);
528539
mapping->nrpages -= PG_PMD_NR;
529540
entry = NULL;
530541
xas_set(xas, index);
@@ -622,7 +633,7 @@ struct page *dax_layout_busy_page_range(struct address_space *mapping,
622633
entry = get_unlocked_entry(&xas, 0);
623634
if (entry)
624635
page = dax_busy_page(entry);
625-
put_unlocked_entry(&xas, entry);
636+
put_unlocked_entry(&xas, entry, WAKE_NEXT);
626637
if (page)
627638
break;
628639
if (++scanned % XA_CHECK_SCHED)
@@ -664,7 +675,7 @@ static int __dax_invalidate_entry(struct address_space *mapping,
664675
mapping->nrpages -= 1UL << dax_entry_order(entry);
665676
ret = 1;
666677
out:
667-
put_unlocked_entry(&xas, entry);
678+
put_unlocked_entry(&xas, entry, WAKE_ALL);
668679
xas_unlock_irq(&xas);
669680
return ret;
670681
}
@@ -937,13 +948,13 @@ static int dax_writeback_one(struct xa_state *xas, struct dax_device *dax_dev,
937948
xas_lock_irq(xas);
938949
xas_store(xas, entry);
939950
xas_clear_mark(xas, PAGECACHE_TAG_DIRTY);
940-
dax_wake_entry(xas, entry, false);
951+
dax_wake_entry(xas, entry, WAKE_NEXT);
941952

942953
trace_dax_writeback_one(mapping->host, index, count);
943954
return ret;
944955

945956
put_unlocked:
946-
put_unlocked_entry(xas, entry);
957+
put_unlocked_entry(xas, entry, WAKE_NEXT);
947958
return ret;
948959
}
949960

@@ -1684,7 +1695,7 @@ dax_insert_pfn_mkwrite(struct vm_fault *vmf, pfn_t pfn, unsigned int order)
16841695
/* Did we race with someone splitting entry or so? */
16851696
if (!entry || dax_is_conflict(entry) ||
16861697
(order == 0 && !dax_is_pte_entry(entry))) {
1687-
put_unlocked_entry(&xas, entry);
1698+
put_unlocked_entry(&xas, entry, WAKE_NEXT);
16881699
xas_unlock_irq(&xas);
16891700
trace_dax_insert_pfn_mkwrite_no_entry(mapping->host, vmf,
16901701
VM_FAULT_NOPAGE);

0 commit comments

Comments
 (0)