diff options
Diffstat (limited to 'include/linux/nfs_page.h')
-rw-r--r-- | include/linux/nfs_page.h | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index ba7e2e4b0926..a2f1ca657623 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -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 */ @@ -117,10 +121,15 @@ struct nfs_pageio_descriptor { #define NFS_WBACK_BUSY(req) (test_bit(PG_BUSY,&(req)->wb_flags)) -extern struct nfs_page *nfs_create_request(struct nfs_open_context *ctx, - struct page *page, - unsigned int offset, - unsigned int count); +extern struct nfs_page *nfs_page_create_from_page(struct nfs_open_context *ctx, + struct page *page, + unsigned int pgbase, + loff_t offset, + unsigned int count); +extern struct nfs_page *nfs_page_create_from_folio(struct nfs_open_context *ctx, + struct folio *folio, + unsigned int offset, + unsigned int count); extern void nfs_release_request(struct nfs_page *); @@ -153,6 +162,66 @@ 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); +} + +/** + * nfs_page_to_inode - Retrieve an inode for the request + * @req: pointer to a struct nfs_page + */ +static inline struct inode *nfs_page_to_inode(const struct nfs_page *req) +{ + struct folio *folio = nfs_page_to_folio(req); + + if (folio == NULL) + return page_file_mapping(req->wb_page)->host; + return folio_file_mapping(folio)->host; +} + +/** + * nfs_page_max_length - Retrieve the maximum possible length for a request + * @req: pointer to a struct nfs_page + * + * Returns the maximum possible length of a request + */ +static inline size_t nfs_page_max_length(const struct nfs_page *req) +{ + struct folio *folio = nfs_page_to_folio(req); + + if (folio == NULL) + return PAGE_SIZE; + return folio_size(folio); +} + /* * Lock the page of an asynchronous request */ |