From owner-svn-src-stable-12@freebsd.org Sat Feb 29 22:10:02 2020 Return-Path: Delivered-To: svn-src-stable-12@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 0221A242681; Sat, 29 Feb 2020 22:10:02 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48VLDn3ymmz4T5Z; Sat, 29 Feb 2020 22:10:01 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 56EC3216B6; Sat, 29 Feb 2020 22:10:01 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 01TMA1rK073735; Sat, 29 Feb 2020 22:10:01 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 01TMA02o073732; Sat, 29 Feb 2020 22:10:00 GMT (envelope-from kib@FreeBSD.org) Message-Id: <202002292210.01TMA02o073732@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Sat, 29 Feb 2020 22:10:00 +0000 (UTC) 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 X-SVN-Group: stable-12 X-SVN-Commit-Author: kib X-SVN-Commit-Paths: in stable/12/sys: fs/nfsclient sys X-SVN-Commit-Revision: 358476 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-12@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for only the 12-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 29 Feb 2020 22:10:02 -0000 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.