Author: kib
Date: Sun Jun 19 18:32:35 2016
New Revision: 302020
URL: https://svnweb.freebsd.org/changeset/base/302020

Log:
  Remote and local adv lock servers might de-synchronize (the added comment
  explains the plausible scenario), resulting in EDEADLK returned on the
  local registration attempt.  Handle this by re-trying the local op [1].
  
  On unmount, local registration abort is indicated as EINTR, abort the nlm
  call as well.
  
  Reported and tested by:       pho
  Suggested and reviewed by:    dfr (previous version, [1])
  Sponsored by: The FreeBSD Foundation
  MFC after:    1 week
  Approved by:  re (delphij)

Modified:
  head/sys/nlm/nlm_advlock.c

Modified: head/sys/nlm/nlm_advlock.c
==============================================================================
--- head/sys/nlm/nlm_advlock.c  Sun Jun 19 18:29:43 2016        (r302019)
+++ head/sys/nlm/nlm_advlock.c  Sun Jun 19 18:32:35 2016        (r302020)
@@ -713,7 +713,37 @@ nlm_record_lock(struct vnode *vp, int op
        newfl.l_pid = svid;
        newfl.l_sysid = NLM_SYSID_CLIENT | sysid;
 
-       error = lf_advlockasync(&a, &vp->v_lockf, size);
+       for (;;) {
+               error = lf_advlockasync(&a, &vp->v_lockf, size);
+               if (error == EDEADLK) {
+                       /*
+                        * Locks are associated with the processes and
+                        * not with threads.  Suppose we have two
+                        * threads A1 A2 in one process, A1 locked
+                        * file f1, A2 is locking file f2, and A1 is
+                        * unlocking f1. Then remote server may
+                        * already unlocked f1, while local still not
+                        * yet scheduled A1 to make the call to local
+                        * advlock manager. The process B owns lock on
+                        * f2 and issued the lock on f1.  Remote would
+                        * grant B the request on f1, but local would
+                        * return EDEADLK.
+                       */
+                       pause("nlmdlk", 1);
+                       /* XXXKIB allow suspend */
+               } else if (error == EINTR) {
+                       /*
+                        * lf_purgelocks() might wake up the lock
+                        * waiter and removed our lock graph edges.
+                        * There is no sense in re-trying recording
+                        * the lock to the local manager after
+                        * reclaim.
+                        */
+                       error = 0;
+                       break;
+               } else
+                       break;
+       }
        KASSERT(error == 0 || error == ENOENT,
            ("Failed to register NFS lock locally - error=%d", error));
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to