Messages in this thread Patches in this message | | | From | Armin Groesslinger <> | Date | Mon, 12 Apr 1999 10:06:31 +0200 (MET DST) | Subject | [PATCH] memory leaks: serial module & tty code, kernel 2.2.5 & 2.0.36 |
| |
Hello! I think I have discovered two memory leaks in kernel 2.2.5, one of which is also existent in 2.0.36. It only happens when the serial driver is compiled as a MODULE. I did (with 2.2.5) something like while true; do insmod serial; echo >/dev/ttyS0; rmmod serial; done
Watching the process with "cat /proc/slabinfo" I discovered that with each iteration there was an increase of 1 for "size-256" and of 2 for "size-64". After 23000 interations my system (i486,16 MB RAM) was unrecoverably out of memory and completely useless.
Looking at the sources I found two problems: 1. When the serial module is removed, it does not free the rs_table[?].info async_struct's and they get lost. (applies to 2.2.5 only) 2. When tty_unregister_driver is called, it does not free the structures driver->termios[?] and driver->termios_locked[?] and they also get lost. (applies to both 2.2.5 and 2.0.36)
I have written some patches to fix these problems: Patch for Problem 1 (2.2.5 only):
diff -ur 2.2.5/drivers/char/serial.c linux/drivers/char/serial.c --- 2.2.5/drivers/char/serial.c Thu Apr 8 21:24:12 1999 +++ linux/drivers/char/serial.c Sun Apr 11 19:02:27 1999 @@ -3307,6 +3307,8 @@ for (i = 0; i < NR_PORTS; i++) { if (rs_table[i].type != PORT_UNKNOWN) release_region(rs_table[i].port, 8); + if (rs_table[i].info != NULL) + kfree(rs_table[i].info); } if (tmp_buf) { free_page((unsigned long) tmp_buf);
Patch against 2.2.5 for Problem 2:
diff -ur 2.2.5/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- 2.2.5/drivers/char/tty_io.c Thu Apr 8 21:24:13 1999 +++ linux/drivers/char/tty_io.c Sun Apr 11 19:26:02 1999 @@ -1979,8 +1979,9 @@ { int retval; struct tty_driver *p; - int found = 0; + int i, found = 0; const char *othername = NULL; + struct termios *tp; if (*driver->refcount) return -EBUSY; @@ -2011,6 +2012,18 @@ driver->next->prev = driver->prev; proc_tty_unregister_driver(driver); + for (i = 0; i < driver->num; i++) { + tp = driver->termios[i]; + if (tp != NULL) { + kfree_s(tp, sizeof(struct termios)); + driver->termios[i] = NULL; + } + tp = driver->termios_locked[i]; + if (tp != NULL) { + kfree_s(tp, sizeof(struct termios)); + driver->termios_locked[i] = NULL; + } + } return 0; }
Patch against 2.0.36 for Problem 2:
--- 2.0.36/drivers/char/tty_io.c Mon Apr 12 01:39:19 1999 +++ linux/drivers/char/tty_io.c Mon Apr 12 02:48:40 1999 @@ -1926,8 +1926,9 @@ { int retval; struct tty_driver *p; - int found = 0; + int i, found = 0; const char *othername = NULL; + struct termios *tp; if (*driver->refcount) return -EBUSY; @@ -1957,6 +1958,18 @@ if (driver->next) driver->next->prev = driver->prev; + for (i = 0; i < driver->num; i++) { + tp = driver->termios[i]; + if (tp != NULL) { + kfree_s(tp, sizeof(struct termios)); + driver->termios[i] = NULL; + } + tp = driver->termios_locked[i]; + if (tp != NULL) { + kfree_s(tp, sizeof(struct termios)); + driver->termios_locked[i] = NULL; + } + } return 0; }
Note: Although I could not try it myself, I think that problem 2 is existent as well for other tty* drivers (e.g. ttyI* for ISDN) when they are compiled as modules. Could someone check this?
I am looking forward to getting your responses to my suggestions.
Yours, Armin Groesslinger.
PS: As I am not subscribed to the mailing list, could you please CC any reply to my personal mail address (groessli@fmi.uni-passau.de), please? Thanks.
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |