From: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> While the NFS readahead code has no problems using the generic code to manage the dropbehind behaviour enabled by RWF_DONTCACHE, the write code needs to deal with the fact that NFS writeback uses a 2 step process (UNSTABLE write followed by COMMIT). This commit replaces the use of the folio dropbehind flag with a local NFS request flag that triggers the dropbehind behaviour once the data has been written to stable storage. Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> Link: https://lore.kernel.org/all/ec165b304a7b56d1fa4c6c2b1ad1c04d4dcbd3f6.1745381692.git.trond.myklebust@xxxxxxxxxxxxxxx/ Reviewed-by: Mike Snitzer <snitzer@xxxxxxxxxx> --- fs/nfs/file.c | 6 ++---- fs/nfs/nfs4file.c | 1 + fs/nfs/write.c | 20 +++++++++++++++++--- include/linux/nfs_page.h | 1 + 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 86e36c630f09..f771bd92d61e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -348,7 +348,6 @@ static int nfs_write_begin(const struct kiocb *iocb, loff_t pos, unsigned len, struct folio **foliop, void **fsdata) { - fgf_t fgp = FGP_WRITEBEGIN; struct folio *folio; struct file *file = iocb->ki_filp; int once_thru = 0; @@ -357,10 +356,8 @@ static int nfs_write_begin(const struct kiocb *iocb, dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%lu), %u@%lld)\n", file, mapping->host->i_ino, len, (long long) pos); - fgp |= fgf_set_order(len); start: - folio = __filemap_get_folio(mapping, pos >> PAGE_SHIFT, fgp, - mapping_gfp_mask(mapping)); + folio = write_begin_get_folio(iocb, mapping, pos >> PAGE_SHIFT, len); if (IS_ERR(folio)) return PTR_ERR(folio); *foliop = folio; @@ -915,5 +912,6 @@ const struct file_operations nfs_file_operations = { .splice_write = iter_file_splice_write, .check_flags = nfs_check_flags, .setlease = simple_nosetlease, + .fop_flags = FOP_DONTCACHE, }; EXPORT_SYMBOL_GPL(nfs_file_operations); diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 1d6b5f4230c9..654fda6f362c 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -454,4 +454,5 @@ const struct file_operations nfs4_file_operations = { #else .llseek = nfs_file_llseek, #endif + .fop_flags = FOP_DONTCACHE, }; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 8b7c04737967..f0fd5162154f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -349,8 +349,12 @@ static void nfs_folio_end_writeback(struct folio *folio) static void nfs_page_end_writeback(struct nfs_page *req) { if (nfs_page_group_sync_on_bit(req, PG_WB_END)) { + struct folio *folio = nfs_page_to_folio(req); + + if (folio_test_clear_dropbehind(folio)) + set_bit(PG_DROPBEHIND, &req->wb_head->wb_flags); nfs_unlock_request(req); - nfs_folio_end_writeback(nfs_page_to_folio(req)); + nfs_folio_end_writeback(folio); } else nfs_unlock_request(req); } @@ -787,8 +791,15 @@ static void nfs_inode_remove_request(struct nfs_page *req) clear_bit(PG_MAPPED, &req->wb_head->wb_flags); } spin_unlock(&mapping->i_private_lock); - } - nfs_page_group_unlock(req); + nfs_page_group_unlock(req); + + if (test_and_clear_bit(PG_DROPBEHIND, + &req->wb_head->wb_flags)) { + folio_set_dropbehind(folio); + folio_end_dropbehind(folio); + } + } else + nfs_page_group_unlock(req); if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { atomic_long_dec(&nfsi->nrequests); @@ -2068,6 +2079,7 @@ int nfs_wb_folio(struct inode *inode, struct folio *folio) .range_start = range_start, .range_end = range_start + len - 1, }; + bool dropbehind = folio_test_clear_dropbehind(folio); int ret; trace_nfs_writeback_folio(inode, range_start, len); @@ -2088,6 +2100,8 @@ int nfs_wb_folio(struct inode *inode, struct folio *folio) goto out_error; } out_error: + if (dropbehind) + folio_set_dropbehind(folio); trace_nfs_writeback_folio_done(inode, range_start, len, ret); return ret; } diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 9aed39abc94b..32ab7a590098 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -37,6 +37,7 @@ enum { PG_REMOVE, /* page group sync bit in write path */ PG_CONTENDED1, /* Is someone waiting for a lock? */ PG_CONTENDED2, /* Is someone waiting for a lock? */ + PG_DROPBEHIND, /* Implement RWF_DONTCACHE */ }; struct nfs_inode; -- 2.50.1