From: Shaun Tancheff Date: Tue, 8 Nov 2022 15:26:46 +0000 (-0600) Subject: LU-16121 llite: invalidate_folio and dirty_folio X-Git-Tag: 2.15.54~111 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=f1604e680ba2b919c0c52c76c75a7e0dc27ec3c5 LU-16121 llite: invalidate_folio and dirty_folio linux commit v5.17-rc4-10-g128d1f8241d6 fs: Add invalidate_folio() aops method A struct folio is often analogous to a struct page however a struct folio can represent (contain) multiple pages. linux commit v5.17-rc4-38-g6f31a5a261db fs: Add aops->dirty_folio __set_page_dirty_nobuffers() is replaced with filemap_dirty_folio() Test-Parameters: trivial HPE-bug-id: LUS-11197 Signed-off-by: Shaun Tancheff Change-Id: Iefe67615b333e066c49c4b884dad5bea3b3ae226 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/48366 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin Reviewed-by: Jian Yu Reviewed-by: Petros Koutoupis --- diff --git a/lustre/autoconf/lustre-core.m4 b/lustre/autoconf/lustre-core.m4 index 8ccc779..1df9296 100644 --- a/lustre/autoconf/lustre-core.m4 +++ b/lustre/autoconf/lustre-core.m4 @@ -2804,6 +2804,55 @@ AC_DEFUN([LC_PROG_LINUX_SRC], []) AC_DEFUN([LC_PROG_LINUX_RESULTS], []) # +# LC_HAVE_INVALIDATE_FOLIO +# +# linux commit v5.17-rc4-10-g128d1f8241d6 +# fs: Add invalidate_folio() aops method +# +AC_DEFUN([LC_HAVE_INVALIDATE_FOLIO], [ +tmp_flags="$EXTRA_KCFLAGS" +EXTRA_KCFLAGS="-Werror" +LB_CHECK_COMPILE([if have address_spaace_operaions->invalidate_folio() member], +address_spaace_operaions_invalidate_folio, [ + #include + ],[ + struct address_space_operations *aops = NULL; + struct folio *folio = NULL; + aops->invalidate_folio(folio, 0, PAGE_SIZE); + ],[ + AC_DEFINE(HAVE_INVALIDATE_FOLIO, 1, + [address_spaace_operaions->invalidate_folio() member exists]) + ]) +EXTRA_KCFLAGS="$tmp_flags" +]) # LC_HAVE_INVALIDATE_FOLIO + +# +# LC_HAVE_DIRTY_FOLIO +# +# linux commit v5.17-rc4-38-g6f31a5a261db +# fs: Add aops->dirty_folio +# ... replaces ->set_page_dirty() with ->dirty_folio() +# +AC_DEFUN([LC_HAVE_DIRTY_FOLIO], [ +tmp_flags="$EXTRA_KCFLAGS" +EXTRA_KCFLAGS="-Werror" +LB_CHECK_COMPILE([if have address_spaace_operaions->dirty_folio() member], +address_spaace_operaions_dirty_folio, [ + #include + ],[ + struct address_space_operations *aops = NULL; + struct address_space *mapping = NULL; + struct folio *folio = NULL; + bool dirty = aops->dirty_folio(mapping, folio); + (void) dirty; + ],[ + AC_DEFINE(HAVE_DIRTY_FOLIO, 1, + [address_spaace_operaions->dirty_folio() member exists]) + ]) +EXTRA_KCFLAGS="$tmp_flags" +]) # LC_HAVE_DIRTY_FOLIO + +# # LC_PROG_LINUX # # Lustre linux kernel checks @@ -3012,6 +3061,10 @@ AC_DEFUN([LC_PROG_LINUX], [ LC_HAVE_SECURITY_DENTRY_INIT_WITH_XATTR_NAME_ARG LC_HAVE_KIOCB_COMPLETE_2ARGS + # 5.18 + LC_HAVE_INVALIDATE_FOLIO + LC_HAVE_DIRTY_FOLIO + # kernel patch to extend integrity interface LC_BIO_INTEGRITY_PREP_FN diff --git a/lustre/llite/rw26.c b/lustre/llite/rw26.c index a6e98a2..1c5a88a 100644 --- a/lustre/llite/rw26.c +++ b/lustre/llite/rw26.c @@ -50,6 +50,59 @@ #include "llite_internal.h" #include +#ifdef HAVE_INVALIDATE_FOLIO +/** + * Implements Linux VM address_space::invalidate_folio() method. This method is + * called when the folio is truncated from a file, either as a result of + * explicit truncate, or when inode is removed from memory (as a result of + * final iput(), umount, or memory pressure induced icache shrinking). + * + * [0, off] bytes of the folio remain valid (this is for a case of non-page + * aligned truncate). Lustre leaves partially truncated folios in the cache, + * relying on struct inode::i_size to limit further accesses. + */ +static void ll_invalidate_folio(struct folio *folio, size_t offset, size_t len) +{ + struct inode *inode; + struct lu_env *env; + struct cl_page *page; + struct cl_object *obj; + + LASSERT(!folio_test_writeback(folio)); + LASSERT(folio_test_locked(folio)); + + if (!(offset == 0 && len == folio_size(folio)) && + !folio_test_large(folio)) + return; + + /* Drop the pages from the folio */ + env = cl_env_percpu_get(); + LASSERT(!IS_ERR(env)); + + inode = folio_inode(folio); + obj = ll_i2info(inode)->lli_clob; + if (obj != NULL) { + int n, npgs = folio_nr_pages(folio); + + for (n = 0; n < npgs; n++) { + struct page *vmpage = folio_page(folio, n); + + LASSERT(PageLocked(vmpage)); + LASSERT(!PageWriteback(vmpage)); + + page = cl_vmpage_page(vmpage, obj); + if (page != NULL) { + cl_page_delete(env, page); + cl_page_put(env, page); + } + } + } else { + LASSERT(!folio_get_private(folio)); + } + cl_env_percpu_put(env); +} +#else + /** * Implements Linux VM address_space::invalidatepage() method. This method is * called when the page is truncate from a file, either as a result of @@ -68,13 +121,13 @@ static void ll_invalidatepage(struct page *vmpage, #endif ) { - struct inode *inode; - struct lu_env *env; - struct cl_page *page; - struct cl_object *obj; + struct inode *inode; + struct lu_env *env; + struct cl_page *page; + struct cl_object *obj; - LASSERT(PageLocked(vmpage)); - LASSERT(!PageWriteback(vmpage)); + LASSERT(PageLocked(vmpage)); + LASSERT(!PageWriteback(vmpage)); /* * It is safe to not check anything in invalidatepage/releasepage @@ -102,8 +155,9 @@ static void ll_invalidatepage(struct page *vmpage, LASSERT(vmpage->private == 0); cl_env_percpu_put(env); - } + } } +#endif #ifdef HAVE_RELEASEPAGE_WITH_INT #define RELEASEPAGE_ARG_TYPE int @@ -916,16 +970,24 @@ static int ll_migratepage(struct address_space *mapping, #endif const struct address_space_operations ll_aops = { - .readpage = ll_readpage, - .direct_IO = ll_direct_IO, - .writepage = ll_writepage, - .writepages = ll_writepages, - .set_page_dirty = __set_page_dirty_nobuffers, - .write_begin = ll_write_begin, - .write_end = ll_write_end, - .invalidatepage = ll_invalidatepage, - .releasepage = (void *)ll_releasepage, +#ifdef HAVE_DIRTY_FOLIO + .dirty_folio = filemap_dirty_folio, +#else + .set_page_dirty = __set_page_dirty_nobuffers, +#endif +#ifdef HAVE_INVALIDATE_FOLIO + .invalidate_folio = ll_invalidate_folio, +#else + .invalidatepage = ll_invalidatepage, +#endif + .readpage = ll_readpage, + .releasepage = (void *)ll_releasepage, + .direct_IO = ll_direct_IO, + .writepage = ll_writepage, + .writepages = ll_writepages, + .write_begin = ll_write_begin, + .write_end = ll_write_end, #ifdef CONFIG_MIGRATION - .migratepage = ll_migratepage, + .migratepage = ll_migratepage, #endif };