svn commit: r302020 - head/sys/nlm

Konstantin Belousov kib at FreeBSD.org
Sun Jun 19 18:32:37 UTC 2016


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));
 }


More information about the svn-src-all mailing list