From 376e35fd59e56659560f6f2fb0e7f5cf5003f457 Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Mon, 13 Nov 2023 20:57:43 -0800 Subject: [PATCH] LU-16327 llite: read_folio, release_folio, filler_t Linux commit v5.18-rc5-221-gb7446e7cf15f fs: Remove aop flags parameter from grab_cache_page_write_begin() flags have been dropped from write_begin() and grab_cache_page_write_begin() Linux commit v5.18-rc5-241-g5efe7448a142 fs: Introduce aops->read_folio Provide a ll_read_folio handler around ll_readpage Linux commit v5.18-rc5-280-ge9b5b23e957e fs: Change the type of filler_t Affects read_cache_page, provides a wrapper for read_cache_page and wrappers for filler functions Linux commit v5.18-rc5-282-gfa29000b6b26 fs: Add aops->release_folio Provide an ll_release_folio function based on ll_releasepage Lustre-change: https://review.whamcloud.com/49199 Lustre-commit: 133ed0cf6f0c84d2b5b84e1de3ff2c54b1fb902d Test-Parameters: trivial HPE-bug-id: LUS-11357 Signed-off-by: Shaun Tancheff Change-Id: Ibd4ec1133c80cd0eb8400c4cd07b50e421dd35c5 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53125 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/autoconf/lustre-core.m4 | 111 +++++++++++++++++++++++++++++++++++++++++ lustre/include/lustre_compat.h | 15 ++++++ lustre/llite/file.c | 13 ++++- lustre/llite/llite_internal.h | 3 ++ lustre/llite/rw.c | 9 +++- lustre/llite/rw26.c | 57 ++++++++++++++++----- lustre/mdc/mdc_request.c | 20 ++++++-- 7 files changed, 207 insertions(+), 21 deletions(-) diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 03f2c79..102b79b 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -3110,6 +3110,105 @@ AC_DEFUN([LC_HAVE_ALLOC_INODE_SB], [ ]) # LC_HAVE_ALLOC_INODE_SB # +# LC_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS +# +# Linux commit v5.18-rc5-221-gb7446e7cf15f +# fs: Remove aop flags parameter from grab_cache_page_write_begin() +# +AC_DEFUN([LC_SRC_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS], [ + LB2_LINUX_TEST_SRC([grab_cache_page_write_begin_with_flags], [ + #include + ],[ + struct address_space *mapping = NULL; + (void)grab_cache_page_write_begin(mapping, 0, 1); + ],[-Werror]) +]) +AC_DEFUN([LC_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS], [ + AC_MSG_CHECKING([if grab_cache_page_write_begin() has flags argument]) + LB2_LINUX_TEST_RESULT([grab_cache_page_write_begin_with_flags], [ + AC_DEFINE(HAVE_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS, 1, + [grab_cache_page_write_begin() has flags argument]) + ]) +]) # LC_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS + +# +# LC_HAVE_ADDRESS_SPACE_OPERATIONS_READ_FOLIO +# +# Linux commit v5.18-rc5-241-g5efe7448a142 +# fs: Introduce aops->read_folio +# +AC_DEFUN([LC_SRC_HAVE_ADDRESS_SPACE_OPERATIONS_READ_FOLIO], [ + LB2_LINUX_TEST_SRC([address_space_operations_read_folio], [ + #include + ],[ + struct address_space_operations *aops = NULL; + struct file *file = NULL; + struct folio *folio = NULL; + int err = aops->read_folio(file, folio); + (void)err; + ],[-Werror]) +]) +AC_DEFUN([LC_HAVE_ADDRESS_SPACE_OPERATIONS_READ_FOLIO], [ + AC_MSG_CHECKING([if struct address_space_operations() has read_folio()]) + LB2_LINUX_TEST_RESULT([address_space_operations_read_folio], [ + AC_DEFINE(HAVE_AOPS_READ_FOLIO, 1, + [struct address_space_operations() has read_folio()]) + ]) +]) # LC_HAVE_ADDRESS_SPACE_OPERATIONS_READ_FOLIO + +# +# LC_HAVE_READ_CACHE_PAGE_FILLER_WITH_FILE +# +# Linux commit v5.18-rc5-280-ge9b5b23e957e +# fs: Change the type of filler_t +# +AC_DEFUN([LC_SRC_HAVE_READ_CACHE_PAGE_FILLER_WITH_FILE], [ + LB2_LINUX_TEST_SRC([read_cache_page_filler_with_file], [ + #include + static inline int _filler(struct file *file, struct folio *f) + { + return 0; + } + ],[ + struct address_space *mapping = NULL; + struct file *file = NULL; + struct page *page = read_cache_page(mapping, 0, _filler, file); + (void)page; + ],[-Werror]) +]) +AC_DEFUN([LC_HAVE_READ_CACHE_PAGE_FILLER_WITH_FILE], [ + AC_MSG_CHECKING([if read_cache_page() filler_t needs struct file]) + LB2_LINUX_TEST_RESULT([read_cache_page_filler_with_file], [ + AC_DEFINE(HAVE_READ_CACHE_PAGE_WANTS_FILE, 1, + [read_cache_page() filler_t needs struct file]) + ]) +]) # LC_HAVE_READ_CACHE_PAGE_FILLER_WITH_FILE + +# +# LC_HAVE_ADDRESS_SPACE_OPERATIONS_RELEASE_FOLIO +# +# Linux commit v5.18-rc5-282-gfa29000b6b26 +# fs: Add aops->release_folio +# +AC_DEFUN([LC_SRC_HAVE_ADDRESS_SPACE_OPERATIONS_RELEASE_FOLIO], [ + LB2_LINUX_TEST_SRC([address_space_operations_release_folio], [ + #include + ],[ + struct address_space_operations *aops = NULL; + struct folio *folio = NULL; + int err = aops->release_folio(folio, GFP_KERNEL); + (void)err; + ],[-Werror]) +]) +AC_DEFUN([LC_HAVE_ADDRESS_SPACE_OPERATIONS_RELEASE_FOLIO], [ + AC_MSG_CHECKING([if struct address_space_operations() has release_folio()]) + LB2_LINUX_TEST_RESULT([address_space_operations_release_folio], [ + AC_DEFINE(HAVE_AOPS_RELEASE_FOLIO, 1, + [struct address_space_operations() has release_folio()]) + ]) +]) # LC_HAVE_ADDRESS_SPACE_OPERATIONS_RELEASE_FOLIO + +# # LC_PROG_LINUX # # Lustre linux kernel checks @@ -3318,6 +3417,12 @@ AC_DEFUN([LC_PROG_LINUX_SRC], [ # 5.18 LC_SRC_HAVE_ALLOC_INODE_SB + # 5.19 + LC_SRC_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS + LC_SRC_HAVE_ADDRESS_SPACE_OPERATIONS_READ_FOLIO + LC_SRC_HAVE_READ_CACHE_PAGE_FILLER_WITH_FILE + LC_SRC_HAVE_ADDRESS_SPACE_OPERATIONS_RELEASE_FOLIO + # kernel patch to extend integrity interface LC_SRC_BIO_INTEGRITY_PREP_FN ]) @@ -3538,6 +3643,12 @@ AC_DEFUN([LC_PROG_LINUX_RESULTS], [ # 5.18 LC_HAVE_ALLOC_INODE_SB + # 5.19 + LC_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS + LC_HAVE_ADDRESS_SPACE_OPERATIONS_READ_FOLIO + LC_HAVE_READ_CACHE_PAGE_FILLER_WITH_FILE + LC_HAVE_ADDRESS_SPACE_OPERATIONS_RELEASE_FOLIO + # kernel patch to extend integrity interface LC_BIO_INTEGRITY_PREP_FN ]) diff --git a/lustre/include/lustre_compat.h b/lustre/include/lustre_compat.h index 4a9aa4b..bd5e976 100644 --- a/lustre/include/lustre_compat.h +++ b/lustre/include/lustre_compat.h @@ -590,4 +590,19 @@ static inline void cfs_delete_from_page_cache(struct page *page) } #endif +static inline struct page *ll_read_cache_page(struct address_space *mapping, + pgoff_t index, filler_t *filler, + void *data) +{ +#ifdef HAVE_READ_CACHE_PAGE_WANTS_FILE + struct file dummy_file; + + dummy_file.f_ra.ra_pages = 32; /* unused, modified on ra error */ + dummy_file.private_data = data; + return read_cache_page(mapping, index, filler, &dummy_file); +#else + return read_cache_page(mapping, index, filler, data); +#endif /* HAVE_READ_CACHE_PAGE_WANTS_FILE */ +} + #endif /* _LUSTRE_COMPAT_H */ diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 71f11a9..8852efc 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -492,6 +492,15 @@ static inline int ll_dom_readpage(void *data, struct page *page) return rc; } +#ifdef HAVE_READ_CACHE_PAGE_WANTS_FILE +static inline int ll_dom_read_folio(struct file *file, struct folio *folio0) +{ + return ll_dom_readpage(file->private_data, folio_page(folio0, 0)); +} +#else +#define ll_dom_read_folio ll_dom_readpage +#endif + void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req) { struct lu_env *env; @@ -569,8 +578,8 @@ void ll_dom_finish_open(struct inode *inode, struct ptlrpc_request *req) if (lnb.lnb_len > PAGE_SIZE) lnb.lnb_len = PAGE_SIZE; - vmpage = read_cache_page(mapping, index + start, - ll_dom_readpage, &lnb); + vmpage = ll_read_cache_page(mapping, index + start, + ll_dom_read_folio, &lnb); if (IS_ERR(vmpage)) { CWARN("%s: cannot fill page %lu for "DFID " with data: rc = %li\n", diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index a5cb82d..9c75c18 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -1123,6 +1123,9 @@ void ll_update_times(struct ptlrpc_request *request, struct inode *inode); int ll_writepage(struct page *page, struct writeback_control *wbc); int ll_writepages(struct address_space *, struct writeback_control *wbc); int ll_readpage(struct file *file, struct page *page); +#ifdef HAVE_AOPS_READ_FOLIO +int ll_read_folio(struct file *file, struct folio *folio); +#endif int ll_io_read_page(const struct lu_env *env, struct cl_io *io, struct cl_page *page, struct file *file); void ll_readahead_init(struct inode *inode, struct ll_readahead_state *ras); diff --git a/lustre/llite/rw.c b/lustre/llite/rw.c index 4e30df5..abb105e 100644 --- a/lustre/llite/rw.c +++ b/lustre/llite/rw.c @@ -1986,7 +1986,7 @@ int ll_readpage(struct file *file, struct page *vmpage) } else { unlock_page(vmpage); result = PTR_ERR(page); - } + } out: if (ra.cra_release != NULL) @@ -2002,3 +2002,10 @@ out: RETURN(result); } + +#ifdef HAVE_AOPS_READ_FOLIO +int ll_read_folio(struct file *file, struct folio *folio) +{ + return ll_readpage(file, folio_page(folio, 0)); +} +#endif diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c index 608d277..062fade 100644 --- a/lustre/llite/rw26.c +++ b/lustre/llite/rw26.c @@ -159,17 +159,12 @@ static void ll_invalidatepage(struct page *vmpage, } #endif -#ifdef HAVE_RELEASEPAGE_WITH_INT -#define RELEASEPAGE_ARG_TYPE int -#else -#define RELEASEPAGE_ARG_TYPE gfp_t -#endif -static int ll_releasepage(struct page *vmpage, RELEASEPAGE_ARG_TYPE gfp_mask) +static bool do_release_page(struct page *vmpage, gfp_t wait) { - struct lu_env *env; - struct cl_object *obj; - struct cl_page *page; - struct address_space *mapping; + struct lu_env *env; + struct cl_object *obj; + struct cl_page *page; + struct address_space *mapping; int result = 0; ENTRY; @@ -218,6 +213,28 @@ static int ll_releasepage(struct page *vmpage, RELEASEPAGE_ARG_TYPE gfp_mask) RETURN(result); } +#ifdef HAVE_AOPS_RELEASE_FOLIO +static bool ll_release_folio(struct folio *folio, gfp_t wait) +{ + struct page *vmpage = folio_page(folio, 0); + + /* folio_nr_pages(folio) == 1 is fixed with grab_cache_page* */ + BUG_ON(folio_nr_pages(folio) != 1); + + return do_release_page(vmpage, wait); +} +#else /* !HAVE_AOPS_RELEASE_FOLIO */ +#ifdef HAVE_RELEASEPAGE_WITH_INT +#define RELEASEPAGE_ARG_TYPE int +#else +#define RELEASEPAGE_ARG_TYPE gfp_t +#endif +static int ll_releasepage(struct page *vmpage, RELEASEPAGE_ARG_TYPE gfp_mask) +{ + return do_release_page(vmpage, gfp_mask); +} +#endif /* HAVE_AOPS_RELEASE_FOLIO */ + static ssize_t ll_get_user_pages(int rw, struct iov_iter *iter, struct page ***pages, ssize_t *npages, size_t maxsize) @@ -696,7 +713,10 @@ static int ll_tiny_write_begin(struct page *vmpage, struct address_space *mappin } static int ll_write_begin(struct file *file, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, + loff_t pos, unsigned int len, +#ifdef HAVE_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS + unsigned int flags, +#endif struct page **pagep, void **fsdata) { struct ll_cl_context *lcc = NULL; @@ -769,8 +789,11 @@ again: GOTO(out, result); if (vmpage == NULL) { - vmpage = grab_cache_page_write_begin(mapping, index, - flags); + vmpage = grab_cache_page_write_begin(mapping, index +#ifdef HAVE_GRAB_CACHE_PAGE_WRITE_BEGIN_WITH_FLAGS + , flags +#endif + ); if (vmpage == NULL) GOTO(out, result = -ENOMEM); } @@ -976,8 +999,16 @@ const struct address_space_operations ll_aops = { #else .invalidatepage = ll_invalidatepage, #endif +#ifdef HAVE_AOPS_READ_FOLIO + .read_folio = ll_read_folio, +#else .readpage = ll_readpage, +#endif +#ifdef HAVE_AOPS_RELEASE_FOLIO + .release_folio = ll_release_folio, +#else .releasepage = (void *)ll_releasepage, +#endif .direct_IO = ll_direct_IO, .writepage = ll_writepage, .writepages = ll_writepages, diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index 47f6b3c..662a87c 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -1330,7 +1330,7 @@ struct readpage_param { * in PAGE_SIZE (if PAGE_SIZE greater than LU_PAGE_SIZE), and the * lu_dirpage for this integrated page will be adjusted. **/ -static int mdc_read_page_remote(void *data, struct page *page0) +static int ll_mdc_read_page_remote(void *data, struct page *page0) { struct readpage_param *rp = data; struct page **page_pool; @@ -1426,6 +1426,16 @@ static int mdc_read_page_remote(void *data, struct page *page0) RETURN(rc); } +#ifdef HAVE_READ_CACHE_PAGE_WANTS_FILE +static inline int mdc_read_folio_remote(struct file *file, struct folio *folio) +{ + return ll_mdc_read_page_remote(file->private_data, + folio_page(folio, 0)); +} +#else +#define mdc_read_folio_remote ll_mdc_read_page_remote +#endif + /** * Read dir page from cache first, if it can not find it, read it from * server and add into the cache. @@ -1508,10 +1518,10 @@ static int mdc_read_page(struct obd_export *exp, struct md_op_data *op_data, rp_param.rp_exp = exp; rp_param.rp_mod = op_data; - page = read_cache_page(mapping, - hash_x_index(rp_param.rp_off, - rp_param.rp_hash64), - mdc_read_page_remote, &rp_param); + page = ll_read_cache_page(mapping, + hash_x_index(rp_param.rp_off, + rp_param.rp_hash64), + mdc_read_folio_remote, &rp_param); if (IS_ERR(page)) { CDEBUG(D_INFO, "%s: read cache page: "DFID" at %llu: %ld\n", exp->exp_obd->obd_name, PFID(&op_data->op_fid1), -- 1.8.3.1