Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Apr 2017 16:12:02 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r317148 - head/sys/compat/linuxkpi/common/src
Message-ID:  <201704191612.v3JGC2j1081756@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704191612.v3JGC2j1081756>