Author: rmacklem
Date: Wed Dec 31 00:34:37 2014
New Revision: 276436
URL: https://svnweb.freebsd.org/changeset/base/276436

Log:
  MFC: r276192, r276200
  Modify vop_stdadvlock{async}() so that it only
  locks/unlocks the vnode and does a VOP_GETATTR()
  for the SEEK_END case. This is safe to do, since
  lf_advlock{async}() only uses the size argument
  for the SEEK_END case.
  The NFSv4 server needs this when
  vfs.nfsd.enable_locallocks!=0 since locking the
  vnode results in a LOR that can cause a deadlock
  for the nfsd threads.

Modified:
  stable/10/sys/kern/vfs_default.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/vfs_default.c
==============================================================================
--- stable/10/sys/kern/vfs_default.c    Wed Dec 31 00:09:05 2014        
(r276435)
+++ stable/10/sys/kern/vfs_default.c    Wed Dec 31 00:34:37 2014        
(r276436)
@@ -399,17 +399,24 @@ int
 vop_stdadvlock(struct vop_advlock_args *ap)
 {
        struct vnode *vp;
-       struct ucred *cred;
        struct vattr vattr;
        int error;
 
        vp = ap->a_vp;
-       cred = curthread->td_ucred;
-       vn_lock(vp, LK_SHARED | LK_RETRY);
-       error = VOP_GETATTR(vp, &vattr, cred);
-       VOP_UNLOCK(vp, 0);
-       if (error)
-               return (error);
+       if (ap->a_fl->l_whence == SEEK_END) {
+               /*
+                * The NFSv4 server must avoid doing a vn_lock() here, since it
+                * can deadlock the nfsd threads, due to a LOR.  Fortunately
+                * the NFSv4 server always uses SEEK_SET and this code is
+                * only required for the SEEK_END case.
+                */
+               vn_lock(vp, LK_SHARED | LK_RETRY);
+               error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
+               VOP_UNLOCK(vp, 0);
+               if (error)
+                       return (error);
+       } else
+               vattr.va_size = 0;
 
        return (lf_advlock(ap, &(vp->v_lockf), vattr.va_size));
 }
@@ -418,17 +425,19 @@ int
 vop_stdadvlockasync(struct vop_advlockasync_args *ap)
 {
        struct vnode *vp;
-       struct ucred *cred;
        struct vattr vattr;
        int error;
 
        vp = ap->a_vp;
-       cred = curthread->td_ucred;
-       vn_lock(vp, LK_SHARED | LK_RETRY);
-       error = VOP_GETATTR(vp, &vattr, cred);
-       VOP_UNLOCK(vp, 0);
-       if (error)
-               return (error);
+       if (ap->a_fl->l_whence == SEEK_END) {
+               /* The size argument is only needed for SEEK_END. */
+               vn_lock(vp, LK_SHARED | LK_RETRY);
+               error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
+               VOP_UNLOCK(vp, 0);
+               if (error)
+                       return (error);
+       } else
+               vattr.va_size = 0;
 
        return (lf_advlockasync(ap, &(vp->v_lockf), vattr.va_size));
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to