NFS: Add basic functionality for tracking folios in struct nfs_page
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Thu, 19 Jan 2023 21:33:35 +0000 (16:33 -0500)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Tue, 14 Feb 2023 19:22:32 +0000 (14:22 -0500)
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/pagelist.c
include/linux/nfs_page.h

index 369e4553399a057b6d4d12963c838f300c41c8ff..315e58d737185d2b8cc1c6a2c73f32fe47e88fd6 100644 (file)
@@ -500,9 +500,10 @@ nfs_create_subreq(struct nfs_page *req,
 {
        struct nfs_page *last;
        struct nfs_page *ret;
+       struct page *page = nfs_page_to_page(req, pgbase);
 
-       ret = __nfs_create_request(req->wb_lock_context, req->wb_page,
-                       pgbase, offset, count);
+       ret = __nfs_create_request(req->wb_lock_context, page, pgbase, offset,
+                                  count);
        if (!IS_ERR(ret)) {
                /* find the last request */
                for (last = req->wb_head;
index ba7e2e4b092645762f56c16474fe1545337d6b1a..d2ddc9a594c591c1fc20a710fbecb02105bb3f69 100644 (file)
@@ -25,6 +25,7 @@
 enum {
        PG_BUSY = 0,            /* nfs_{un}lock_request */
        PG_MAPPED,              /* page private set for buffered io */
+       PG_FOLIO,               /* Tracking a folio (unset for O_DIRECT) */
        PG_CLEAN,               /* write succeeded */
        PG_COMMIT_TO_DS,        /* used by pnfs layouts */
        PG_INODE_REF,           /* extra ref held by inode when in writeback */
@@ -41,7 +42,10 @@ enum {
 struct nfs_inode;
 struct nfs_page {
        struct list_head        wb_list;        /* Defines state of page: */
-       struct page             *wb_page;       /* page to read in/write out */
+       union {
+               struct page     *wb_page;       /* page to read in/write out */
+               struct folio    *wb_folio;
+       };
        struct nfs_lock_context *wb_lock_context;       /* lock context info */
        pgoff_t                 wb_index;       /* Offset >> PAGE_SHIFT */
        unsigned int            wb_offset,      /* Offset & ~PAGE_MASK */
@@ -153,6 +157,38 @@ extern     int nfs_page_set_headlock(struct nfs_page *req);
 extern void nfs_page_clear_headlock(struct nfs_page *req);
 extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *);
 
+/**
+ * nfs_page_to_folio - Retrieve a struct folio for the request
+ * @req: pointer to a struct nfs_page
+ *
+ * If a folio was assigned to @req, then return it, otherwise return NULL.
+ */
+static inline struct folio *nfs_page_to_folio(const struct nfs_page *req)
+{
+       if (test_bit(PG_FOLIO, &req->wb_flags))
+               return req->wb_folio;
+       return NULL;
+}
+
+/**
+ * nfs_page_to_page - Retrieve a struct page for the request
+ * @req: pointer to a struct nfs_page
+ * @pgbase: folio byte offset
+ *
+ * Return the page containing the byte that is at offset @pgbase relative
+ * to the start of the folio.
+ * Note: The request starts at offset @req->wb_pgbase.
+ */
+static inline struct page *nfs_page_to_page(const struct nfs_page *req,
+                                           size_t pgbase)
+{
+       struct folio *folio = nfs_page_to_folio(req);
+
+       if (folio == NULL)
+               return req->wb_page;
+       return folio_page(folio, pgbase >> PAGE_SHIFT);
+}
+
 /*
  * Lock the page of an asynchronous request
  */