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