Author: markj
Date: Wed May  3 23:41:09 2017
New Revision: 317780
URL: https://svnweb.freebsd.org/changeset/base/317780

Log:
  MFC r317148:
  Drop Giant before sleeping in linux_wait_for_{timeout_,}common().

Modified:
  stable/11/sys/compat/linuxkpi/common/src/linux_compat.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- stable/11/sys/compat/linuxkpi/common/src/linux_compat.c     Wed May  3 
22:35:41 2017        (r317779)
+++ stable/11/sys/compat/linuxkpi/common/src/linux_compat.c     Wed May  3 
23:41:09 2017        (r317780)
@@ -1096,28 +1096,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);
 }
 
 /*
@@ -1126,18 +1136,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;
@@ -1150,16 +1164,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
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to