The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=70dc6b2ce314a0f32755005ad02802fca7ed186e

commit 70dc6b2ce314a0f32755005ad02802fca7ed186e
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2024-01-01 22:22:44 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2024-01-05 04:58:58 +0000

    nfsclient: limit situations when we do unlocked read-ahead by nfsiod
    
    If there were or are writeable mappings, read-ahead might overwrite the
    dirty pages data that is not yet reflected as a delayed write in the
    matching buffer state.
    
    Noted by:       rmacklem
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
---
 sys/fs/nfsclient/nfs_clbio.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index e6486af55daf..f6506e34ee59 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -481,9 +481,14 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, 
struct ucred *cred)
                on = uio->uio_offset - (lbn * biosize);
 
                /*
-                * Start the read ahead(s), as required.
+                * Start the read ahead(s), as required.  Do not do
+                * read-ahead if there are writeable mappings, since
+                * unlocked read by nfsiod could obliterate changes
+                * done by userspace.
                 */
-               if (nmp->nm_readahead > 0) {
+               if (nmp->nm_readahead > 0 &&
+                   !vm_object_mightbedirty(vp->v_object) &&
+                   vp->v_object->un_pager.vnp.writemappings == 0) {
                    for (nra = 0; nra < nmp->nm_readahead && nra < seqcount &&
                        (off_t)(lbn + 1 + nra) * biosize < nsize; nra++) {
                        rabn = lbn + 1 + nra;
@@ -671,6 +676,8 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, 
struct ucred *cred)
                 */
                NFSLOCKNODE(np);
                if (nmp->nm_readahead > 0 &&
+                   !vm_object_mightbedirty(vp->v_object) &&
+                   vp->v_object->un_pager.vnp.writemappings == 0 &&
                    (bp->b_flags & B_INVAL) == 0 &&
                    (np->n_direofoffset == 0 ||
                    (lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&

Reply via email to