git: 70dc6b2ce314 - main - nfsclient: limit situations when we do unlocked read-ahead by nfsiod
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 05 Jan 2024 05:00:52 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=70dc6b2ce314a0f32755005ad02802fca7ed186e commit 70dc6b2ce314a0f32755005ad02802fca7ed186e Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2024-01-01 22:22:44 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> 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) &&