[PATCH] unionfs: fix slab abuses with krealloc
authorPekka Enberg <penberg@cs.helsinki.fi>
Sun, 13 May 2007 16:55:44 +0000 (12:55 -0400)
committerErez Zadok <ezk@cs.sunysb.edu>
Mon, 12 Jan 2009 23:20:21 +0000 (18:20 -0500)
This changes unionfs to use krealloc() for reallocating memory so that we
don't need to play tricks with slab internals.

Cc: Josef Sipek <jsipek@fsl.cs.sunysb.edu>
Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Josef 'Jeff' Sipek <jsipek@cs.sunysb.edu>
fs/Kconfig
fs/unionfs/copyup.c
fs/unionfs/lookup.c

index 1efbf5b572776e1d8bf495c1da70b4e9c5eefb9e..a54ce242b9498cea581a2c757ca96679aee1bf70 100644 (file)
@@ -1019,7 +1019,7 @@ config ECRYPT_FS
 
 config UNION_FS
        tristate "Union file system (EXPERIMENTAL)"
-       depends on SLAB && EXPERIMENTAL
+       depends on EXPERIMENTAL
        help
          Unionfs is a stackable unification file system, which appears to
          merge the contents of several directories (branches), while keeping
index 411553a9a968eaf06f1c95b81ae3f796e342b9db..331c6eebef1f444dae54e98b7b6943988e627310 100644 (file)
@@ -618,23 +618,16 @@ static struct dentry *create_parents_named(struct inode *dir,
        const char *childname;
        unsigned int childnamelen;
 
-       int old_kmalloc_size;
-       int kmalloc_size;
-       int num_dentry;
+       int nr_dentry;
        int count;
 
        int old_bstart;
        int old_bend;
        struct dentry **path = NULL;
-       struct dentry **tmp_path;
        struct super_block *sb;
 
        verify_locked(dentry);
 
-       /* There is no sense allocating any less than the minimum. */
-       kmalloc_size = malloc_sizes[0].cs_size;
-       num_dentry = kmalloc_size / sizeof(struct dentry *);
-
        if ((err = is_robranch_super(dir->i_sb, bindex))) {
                hidden_dentry = ERR_PTR(err);
                goto out;
@@ -644,7 +637,10 @@ static struct dentry *create_parents_named(struct inode *dir,
        old_bend = dbend(dentry);
 
        hidden_dentry = ERR_PTR(-ENOMEM);
-       path = kzalloc(kmalloc_size, GFP_KERNEL);
+
+       /* There is no sense allocating any less than the minimum. */
+       nr_dentry = 1;
+       path = kmalloc(nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
        if (!path)
                goto out;
 
@@ -670,26 +666,21 @@ static struct dentry *create_parents_named(struct inode *dir,
                /* find out the hidden_parent_dentry in the given branch */
                hidden_parent_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex);
 
-               /* store the child dentry */
-               path[count++] = child_dentry;
-
                /* grow path table */
-               if (count == num_dentry) {
-                       old_kmalloc_size = kmalloc_size;
-                       kmalloc_size *= 2;
-                       num_dentry = kmalloc_size / sizeof(struct dentry *);
+               if (count == nr_dentry) {
+                       void *p;
 
-                       tmp_path = kzalloc(kmalloc_size, GFP_KERNEL);
-                       if (!tmp_path) {
+                       nr_dentry *= 2;
+                       p = krealloc(path, nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
+                       if (!p) {
                                hidden_dentry = ERR_PTR(-ENOMEM);
                                goto out;
                        }
-                       memcpy(tmp_path, path, old_kmalloc_size);
-                       kfree(path);
-                       path = tmp_path;
-                       tmp_path = NULL;
+                       path = p;
                }
 
+               /* store the child dentry */
+               path[count++] = child_dentry;
        } while (!hidden_parent_dentry);
        count--;
 
index 0fc5993290118ce3ce8a82a4bb22fc6fc874b90d..5157f36960b00103df7411b7d17bf878a0e926f5 100644 (file)
@@ -432,8 +432,8 @@ void free_dentry_private_data(struct unionfs_dentry_info *udi)
 /* allocate new dentry private data, free old one if necessary */
 int new_dentry_private_data(struct dentry *dentry)
 {
-       int newsize;
-       int oldsize = 0;
+       int new_size;
+       int size;
        struct unionfs_dentry_info *info = UNIONFS_D(dentry);
        int unlock_on_err = 0;
 
@@ -451,8 +451,9 @@ int new_dentry_private_data(struct dentry *dentry)
                unlock_on_err = 1;
 
                info->lower_paths = NULL;
+               size = 0;
        } else
-               oldsize = sizeof(struct path) * info->bcount;
+               size = sizeof(struct path) * info->bcount;
 
        info->bstart = -1;
        info->bend = -1;
@@ -460,28 +461,21 @@ int new_dentry_private_data(struct dentry *dentry)
        info->bcount = sbmax(dentry->d_sb);
        atomic_set(&info->generation,
                   atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
-       newsize = sizeof(struct path) * sbmax(dentry->d_sb);
 
-       /* Don't reallocate when we already have enough space. */
-       /* It would be ideal if we could actually use the slab macros to
-        * determine what our object sizes is, but those are not exported.
-        */
-       if (oldsize) {
-               int minsize = malloc_sizes[0].cs_size;
+       new_size = sizeof(struct path) * sbmax(dentry->d_sb);
 
-               if (!newsize || ((oldsize < newsize) && (newsize > minsize))) {
-                       kfree(info->lower_paths);
-                       info->lower_paths = NULL;
-               }
-       }
+       /* Don't reallocate when we already have enough space. */
+       if (new_size > size) {
+               void *p;
 
-       if (!info->lower_paths && newsize) {
-               info->lower_paths = kmalloc(newsize, GFP_ATOMIC);
-               if (!info->lower_paths)
+               p = krealloc(info->lower_paths, new_size, GFP_ATOMIC);
+               if (!p)
                        goto out_free;
-       }
 
-       memset(info->lower_paths, 0, (oldsize > newsize ? oldsize : newsize));
+               info->lower_paths = p;
+               size = new_size;
+       }
+       memset(info->lower_paths, 0, size);
 
        spin_unlock(&dentry->d_lock);
        return 0;