svn commit: r317148 - head/sys/compat/linuxkpi/common/src

Mark Johnston markj at FreeBSD.org
Wed Apr 19 16:12:03 UTC 2017


Author: markj
Date: Wed Apr 19 16:12:02 2017
New Revision: 317148
URL: https://svnweb.freebsd.org/changeset/base/317148

Log:
  Drop Giant before sleeping in linux_wait_for_{timeout_,}common().
  
  Reported and tested by:	Pete Wright <pete at nomadlogic.org>
  Reviewed by:	hselasky (previous version)
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D10414

Modified:
  head/sys/compat/linuxkpi/common/src/linux_compat.c

Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c	Wed Apr 19 15:59:16 2017	(r317147)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c	Wed Apr 19 16:12:02 2017	(r317148)
@@ -1321,28 +1321,38 @@ linux_complete_common(struct completion 
 long
 linux_wait_for_common(struct completion *c, int flags)
 {
+	long error;
+
 	if (SCHEDULER_STOPPED())
 		return (0);
 
+	DROP_GIANT();
+
 	if (flags != 0)
 		flags = SLEEPQ_INTERRUPTIBLE | SLEEPQ_SLEEP;
 	else
 		flags = SLEEPQ_SLEEP;
+	error = 0;
 	for (;;) {
 		sleepq_lock(c);
 		if (c->done)
 			break;
 		sleepq_add(c, NULL, "completion", flags, 0);
 		if (flags & SLEEPQ_INTERRUPTIBLE) {
-			if (sleepq_wait_sig(c, 0) != 0)
-				return (-ERESTARTSYS);
+			if (sleepq_wait_sig(c, 0) != 0) {
+				error = -ERESTARTSYS;
+				goto intr;
+			}
 		} else
 			sleepq_wait(c, 0);
 	}
 	c->done--;
 	sleepq_release(c);
 
-	return (0);
+intr:
+	PICKUP_GIANT();
+
+	return (error);
 }
 
 /*
@@ -1351,18 +1361,22 @@ linux_wait_for_common(struct completion 
 long
 linux_wait_for_timeout_common(struct completion *c, long timeout, int flags)
 {
-	long end = jiffies + timeout;
+	long end = jiffies + timeout, error;
+	int ret;
 
 	if (SCHEDULER_STOPPED())
 		return (0);
 
+	DROP_GIANT();
+
 	if (flags != 0)
 		flags = SLEEPQ_INTERRUPTIBLE | SLEEPQ_SLEEP;
 	else
 		flags = SLEEPQ_SLEEP;
-	for (;;) {
-		int ret;
 
+	error = 0;
+	ret = 0;
+	for (;;) {
 		sleepq_lock(c);
 		if (c->done)
 			break;
@@ -1375,16 +1389,20 @@ linux_wait_for_timeout_common(struct com
 		if (ret != 0) {
 			/* check for timeout or signal */
 			if (ret == EWOULDBLOCK)
-				return (0);
+				error = 0;
 			else
-				return (-ERESTARTSYS);
+				error = -ERESTARTSYS;
+			goto intr;
 		}
 	}
 	c->done--;
 	sleepq_release(c);
 
+intr:
+	PICKUP_GIANT();
+
 	/* return how many jiffies are left */
-	return (linux_timer_jiffies_until(end));
+	return (ret != 0 ? error : linux_timer_jiffies_until(end));
 }
 
 int


More information about the svn-src-head mailing list