Fix for crash on eject after module removal

Dominik Brodowski linux at brodo.de
Sun Apr 27 01:55:28 BST 2003


On Sat, Apr 26, 2003 at 08:27:14PM +0100, Russell King wrote:
> I'll wait for Dominik to ack/nack this patch before putting it in bk.
See below.

> The recent 2.5.x kernels panic if I remove a PCMCIA client module by 
> rmmod and then do "cardctl eject":
> 
> modprobe yenta_socket
> cardmgr
> rmmod orinoco_cs
> cardctl eject

Yes, users might do this. But it's BAD BAD BAD. cardmgr does its own
reference counting of module usage, and rmmod's it automatically if it isn't
needed any longer. Instead, the pcmcia core should increase the reference
count on "bind"==probe, and drop the reference in "unbind"==remove. So I'd
prefer the patch attached (untested, notebook ~6km away). Pavel, could you
please test it?

	Dominik


[PCMCIA] fix kernel panic on rmmod (Pavel Roskin, Dominik Brodowski)

Currently, PCMCIA tries to keep track of module usage in userspace. This
causes a kernel panic on manual "rmmod" commands if modules are in use.
Despite the reference counting being horribly broken, try to keep this 
working, but use try_module_get() / put_module() if possible.

diff -ruN linux-original/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux-original/drivers/pcmcia/ds.c	2003-04-27 00:41:56.000000000 +0200
+++ linux/drivers/pcmcia/ds.c	2003-04-27 00:50:20.000000000 +0200
@@ -163,17 +163,24 @@
  */
 void pcmcia_unregister_driver(struct pcmcia_driver *driver)
 {
-	socket_bind_t *b;
+	socket_bind_t **b, *c;
 	struct pcmcia_bus_socket *bus_sock;
 
 	if (driver->use_count > 0) {
+		printk(KERN_CRIT "Don't rmmod pcmcia modules manually!!!\n");
 		/* Blank out any left-over device instances */
 		driver->attach = NULL; driver->detach = NULL;
 		down_read(&bus_socket_list_rwsem);
 		list_for_each_entry(bus_sock, &bus_socket_list, socket_list) {
-			for (b = bus_sock->bind; b; b = b->next)
-				if (b->driver == driver) 
-					b->instance = NULL;
+			for (b = &bus_sock->bind; *b; b = &(*b)->next) {
+				if ((*b)->driver == driver) {
+					c = *b;
+					*b = c->next;
+					kfree(c);
+					if (!(*b))
+						break;
+				}
+			}
 		}
 		up_read(&bus_socket_list_rwsem);
 	}
@@ -421,6 +428,8 @@
     }
 
     /* Add binding to list for this socket */
+    if (!try_module_get(driver->owner))
+    	return -EINVAL;
     driver->use_count++;
     b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
     if (!b) 
@@ -533,6 +542,7 @@
     
     c = *b;
     c->driver->use_count--;
+    module_put(c->driver->owner);
     if (c->driver->detach) {
 	if (c->instance)
 	    c->driver->detach(c->instance);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://lists.infradead.org/pipermail/linux-pcmcia/attachments/20030427/0de9e908/attachment.bin


More information about the linux-pcmcia mailing list