[PATCH] slab cache OOPS with unloaded module

From: Andreas Dilger (adilger@home.com)
Date: Wed Jan 12 2000 - 18:24:47 EST


Linus,
please consider the following patch for inclusion. It fixes an oops when
"cat /proc/slabinfo" is run, if a module that has allocated cache and not
freed it (e.g. nfs). The patch adds 16 bytes to the kmem_cache_s struct,
giving 20 bytes (instead of a pointer) to hold the cache name, instead of
keeping it in the module memory space.

Also a minor change to the comments indicating that slab caches should be
"destroyed" instead of "shrunk" when a module is unloaded. I have tested
this and destroy works with my module (it is not in use anywhere else in
the kernel. In the future, I hope to send another patch cleaning up the
modules that use slab caches (or could do so, like uhci).

Cheers, Andreas
--- cut here ---
--- linux/mm/slab.c.old Fri Dec 31 11:38:32 1999
+++ linux/mm/slab.c Tue Jan 11 15:30:26 2000
@@ -216,6 +216,8 @@
 
 #endif /* SLAB_DEBUG_SUPPORT */
 
+#define SLAB_CACHE_NAME_LEN 20 /* max name length for a slab cache */
+
 /* Cache struct - manages a cache.
  * First four members are commonly referenced during an alloc/free operation.
  */
@@ -241,7 +243,7 @@
         size_t c_colour; /* cache colouring range */
         size_t c_colour_next;/* cache colouring */
         unsigned long c_failures;
- const char *c_name;
+ char c_name[SLAB_CACHE_NAME_LEN];
         struct kmem_cache_s *c_nextp;
         kmem_cache_t *c_index_cachep;
 #if SLAB_STATS
@@ -674,7 +676,6 @@
 /* Create a cache:
  * Returns a ptr to the cache on success, NULL on failure.
  * Cannot be called within a int, but can be interrupted.
- * NOTE: The 'name' is assumed to be memory that is _not_ going to disappear.
  */
 kmem_cache_t *
 kmem_cache_create(const char *name, size_t size, size_t offset,
@@ -694,6 +695,10 @@
                 printk("%sNULL ptr\n", func_nm);
                 goto opps;
         }
+ if (strlen(name) >= SLAB_CACHE_NAME_LEN) {
+ printk("%sname too long\n", func_nm);
+ goto opps;
+ }
         if (in_interrupt()) {
                 printk("%sCalled during int - %s\n", func_nm, name);
                 goto opps;
@@ -955,7 +960,8 @@
         cachep->c_ctor = ctor;
         cachep->c_dtor = dtor;
         cachep->c_magic = SLAB_C_MAGIC;
- cachep->c_name = name; /* Simply point to the name. */
+ /* Copy name over so we don't have problems with unloaded modules */
+ strcpy(cachep->c_name, name);
         spin_lock_init(&cachep->c_spinlock);
 
         /* Need the semaphore to access the chain. */
@@ -1033,12 +1039,7 @@
 }
 
 /* Shrink a cache. Releases as many slabs as possible for a cache.
- * It is expected this function will be called by a module when it is
- * unloaded. The cache is _not_ removed, this creates too many problems and
- * the cache-structure does not take up much room. A module should keep its
- * cache pointer(s) in unloaded memory, so when reloaded it knows the cache
- * is available. To help debugging, a zero exit status indicates all slabs
- * were released.
+ * To help debugging, a zero exit status indicates all slabs were released.
  */
 int
 kmem_cache_shrink(kmem_cache_t *cachep)
@@ -1056,6 +1057,12 @@
 /*
  * Remove a kmem_cache_t object from the slab cache. When returns 0 it
  * completed succesfully. -arca
+ *
+ * It is expected this function will be called by a module when it is
+ * unloaded. This will remove the cache completely, and avoid a duplicate
+ * cache being allocated each time a module is loaded and unloaded, if the
+ * module doesn't have persistent in-kernel storage across loads and unloads.
+ *
  */
 int kmem_cache_destroy(kmem_cache_t * cachep)
 {
--- cut here ---

-- 
Andreas Dilger  \ "If a man ate a pound of pasta and a pound of antipasto,
                 \  would they cancel out, leaving him still hungry?"
http://www-mddsp.enel.ucalgary.ca/People/adilger/               -- Dogbert

- 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/



This archive was generated by hypermail 2b29 : Sat Jan 15 2000 - 21:00:21 EST