Date: Sat, 29 Feb 2020 22:10:00 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r358476 - in stable/12/sys: fs/nfsclient sys Message-ID: <202002292210.01TMA02o073732@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Sat Feb 29 22:10:00 2020 New Revision: 358476 URL: https://svnweb.freebsd.org/changeset/base/358476 Log: MFC r358252: Fix NFS client deadlock when read reports truncated node. Modified: stable/12/sys/fs/nfsclient/nfs_clbio.c stable/12/sys/fs/nfsclient/nfs_clport.c stable/12/sys/sys/proc.h Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/fs/nfsclient/nfs_clbio.c ============================================================================== --- stable/12/sys/fs/nfsclient/nfs_clbio.c Sat Feb 29 21:55:48 2020 (r358475) +++ stable/12/sys/fs/nfsclient/nfs_clbio.c Sat Feb 29 22:10:00 2020 (r358476) @@ -425,14 +425,11 @@ int ncl_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) { struct nfsnode *np = VTONFS(vp); - int biosize, i; struct buf *bp, *rabp; struct thread *td; struct nfsmount *nmp = VFSTONFS(vp->v_mount); daddr_t lbn, rabn; - int bcount; - int seqcount; - int nra, error = 0, n = 0, on = 0; + int biosize, bcount, error, i, n, nra, on, save2, seqcount; off_t tmp_off; KASSERT(uio->uio_rw == UIO_READ, ("ncl_read mode")); @@ -464,6 +461,8 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof /* No caching/ no readaheads. Just read data into the user buffer */ return ncl_readrpc(vp, uio, cred); + n = 0; + on = 0; biosize = vp->v_bufobj.bo_bsize; seqcount = (int)((off_t)(ioflag >> IO_SEQSHIFT) * biosize / BKVASIZE); @@ -471,6 +470,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof if (error) return error; + save2 = curthread_pflags2_set(TDP2_SBPAGES); do { u_quad_t nsize; @@ -495,7 +495,9 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof rabp = nfs_getcacheblk(vp, rabn, biosize, td); if (!rabp) { error = newnfs_sigintr(nmp, td); - return (error ? error : EINTR); + if (error == 0) + error = EINTR; + goto out; } if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) { rabp->b_flags |= B_ASYNC; @@ -526,7 +528,9 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof if (!bp) { error = newnfs_sigintr(nmp, td); - return (error ? error : EINTR); + if (error == 0) + error = EINTR; + goto out; } /* @@ -540,7 +544,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof error = ncl_doio(vp, bp, cred, td, 0); if (error) { brelse(bp); - return (error); + goto out; } } @@ -561,7 +565,9 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, td); if (!bp) { error = newnfs_sigintr(nmp, td); - return (error ? error : EINTR); + if (error == 0) + error = EINTR; + goto out; } if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; @@ -570,7 +576,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof if (error) { bp->b_ioflags |= BIO_ERROR; brelse(bp); - return (error); + goto out; } } n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid); @@ -580,14 +586,17 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof NFSINCRGLOBAL(nfsstatsv1.biocache_readdirs); if (np->n_direofoffset && uio->uio_offset >= np->n_direofoffset) { - return (0); + error = 0; + goto out; } lbn = (uoff_t)uio->uio_offset / NFS_DIRBLKSIZ; on = uio->uio_offset & (NFS_DIRBLKSIZ - 1); bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, td); if (!bp) { - error = newnfs_sigintr(nmp, td); - return (error ? error : EINTR); + error = newnfs_sigintr(nmp, td); + if (error == 0) + error = EINTR; + goto out; } if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; @@ -612,12 +621,16 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof */ for (i = 0; i <= lbn && !error; i++) { if (np->n_direofoffset - && (i * NFS_DIRBLKSIZ) >= np->n_direofoffset) - return (0); + && (i * NFS_DIRBLKSIZ) >= np->n_direofoffset) { + error = 0; + goto out; + } bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, td); if (!bp) { error = newnfs_sigintr(nmp, td); - return (error ? error : EINTR); + if (error == 0) + error = EINTR; + goto out; } if ((bp->b_flags & B_CACHE) == 0) { bp->b_iocmd = BIO_READ; @@ -646,7 +659,7 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof * we give up. */ if (error) - return (error); + goto out; } /* @@ -706,6 +719,12 @@ ncl_bioread(struct vnode *vp, struct uio *uio, int iof if (bp != NULL) brelse(bp); } while (error == 0 && uio->uio_resid > 0 && n > 0); +out: + curthread_pflags2_restore(save2); + if ((curthread->td_pflags2 & TDP2_SBPAGES) == 0) { + NFSLOCKNODE(np); + ncl_pager_setsize(vp, NULL); + } return (error); } Modified: stable/12/sys/fs/nfsclient/nfs_clport.c ============================================================================== --- stable/12/sys/fs/nfsclient/nfs_clport.c Sat Feb 29 21:55:48 2020 (r358475) +++ stable/12/sys/fs/nfsclient/nfs_clport.c Sat Feb 29 22:10:00 2020 (r358476) @@ -597,7 +597,8 @@ ncl_pager_setsize(struct vnode *vp, u_quad_t *nsizep) setnsize = false; if (object != NULL && nsize != object->un_pager.vnp.vnp_size) { - if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) + if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE && + (curthread->td_pflags2 & TDP2_SBPAGES) == 0) setnsize = true; else np->n_flag |= NVNSETSZSKIP; Modified: stable/12/sys/sys/proc.h ============================================================================== --- stable/12/sys/sys/proc.h Sat Feb 29 21:55:48 2020 (r358475) +++ stable/12/sys/sys/proc.h Sat Feb 29 22:10:00 2020 (r358476) @@ -497,6 +497,8 @@ do { \ #define TDP_FORKING 0x20000000 /* Thread is being created through fork() */ #define TDP_EXECVMSPC 0x40000000 /* Execve destroyed old vmspace */ +#define TDP2_SBPAGES 0x00000001 /* Owns sbusy on some pages */ + /* * Reasons that the current thread can not be run yet. * More than one may apply.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202002292210.01TMA02o073732>