commit b1c27b05c1dd73591d7d9f3bd48e9d67fde863bc
Author: Erez_Zadok <[EMAIL PROTECTED]>
Date:   Fri Nov 16 14:51:39 2007 -0500

    Unionfs: Cleanup new_dentry_private_data
    
    Signed-off-by: Josef 'Jeff' Sipek <[EMAIL PROTECTED]>
    
    Conflicts:
    
        fs/unionfs/lookup.c

diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 2372682..61c6119 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -59,11 +59,22 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry,
                BUG_ON(UNIONFS_D(dentry) != NULL);
                locked_child = 1;
        }
-       if (lookupmode != INTERPOSE_PARTIAL) {
-               if ((err = new_dentry_private_data(dentry)))
-                       goto out;
-               allocated_new_info = 1;
+
+       switch(lookupmode) {
+               case INTERPOSE_PARTIAL:
+                       break;
+               case INTERPOSE_LOOKUP:
+                       if ((err = new_dentry_private_data(dentry)))
+                               goto out;
+                       allocated_new_info = 1;
+                       break;
+               default:
+                       if ((err = realloc_dentry_private_data(dentry)))
+                               goto out;
+                       allocated_new_info = 1;
+                       break;
        }
+
        /* must initialize dentry operations */
        dentry->d_op = &unionfs_dops;
 
@@ -410,69 +421,81 @@ void unionfs_destroy_dentry_cache(void)
                kmem_cache_destroy(unionfs_dentry_cachep);
 }
 
-void free_dentry_private_data(struct unionfs_dentry_info *udi)
+void free_dentry_private_data(struct dentry *dentry)
 {
-       if (!udi)
+       struct unionfs_dentry_info *udi;
+
+       if (!dentry || !dentry->d_fsdata)
                return;
+       udi = UNIONFS_D(dentry);
        dput(udi->odf.dentry);
        udi->odf.dentry = NULL;
-       kmem_cache_free(unionfs_dentry_cachep, udi);
+       kmem_cache_free(unionfs_dentry_cachep, dentry->d_fsdata);
+       dentry->d_fsdata = NULL;
 }
 
-/*
- * Allocate new dentry private data, free old one if necessary.
- * On success, returns a dentry whose ->info node is locked already.
- *
- * Note: this function may get a dentry with an already existing *and*
- * locked info node!
- */
-int new_dentry_private_data(struct dentry *dentry)
+static inline int __realloc_dentry_private_data(struct dentry *dentry)
 {
-       int size;
        struct unionfs_dentry_info *info = UNIONFS_D(dentry);
        void *p;
-       int unlock_on_err = 0;
+       int size;
 
-       if (!info) {
-               dentry->d_fsdata = kmem_cache_alloc(unionfs_dentry_cachep,
-                                                   GFP_ATOMIC);
-               info = UNIONFS_D(dentry);
-               if (!info)
-                       goto out;
+       BUG_ON(!info);
 
-               mutex_init(&info->lock);
-               unionfs_lock_dentry(dentry);
-               unlock_on_err = 1;
+       size = sizeof(struct path) * sbmax(dentry->d_sb);
+       p = krealloc(info->lower_paths, size, GFP_ATOMIC);
+       if (unlikely(!p))
+               return -ENOMEM;
 
-               info->lower_paths = NULL;
-       }
+       info->odf.dentry = NULL;
+
+       info->lower_paths = p;
 
        info->bstart = -1;
        info->bend = -1;
        info->bcount = sbmax(dentry->d_sb);
-       info->odf.dentry = NULL;
        atomic_set(&info->generation,
-                  atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
-
-       size = sizeof(struct path) * sbmax(dentry->d_sb);
+                       atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
 
-       p = krealloc(info->lower_paths, size, GFP_ATOMIC);
-       if (!p)
-               goto out_free;
-
-       info->lower_paths = p;
        memset(info->lower_paths, 0, size);
 
        return 0;
+}
 
-out_free:
-       kfree(info->lower_paths);
-       if (unlock_on_err)
-               unionfs_unlock_dentry(dentry);
+/* UNIONFS_D(dentry)->lock must be locked */
+static int realloc_dentry_private_data(struct dentry *dentry)
+{
+       if (!__realloc_dentry_private_data(dentry))
+               return 0;
 
-out:
-       free_dentry_private_data(info);
-       dentry->d_fsdata = NULL;
+       kfree(UNIONFS_D(dentry)->lower_paths);
+       free_dentry_private_data(dentry);
+       return -ENOMEM;
+}
+
+/* allocate new dentry private data */
+int new_dentry_private_data(struct dentry *dentry)
+{
+       struct unionfs_dentry_info *info = UNIONFS_D(dentry);
+
+       BUG_ON(info);
+
+       info = kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC);
+       if (unlikely(!info))
+               return -ENOMEM;
+
+       mutex_init(&info->lock);
+       mutex_lock(&info->lock);
+
+       info->lower_paths = NULL;
+
+       dentry->d_fsdata = info;
+
+       if (!__realloc_dentry_private_data(dentry))
+               return 0;
+
+       mutex_unlock(&info->lock);
+       free_dentry_private_data(dentry);
        return -ENOMEM;
 }
 
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 54d45ce..aafd2a2 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -254,6 +254,7 @@ static inline void unionfs_double_lock_dentry(struct dentry 
*d1,
        unionfs_lock_dentry(d2);
 }
 
+extern int realloc_dentry_private_data(struct dentry *dentry);
 extern int new_dentry_private_data(struct dentry *dentry);
 extern void free_dentry_private_data(struct unionfs_dentry_info *udi);
 extern void update_bstart(struct dentry *dentry);
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to