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> --- fs/nfs/file.c | 2 ++ fs/nfs/nfs4file.c | 2 ++ fs/nfs/write.c | 12 +++++++++++- include/linux/nfs_page.h | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 033feeab8c34..60d47f141acb 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -910,5 +910,7 @@ 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 1cd9652f3c28..e6726499c585 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -467,4 +467,6 @@ 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 23df8b214474..e0ac439ab211 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -359,8 +359,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_flags); nfs_unlock_request(req); - nfs_folio_end_writeback(nfs_page_to_folio(req)); + nfs_folio_end_writeback(folio); } else nfs_unlock_request(req); } @@ -813,6 +817,9 @@ 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); + + if (test_bit(PG_DROPBEHIND, &req->wb_flags)) + folio_end_dropbehind(folio); } if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { @@ -2093,6 +2100,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); @@ -2113,6 +2121,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 169b4ae30ff4..1a017b5b476f 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.49.0