From e5cffdd34bb2734f642d4c51f65bc56616561df7 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 20 Aug 2017 10:08:45 +0000 Subject: Do not drop NFS vnode lock when performing consistency checks. Currently several paths in the NFS client upgrade the shared vnode lock to exclusive, which might cause temporal dropping of the lock. This action appears to be fatal for nullfs mounts over NFS. If the operation is performed over nullfs vnode, then bypassed down to NFS VOP, and the lock is dropped, other thread might reclaim the upper nullfs vnode. Since on reclaim the nullfs vnode lock and NFS vnode lock are split, the original lock state of the nullfs vnode is not restored. As result, VFS operations receive not locked vnode after a VOP call. Stop upgrading the vnode lock when we check the consistency or flush buffers as result of detected inconsistency. Instead, allocate a new lockmgr lock for each NFS node, which is locked exclusive instead of the vnode lock upgrade. In other words, the other parallel modification of the vnode are excluded by either vnode lock conflict or exclusivity of the new lock when the vnode lock is shared. Also revert r316529 because now the vnode cannot be reclaimed during ncl_vinvalbuf(). In collaboration with: pho Reviewed by: rmacklem Reported and tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D12083 --- sys/fs/nfsclient/nfs_clnode.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sys/fs/nfsclient/nfs_clnode.c') diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c index 76ff26b07886b..c6fd5736f7385 100644 --- a/sys/fs/nfsclient/nfs_clnode.c +++ b/sys/fs/nfsclient/nfs_clnode.c @@ -141,6 +141,9 @@ ncl_nget(struct mount *mntp, u_int8_t *fhp, int fhsize, struct nfsnode **npp, * happened to return an error no special casing is needed). */ mtx_init(&np->n_mtx, "NEWNFSnode lock", NULL, MTX_DEF | MTX_DUPOK); + lockinit(&np->n_excl, PVFS, "nfsupg", VLKTIMEOUT, LK_NOSHARE | + LK_CANRECURSE); + /* * NFS supports recursive and shared locking. */ @@ -167,6 +170,7 @@ ncl_nget(struct mount *mntp, u_int8_t *fhp, int fhsize, struct nfsnode **npp, *npp = NULL; FREE((caddr_t)np->n_fhp, M_NFSFH); mtx_destroy(&np->n_mtx); + lockdestroy(&np->n_excl); uma_zfree(newnfsnode_zone, np); return (error); } @@ -332,6 +336,7 @@ ncl_reclaim(struct vop_reclaim_args *ap) if (np->n_v4 != NULL) FREE((caddr_t)np->n_v4, M_NFSV4NODE); mtx_destroy(&np->n_mtx); + lockdestroy(&np->n_excl); uma_zfree(newnfsnode_zone, vp->v_data); vp->v_data = NULL; return (0); -- cgit v1.2.3