Bug 19065

Summary: insmod fails to return after installing loop.o
Product: [Retired] Red Hat Linux Reporter: tjfalcone <afalcone>
Component: kernelAssignee: Michael K. Johnson <johnsonm>
Status: CLOSED ERRATA QA Contact: Brock Organ <borgan>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.0CC: afalcone, arjan, dr
Target Milestone: ---   
Target Release: ---   
Hardware: i386   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2000-10-14 19:24:24 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description tjfalcone 2000-10-13 17:33:23 UTC
Whenever the loop.o module is installed, either "manually" via a call to
insmod, or automagically via modprobe (which will in turn call insmod), the
module is installed, but the insmod process does not terminate.  Instead,
insmod enters the "uninterruptable sleep" state (denoted by D in a ps aux
listing).  This drives up the load average by one.  Moreover, since the
module is autocleaned by default, every subsequent call of insmod by
modprobe results in a new instance of insmod, which continues to drive the
load average ever higher.

Anyone know why insmod stays asleep forever after installing loop.o?  Even
when loop.o is removed, it continues to do this...

Comment 1 Arjan van de Ven 2000-10-14 19:21:50 UTC
I have made a patch that fixes this for me. I'll attach it to this bug; if you
want to/can test it,
I'd appreciate feedback.

Comment 2 Arjan van de Ven 2000-10-14 19:24:21 UTC
I can't attach a file to this bug, it seems. Patch at
http://www.fenrus.demon.nl/loop.diff 
and copy-n-pasted below (spaces vs tabs, so it might not apply, use the one in
the url)
--- linux/drivers/block/loop.c.org      Sat Oct 14 21:01:32 2000
+++ linux//drivers/block/loop.c Sat Oct 14 21:22:15 2000
@@ -883,13 +883,18 @@
 EXPORT_SYMBOL(loop_register_transfer);
 EXPORT_SYMBOL(loop_unregister_transfer);

+static volatile int loopd_running = 0; /* Ugly/hackish refcount hack */
+static volatile int stop_loopd = 0; /* Ugly/hackish internal signal */
+
 static int loopd (void *unused)
 {
        struct wait_queue wait = { current, NULL };

        lock_kernel();
+       loopd_running = 1;
        /* printk("loopback system thread started ...\n"); */
        strcpy(current->comm, "loopd");
+       exit_mm(current);
        init_waitqueue(&loopd_wait);
        init_waitqueue(&loopd_done_wait);

@@ -903,6 +908,7 @@
        if (!async_queue) {
                spin_unlock_irq(&io_request_lock);
                wake_up(&loopd_done_wait);
+               current->state = TASK_INTERRUPTIBLE;
                schedule();
                spin_lock_irq(&io_request_lock);
        }
@@ -910,7 +916,10 @@
        remove_wait_queue(&loopd_wait, &wait);
        current->state = TASK_RUNNING;

-       goto repeat;
+       if (!stop_loopd)
+               goto repeat;
+       spin_unlock_irq(&io_request_lock);
+       loopd_running = 0;

        return 0;
 }
@@ -949,7 +958,18 @@
 #ifdef MODULE
 void cleanup_module (void)
 {
+       int count=0;
        if (unregister_blkdev(MAJOR_NR, "loop"))
                printk(KERN_WARNING "loop: cannot unregister blkdev\n");
+       stop_loopd = 1;
+       while (loopd_running) {
+               count++;
+               wake_up(&loopd_wait);
+               current->state = TASK_RUNNING;
+               schedule();
+               if (count>50)
+                       break; /* uh oh. but prevent an infinite loop */
+       }
+
 }
 #endif



Comment 3 Arjan van de Ven 2001-02-09 20:17:11 UTC
Fixed in errata kernel