[PATCH v10 5/9] fsdax: Introduce dax_load_page()

From: Shiyang Ruan
Date: Thu Jan 27 2022 - 07:41:23 EST


The current dax_lock_page() locks dax entry by obtaining mapping and
index in page. To support 1-to-N RMAP in NVDIMM, we need a new function
to lock a specific dax entry corresponding to this file's mapping,index.
And output the page corresponding to the specific dax entry for caller
use.

Signed-off-by: Shiyang Ruan <ruansy.fnst@xxxxxxxxxxx>
Reviewed-by: Christoph Hellwig <hch@xxxxxx>
---
fs/dax.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/dax.h | 8 ++++++++
2 files changed, 52 insertions(+)

diff --git a/fs/dax.c b/fs/dax.c
index c8d57080c1aa..964512107c23 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -455,6 +455,50 @@ void dax_unlock_page(struct page *page, dax_entry_t cookie)
dax_unlock_entry(&xas, (void *)cookie);
}

+/*
+ * dax_load_page - Load the page corresponding to a (mapping,offset)
+ * @mapping: the file's mapping whose entry we want to load
+ * @index: the offset within this file
+ * @page: output the dax page corresponding to this dax entry
+ *
+ * Return: error if it isn't a dax mapping, otherwise 0.
+ */
+int dax_load_page(struct address_space *mapping, pgoff_t index,
+ struct page **page)
+{
+ XA_STATE(xas, &mapping->i_pages, 0);
+ void *entry;
+
+ if (!dax_mapping(mapping))
+ return -EBUSY;
+
+ rcu_read_lock();
+ for (;;) {
+ entry = NULL;
+ xas_lock_irq(&xas);
+ xas_set(&xas, index);
+ entry = xas_load(&xas);
+ if (dax_is_locked(entry)) {
+ rcu_read_unlock();
+ wait_entry_unlocked(&xas, entry);
+ rcu_read_lock();
+ continue;
+ }
+ if (entry &&
+ !dax_is_zero_entry(entry) && !dax_is_empty_entry(entry)) {
+ /*
+ * Output the page if the dax entry exists and isn't
+ * a zero or empty entry.
+ */
+ *page = pfn_to_page(dax_to_pfn(entry));
+ }
+ xas_unlock_irq(&xas);
+ break;
+ }
+ rcu_read_unlock();
+ return 0;
+}
+
/*
* Find page cache entry at given index. If it is a DAX entry, return it
* with the entry locked. If the page cache doesn't contain an entry at
diff --git a/include/linux/dax.h b/include/linux/dax.h
index 96cfc63b12fd..530ff9733dd9 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -155,6 +155,8 @@ struct page *dax_layout_busy_page(struct address_space *mapping);
struct page *dax_layout_busy_page_range(struct address_space *mapping, loff_t start, loff_t end);
dax_entry_t dax_lock_page(struct page *page);
void dax_unlock_page(struct page *page, dax_entry_t cookie);
+int dax_load_page(struct address_space *mapping,
+ unsigned long index, struct page **page);
#else
static inline struct page *dax_layout_busy_page(struct address_space *mapping)
{
@@ -182,6 +184,12 @@ static inline dax_entry_t dax_lock_page(struct page *page)
static inline void dax_unlock_page(struct page *page, dax_entry_t cookie)
{
}
+
+static inline int dax_load_page(struct address_space *mapping,
+ unsigned long index, struct page **page)
+{
+ return 0;
+}
#endif

int dax_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
--
2.34.1