[PATCH] fix ds.c memory leak
Daniel Ritz
daniel.ritz at gmx.ch
Sun Jan 4 00:53:28 GMT 2004
bind_request() leaks memory if driver->attach() fails. also the module is still
referenced (b->driver = driver) while doing a module_put().
and driver->use_count would be wrong.
the patch also undoes what pcmcia_bind_device() did when driver->attach() fails.
it fixes another 'memory leak'. (yes, it's ugly, but ds.c is the only caller of
pcmcia_bind_device() so it's not too bad and since it's too late for massive
cleanup work...)
against 2.6.1-rc1.
--- 1.39/drivers/pcmcia/ds.c Sat Sep 27 05:11:05 2003
+++ edited/drivers/pcmcia/ds.c Sat Jan 3 16:36:16 2004
@@ -360,36 +360,43 @@
cs_error(NULL, BindDevice, ret);
printk(KERN_NOTICE "ds: unable to bind '%s' to socket %d\n",
(char *)dev_info, s->parent->sock);
- module_put(driver->owner);
- return -ENODEV;
+ ret = -ENODEV;
+ goto out_put;
}
/* Add binding to list for this socket */
- driver->use_count++;
- b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
- if (!b)
- {
- driver->use_count--;
- module_put(driver->owner);
- return -ENOMEM;
+ b = kmalloc(sizeof(*b), GFP_KERNEL);
+ if (!b) {
+ ret = -ENOMEM;
+ goto out_unbind;
}
b->driver = driver;
b->function = bind_info->function;
b->instance = NULL;
- b->next = s->bind;
- s->bind = b;
if (driver->attach) {
b->instance = driver->attach();
if (b->instance == NULL) {
printk(KERN_NOTICE "ds: unable to create instance "
"of '%s'!\n", (char *)bind_info->dev_info);
- module_put(driver->owner);
- return -ENODEV;
+ ret = -ENODEV;
+ goto out_free;
}
}
+
+ b->next = s->bind;
+ s->bind = b;
+ driver->use_count++;
return 0;
+
+out_free:
+ kfree(b);
+out_unbind:
+ pcmcia_bind_device_undo(&bind_req);
+out_put:
+ module_put(driver->owner);
+ return ret;
} /* bind_request */
/*====================================================================*/
@@ -873,6 +880,7 @@
ret = pcmcia_register_client(&s->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(NULL, RegisterClient, ret);
+ pcmcia_bind_device_undo(&bind);
kfree(s);
return -EINVAL;
}
--- 1.5/include/pcmcia/cs.h Sat Sep 27 05:15:09 2003
+++ edited/include/pcmcia/cs.h Sat Jan 3 16:31:47 2004
@@ -429,6 +429,7 @@
int pcmcia_access_configuration_register(client_handle_t handle, conf_reg_t *reg);
int pcmcia_bind_device(bind_req_t *req);
+int pcmcia_bind_device_undo(bind_req_t *req);
int pcmcia_bind_mtd(mtd_bind_t *req);
int pcmcia_deregister_client(client_handle_t handle);
int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config);
--- 1.68/drivers/pcmcia/cs.c Tue Dec 30 19:35:32 2003
+++ edited/drivers/pcmcia/cs.c Sat Jan 3 17:57:06 2004
@@ -1015,6 +1015,24 @@
return CS_SUCCESS;
} /* bind_device */
+/* undoes a previous call to pcmcia_bind_device() */
+int pcmcia_bind_device_undo(bind_req_t *req)
+{
+ struct pcmcia_socket *s;
+ client_t *client;
+
+ s = req->Socket;
+ if (!s)
+ return CS_BAD_SOCKET;
+
+ client = s->clients;
+ s->clients = client->next;
+
+ kfree(client);
+ return CS_SUCCESS;
+}
+
+
/*======================================================================
Bind_mtd() associates a device driver with a particular memory
@@ -2441,6 +2459,7 @@
EXPORT_SYMBOL(pcmcia_access_configuration_register);
EXPORT_SYMBOL(pcmcia_adjust_resource_info);
EXPORT_SYMBOL(pcmcia_bind_device);
+EXPORT_SYMBOL(pcmcia_bind_device_undo);
EXPORT_SYMBOL(pcmcia_bind_mtd);
EXPORT_SYMBOL(pcmcia_check_erase_queue);
EXPORT_SYMBOL(pcmcia_close_memory);
More information about the linux-pcmcia
mailing list