patch-2.2.17 linux/drivers/net/comx.c

Next file: linux/drivers/net/de4x5.c
Previous file: linux/drivers/net/comx-proto-ppp.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.16/drivers/net/comx.c linux/drivers/net/comx.c
@@ -10,6 +10,9 @@
  *
  * Copyright (C) 1995-1999 ITConsult-Pro Co.
  *
+ * Contributors:
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> (0.85)
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
@@ -39,9 +42,12 @@
  * Version 0.84 (99/12/01):
  *		- comx_status should not check for IFF_UP (to report
  *		  line status from dev->open())
+ * Version 0.85 (00/08/15):
+ * 		- resource release on failure in comx_mkdir
+ * 		- fix return value on failure at comx_write_proc
  */
 
-#define VERSION "0.84"
+#define VERSION "0.85"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -521,6 +527,7 @@
 	ch->loadavg_size = ch->loadavg[2] / ch->loadavg[0] + 1; 
 	if ((ch->avg_bytes = kmalloc(ch->loadavg_size * 
 		sizeof(unsigned long) * 2, GFP_KERNEL)) == NULL) {
+		kfree(ch);
 		return -ENOMEM;
 	}
 
@@ -649,7 +656,7 @@
 			ch->debug_start = ch->debug_end = 0;
 			restore_flags(flags);
 			free_page((unsigned long)page);
-			return count;
+			return ret ? ret : count;
 		}
 		
 		if (*page != '+' && *page != '-') {
@@ -852,12 +859,18 @@
 	struct proc_dir_entry *new_dir, *debug_file;
 	struct device *dev;
 	struct comx_channel *ch;
+	int ret = -EIO;
 
 	if (dir->i_ino != comx_root_dir.low_ino) return -ENOTDIR;
 
+	if ((dev = kmalloc(sizeof(struct device), GFP_KERNEL)) == NULL) {
+		return -ENOMEM;
+	}
+	memset(dev, 0, sizeof(struct device));
+
 	if ((new_dir = create_proc_entry(dentry->d_name.name, mode | S_IFDIR, 
 		&comx_root_dir)) == NULL) {
-		return -EIO;
+		goto cleanup_dev;
 	}
 
 	new_dir->ops = &proc_dir_inode_operations;  // ez egy normalis /proc konyvtar
@@ -867,22 +880,22 @@
 	/* Ezek kellenek */
 	if (!create_comx_proc_entry(FILENAME_HARDWARE, 0644, 
 	    strlen(HWNAME_NONE) + 1, new_dir)) {
-		return -ENOMEM;
+		goto cleanup_new_dir;
 	}
 	if (!create_comx_proc_entry(FILENAME_PROTOCOL, 0644, 
 	    strlen(PROTONAME_NONE) + 1, new_dir)) {
-		return -ENOMEM;
+		goto cleanup_filename_hardware;
 	}
 	if (!create_comx_proc_entry(FILENAME_STATUS, 0444, 0, new_dir)) {
-		return -ENOMEM;
+		goto cleanup_filename_protocol;
 	}
 	if (!create_comx_proc_entry(FILENAME_LINEUPDELAY, 0644, 2, new_dir)) {
-		return -ENOMEM;
+		goto cleanup_filename_status;
 	}
 
 	if ((debug_file = create_proc_entry(FILENAME_DEBUG, 
 	    S_IFREG | 0644, new_dir)) == NULL) {
-		return -ENOMEM;
+		goto cleanup_filename_lineupdelay;
 	}
 	debug_file->ops = &comx_debug_inode_ops;
 	debug_file->data = (void *)debug_file; 
@@ -890,20 +903,17 @@
 	debug_file->write_proc = &comx_write_proc;
 	debug_file->nlink = 1;
 
-	if ((dev = kmalloc(sizeof(struct device), GFP_KERNEL)) == NULL) {
-		return -ENOMEM;
-	}
-	memset(dev, 0, sizeof(struct device));
 	dev->name = (char *)new_dir->name;
 	dev->init = comx_init_dev;
 
 	if (register_netdevice(dev)) {
-		return -EIO;
+		goto cleanup_filename_debug;
 	}
 	ch=dev->priv;
 	if((ch->if_ptr = (void *)kmalloc(sizeof(struct ppp_device),
 				 GFP_KERNEL)) == NULL) {
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto cleanup_register;
 	}
 	memset(ch->if_ptr, 0, sizeof(struct ppp_device));
 	ch->debug_file = debug_file; 
@@ -913,13 +923,33 @@
 	ch->debug_start = ch->debug_end = 0;
 	if ((ch->debug_area = kmalloc(ch->debug_size = DEFAULT_DEBUG_SIZE, 
 	    GFP_KERNEL)) == NULL) {
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto cleanup_if_ptr;
 	}
 
 	ch->lineup_delay = DEFAULT_LINEUP_DELAY;
 
 	MOD_INC_USE_COUNT;
 	return 0;
+cleanup_if_ptr:
+	kfree(ch->if_ptr);
+cleanup_register:
+	unregister_netdevice(dev);
+cleanup_filename_debug:
+	remove_proc_entry(FILENAME_DEBUG, new_dir);
+cleanup_filename_lineupdelay:
+	remove_proc_entry(FILENAME_LINEUPDELAY, new_dir);
+cleanup_filename_status:
+	remove_proc_entry(FILENAME_STATUS, new_dir);
+cleanup_filename_protocol:
+	remove_proc_entry(FILENAME_PROTOCOL, new_dir);
+cleanup_filename_hardware:
+	remove_proc_entry(FILENAME_HARDWARE, new_dir);
+cleanup_new_dir:
+	remove_proc_entry(dentry->d_name.name, &comx_root_dir);
+cleanup_dev:
+	kfree(dev);
+	return ret;
 }
 
 static int comx_rmdir(struct inode *dir, struct dentry *dentry)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)