commit e846fc966e0e7d3fa4fc2a00b1757085dd917f41
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Fri Feb 9 17:58:59 2007 -0500

    Fixed some concurrency issues
    
    before i would alloc a new odf_info on each odf_lookup,
    now I reuse the same for each unionfs dentry.
    But still my locking needs to be fixed

diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index f17d4d0..caf5689 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -52,7 +52,7 @@ static int unionfs_filldir(void *dirent, const char *name, 
int namelen,
        /* odf check whiteouts */
        if (d_type == DT_DIR)
                odf_flag = ODF_LOOKUP_DIR;
-       odi = odf_lookup_name(buf->dir, name, namelen, odf_flag);
+       odi = __odf_lookup(buf->dir, name, namelen, odf_flag, 0);
        if (IS_ERR(odi)){
                err = PTR_ERR(odi);
                odi = NULL;
diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index afdb974..d3edd0d 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -154,7 +154,7 @@ static int readdir_util_callback(void *dirent, const char 
*name, int namelen,
                goto out;
 
        /* check odf */
-       odi = odf_lookup_name(buf->dir, name, namelen, 0);
+       odi = __odf_lookup(buf->dir, name, namelen, 0, 0);
        if (IS_ERR(odi)){
                odi = NULL;
                goto out;
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 6caf0e3..3467bd6 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -191,10 +191,10 @@ static int unionfs_create(struct inode *parent, struct 
dentry *dentry,
                        if (!IS_COPYUP_ERR(err))
                                break;
                } else {
-                       UNIONFS_D(dentry)->odf_info =
-                               odf_lookup(dentry->d_parent, dentry, 
+                       err = odf_lookup(dentry->d_parent, dentry, 
                                ODF_LOOKUP_FILE|ODF_LOOKUP_RMV_WH);
-                       err = unionfs_interpose(dentry, parent->i_sb, 0);
+                       if (!err)
+                               err = unionfs_interpose(dentry, parent->i_sb, 
0);
                        if (!err) {
                                fsstack_copy_attr_times(parent,
                                                hidden_parent_dentry->d_inode);
@@ -472,10 +472,10 @@ static int unionfs_symlink(struct inode *dir, struct 
dentry *dentry,
                                break;
                } else {
                        /* update odf and remove any wh before interpose*/
-                       UNIONFS_D(dentry)->odf_info =
-                               odf_lookup(dentry->d_parent, dentry, 
+                       err = odf_lookup(dentry->d_parent, dentry, 
                                ODF_LOOKUP_FILE|ODF_LOOKUP_RMV_WH);
-                       err = unionfs_interpose(dentry, dir->i_sb, 0);
+                       if (!err)
+                               err = unionfs_interpose(dentry, dir->i_sb, 0);
                        if (!err) {
                                fsstack_copy_attr_times(dir,
                                                hidden_dir_dentry->d_inode);
@@ -554,13 +554,10 @@ static int unionfs_mkdir(struct inode *parent, struct 
dentry *dentry, int mode)
        set_dbend(dentry, bindex);
 
        /* add to odf with opaque branch set to 0 */
-       UNIONFS_D(dentry)->odf_info =
-               odf_lookup(dentry->d_parent, dentry,
+       err = odf_lookup(dentry->d_parent, dentry,
                ODF_LOOKUP_DIR|ODF_LOOKUP_RMV_WH|ODF_LOOKUP_OPQ);
-       if (IS_ERR( UNIONFS_D(dentry)->odf_info)){
-               err = PTR_ERR( UNIONFS_D(dentry)->odf_info);
+       if (err)
                goto out;
-       }
        err = unionfs_interpose(dentry, parent->i_sb, bindex);
        if (!err) {
                fsstack_copy_attr_times(parent,
@@ -666,11 +663,10 @@ static int unionfs_mknod(struct inode *dir, struct dentry 
*dentry, int mode,
                        break;
                }
                /* update odf and remove any wh before interpose*/
-               UNIONFS_D(dentry)->odf_info =
-                       odf_lookup(dentry->d_parent, dentry, 
+               err = odf_lookup(dentry->d_parent, dentry, 
                        ODF_LOOKUP_FILE|ODF_LOOKUP_RMV_WH);
-
-               err = unionfs_interpose(dentry, dir->i_sb, 0);
+               if (!err)
+                       err = unionfs_interpose(dentry, dir->i_sb, 0);
                if (!err) {
                        fsstack_copy_attr_times(dir,
                                        hidden_parent_dentry->d_inode);
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 7ea5b60..46a9741 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -326,7 +326,7 @@ out_positive:
        BUG_ON(dentry_count <= 0);
        
        /* if what we found is a whiteout then this is really a negative dentry 
*/
-       UNIONFS_D(dentry)->odf_info = odf_lookup(dentry->d_parent, dentry, 0);
+       err = odf_lookup(dentry->d_parent, dentry, 0);
        if (UNIONFS_D(dentry)->odf_info && 
UNIONFS_D(dentry)->odf_info->whiteout){
                first_dentry_offset = -1;
                bindex = 0; /* FIXME: Always create at branch 0? can we 
guarantee that */
@@ -342,8 +342,7 @@ out_positive:
 
        /* Partial lookups need to reinterpose, or throw away older negs. */
        if (lookupmode == INTERPOSE_PARTIAL) {
-               UNIONFS_D(dentry)->odf_info = odf_lookup(
-                                       parent_dentry, dentry, 0);
+               err = odf_lookup(parent_dentry, dentry, 0);
                if (UNIONFS_D(dentry)->odf_info &&
                                UNIONFS_D(dentry)->odf_info->whiteout){
                        err = -ENOENT;
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index 3fefa3d..ed515d3 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -73,11 +73,9 @@ int unionfs_interpose(struct dentry *dentry, struct 
super_block *sb, int flag)
                ino_t ino;
                /* get unique inode number for unionfs */
                if (!UNIONFS_D(dentry)->odf_info)
-                       UNIONFS_D(dentry)->odf_info = 
-                               odf_lookup(dentry->d_parent, dentry, odf_flag);
-               if (IS_ERR(UNIONFS_D(dentry)->odf_info)){
+                       err = odf_lookup(dentry->d_parent, dentry, odf_flag);
+               if (err){
                        printk("unionfs_interpose: odf failed to create 
dentry\n");
-                       err = PTR_ERR(UNIONFS_D(dentry)->odf_info);
                        goto out;
                }
                /* check whiteouts and opaqueness */
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 9d5d11d..0340fbd 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -56,7 +56,7 @@ struct odf_dentry_info* odf_getns(void)
                odi = ERR_PTR(err);
                goto out;
        }
-       odi = odf_fill_info(nd.dentry);
+       odi = odf_fill_info(NULL, nd.dentry);
        path_release(&nd);
        
 out:
@@ -78,7 +78,7 @@ struct odf_dentry_info* odf_getrc(void)
                odi = ERR_PTR(err);
                goto out;
        }
-       odi = odf_fill_info(nd.dentry);
+       odi = odf_fill_info(NULL, nd.dentry);
        path_release(&nd);
        
 out:
@@ -151,20 +151,14 @@ int odf_rename(struct dentry *old_dentry, struct dentry 
*new_dentry)
        struct dentry *old_dir, *new_dir;
        struct dentry *old_odfdentry, *new_odfdentry;
        int err = 0;
-
-       UNIONFS_D(old_dentry)->odf_info = odf_lookup(
-                               old_dentry->d_parent,
-                               old_dentry,
-                               0);
-       UNIONFS_D(new_dentry)->odf_info = odf_lookup(
-                               new_dentry->d_parent,
-                               new_dentry,
-                               0);
+       
+       err = odf_lookup(old_dentry->d_parent, old_dentry, 0);
+       err = odf_lookup(new_dentry->d_parent, new_dentry, 0);
 
        /* if new exists, remove it */
        if (UNIONFS_D(new_dentry)->odf_info)
                err = odf_remove(new_dentry, ODF_RMV_ANY);
-               
+
        old_odfdentry = UNIONFS_D(old_dentry)->odf_info->dentry;
        old_dir = old_odfdentry->d_parent;
        new_dir = (UNIONFS_D(new_dentry->d_parent))->odf_info->dentry;
@@ -204,18 +198,27 @@ out:
  *             (useful for create where we want to rmv wh's)
  *     - ODF_LOOKUP_OPQ: if a dir is created, set it opaque (branch 0)
  */
-struct odf_dentry_info *odf_lookup(struct dentry *parent, struct dentry 
*dentry, int flags)
+int odf_lookup(struct dentry *parent, struct dentry *dentry, int flags)
 {      
-       odf_put_info(UNIONFS_D(dentry)->odf_info);
-       UNIONFS_D(dentry)->odf_info = NULL;
-       return odf_lookup_name(parent, dentry->d_name.name, dentry->d_name.len, 
flags);
+       int err = 0;
+       UNIONFS_D(dentry)->odf_info = __odf_lookup(
+                               parent, 
+                               dentry->d_name.name, 
+                               dentry->d_name.len, 
+                               flags,
+                               UNIONFS_D(dentry)->odf_info);
+       if (IS_ERR(UNIONFS_D(dentry)->odf_info)){
+               err = PTR_ERR(UNIONFS_D(dentry)->odf_info);
+               UNIONFS_D(dentry)->odf_info = NULL;
+       }
+       return err;
 }
 
-struct odf_dentry_info *odf_lookup_name(struct dentry *parent, const char 
*name, 
-                                                               int len, int 
flags)
+struct odf_dentry_info *__odf_lookup(struct dentry *parent, const char *name, 
+                                       int len, int flags,  struct 
odf_dentry_info *old_odi)
 {
        struct dentry *odf_dentry;
-       struct odf_dentry_info *odi = NULL;
+       struct odf_dentry_info *odi = old_odi;
        struct inode *odf_i_dir = UNIONFS_D(parent)->odf_info->dentry->d_inode;
        int err = 0;
        
@@ -227,17 +230,21 @@ struct odf_dentry_info *odf_lookup_name(struct dentry 
*parent, const char *name,
                && odf_dentry->d_inode 
                && (flags & ODF_LOOKUP_RMV_WH)) 
        {
-               if (odf_is_wh_i(odf_dentry->d_inode)){
+               if (__odf_is_wh(odf_dentry->d_inode)){
                        vfs_unlink(odf_i_dir, odf_dentry);
-                       dput(odf_dentry);
+                       //dput(odf_dentry);
                        odf_dentry = lookup_one_len(name,
                                UNIONFS_D(parent)->odf_info->dentry, len);
                }
        }
 
        /* create inode in odf if dont exist */
-       /* FIXME: should we fail if res is ERR? */
-       if (IS_ERR(odf_dentry) || !odf_dentry->d_inode) {
+       if (IS_ERR(odf_dentry)) {
+               odf_put_info(old_odi);
+               odi = (void*)odf_dentry;
+               goto out;
+       } 
+       if (!odf_dentry->d_inode) {
                
                if (name[0]=='.')
                        BUG_ON(len==1 || (name[1]=='.'&&len==2));
@@ -258,6 +265,7 @@ struct odf_dentry_info *odf_lookup_name(struct dentry 
*parent, const char *name,
                }
                if (err) {
                        printk(KERN_WARNING "odf_lookup: could not create odf 
dentry" );
+                       odf_put_info(old_odi);
                        odi = ERR_PTR(err); 
                        goto out;
                }
@@ -265,15 +273,15 @@ struct odf_dentry_info *odf_lookup_name(struct dentry 
*parent, const char *name,
                odf_unlock(UNIONFS_D(parent)->odf_info);
 
                /* set opaqueness to 0 or -1 */
-               odf_set_opaque_i(odf_dentry->d_inode,
+               __odf_set_opaque(odf_dentry->d_inode,
                                -!(flags & ODF_LOOKUP_OPQ));
-               odf_set_wh_i(odf_dentry->d_inode,0);
+               __odf_set_wh(odf_dentry->d_inode,0);
        }
        else {
                /* FIXME check for hardlinks */
        }
        
-       odi = odf_fill_info(odf_dentry);
+       odi = odf_fill_info(old_odi, odf_dentry);
        dput(odf_dentry); /* since we dget in fill_info */
 out:
        return odi;
@@ -289,9 +297,8 @@ int odf_create_wh(struct dentry *dentry)
        struct dentry *odf_dentry;
 
        BUG_ON(!UNIONFS_D(dentry)->odf_info);
-
        odf_dentry = UNIONFS_D(dentry)->odf_info->dentry;
-       if (odf_is_wh_i(odf_dentry->d_inode))
+       if (__odf_is_wh(odf_dentry->d_inode))
                goto out;       /* nothing to be done */        
        
        /* remove entry if existed */
@@ -300,15 +307,13 @@ int odf_create_wh(struct dentry *dentry)
                goto out;
 
        odf_put_info(UNIONFS_D(dentry)->odf_info);
+       UNIONFS_D(dentry)->odf_info = NULL;
 
        /* now create a new file and make it a whiteout */
-       UNIONFS_D(dentry)->odf_info = 
-                       odf_lookup(dentry->d_parent, 
-                       dentry, ODF_LOOKUP_FILE);
-       if (!UNIONFS_D(dentry)->odf_info){
-               err = PTR_ERR(UNIONFS_D(dentry)->odf_info); /* odf out of 
space? */
+       err = odf_lookup(dentry->d_parent, dentry, ODF_LOOKUP_FILE);
+       if (err)
                goto out;       
-       }
+       
        err = odf_set_wh(dentry,1);
 out:
        return err;
@@ -330,13 +335,13 @@ int odf_remove(struct dentry *dentry, int flags)
        BUG_ON(!UNIONFS_D(dentry)->odf_info);
        
        /* refresh odi */
-       UNIONFS_D(dentry)->odf_info = odf_lookup(dentry->d_parent, dentry, 0);
-       odi = UNIONFS_D(dentry)->odf_info;
+       err = odf_lookup(dentry->d_parent, dentry, 0);
        if (IS_ERR(odi)) {
                err = PTR_ERR(odi);
                odi = NULL;
                goto out;
        }
+       odi = UNIONFS_D(dentry)->odf_info;
        if (!odi)
                goto out;
        
@@ -359,13 +364,16 @@ int odf_remove(struct dentry *dentry, int flags)
        /* remove */
        if (S_ISDIR(odi->dentry->d_inode->i_mode))
                err = odf_reclaim(odi->dentry);
-       else
+       else {
                err = vfs_unlink(odi->dentry->d_parent->d_inode, odi->dentry);
+               if (!err)
+;//                    odi->dentry = NULL; /*so we dont dput*/ 
+       }
        if (err)
                goto out_unlock;
 
        /* clean up */
-       odf_put_info(UNIONFS_D(dentry)->odf_info);
+       odf_put_info(odi);
        UNIONFS_D(dentry)->odf_info = NULL;
 out_unlock:
        odf_unlock(odf_dir);
@@ -380,12 +388,12 @@ out:
 /* FIXME: for the following functions can we count on EXT2 to do the locking? 
*/
 int odf_set_wh(struct dentry *dentry, int boolean)
 {
-       int err = odf_set_wh_i(UNIONFS_D(dentry)->odf_info->dentry->d_inode, 
boolean);
+       int err = __odf_set_wh(UNIONFS_D(dentry)->odf_info->dentry->d_inode, 
boolean);
        if (!err) 
                UNIONFS_D(dentry)->odf_info->whiteout = boolean;
        return err;
 }
-int odf_set_wh_i(struct inode *i, int boolean)
+int __odf_set_wh(struct inode *i, int boolean)
 {
        int err = 0;
        if (boolean)
@@ -402,9 +410,9 @@ int odf_set_wh_i(struct inode *i, int boolean)
  */
 int odf_is_wh(struct dentry *dentry)
 {
-       return odf_is_wh_i(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
+       return __odf_is_wh(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
 }
-int odf_is_wh_i(struct inode *i)
+int __odf_is_wh(struct inode *i)
 {
        if (EXT2_I(i)->i_flags & ODF_WHITEOUT)
                return 1;
@@ -417,9 +425,9 @@ int odf_is_wh_i(struct inode *i)
  */
 int odf_is_opaque(struct dentry *dentry) 
 {
-       return odf_is_opaque_i(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
+       return __odf_is_opaque(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
 }
-int odf_is_opaque_i(struct inode *i) 
+int __odf_is_opaque(struct inode *i) 
 {
        if (!S_ISDIR(i->i_mode))
                return 0;
@@ -433,12 +441,12 @@ int odf_is_opaque_i(struct inode *i)
  */
 int odf_get_opaque(struct dentry *dentry) 
 {
-       return odf_get_opaque_i(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
+       return __odf_get_opaque(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
 }
-int odf_get_opaque_i(struct inode *i) 
+int __odf_get_opaque(struct inode *i) 
 {
        u32 res = 0;
-       if (!odf_is_opaque_i(i))
+       if (!__odf_is_opaque(i))
                return -1;
 
        /* get bits 26-30 */
@@ -455,13 +463,13 @@ int odf_get_opaque_i(struct inode *i)
 int odf_set_opaque(struct dentry *dentry, int branch)
 {
        struct odf_dentry_info *odi = UNIONFS_D(dentry)->odf_info;
-       int err = odf_set_opaque_i(odi->dentry->d_inode, branch);
+       int err = __odf_set_opaque(odi->dentry->d_inode, branch);
        if (!err)
                odi->opaque = branch;
        return err;
 }
 
-int odf_set_opaque_i(struct inode *i, int branch) 
+int __odf_set_opaque(struct inode *i, int branch) 
 {
        u32 b = branch;
        int err = 0;
@@ -674,18 +682,30 @@ out:
 /* 
  * Allocates an odi and fills it with inode and dentry 
  */
-struct odf_dentry_info *odf_fill_info(struct dentry *odf_dentry)
+struct odf_dentry_info *odf_alloc_info(struct dentry *odf_dentry)
 {
        struct odf_dentry_info *odi = 
                        kzalloc(sizeof(struct odf_dentry_info),GFP_KERNEL);
-       odi->whiteout = odf_is_wh_i(odf_dentry->d_inode);
-       odi->opaque = odf_get_opaque_i(odf_dentry->d_inode);
+       odi->whiteout = __odf_is_wh(odf_dentry->d_inode);
+       odi->opaque = __odf_get_opaque(odf_dentry->d_inode);
        odi->dentry = odf_dentry;
        odi->inum = odf_dentry->d_inode->i_ino;
        dget(odf_dentry);
        mutex_init(&odi->lock);
        return odi;
 }
+struct odf_dentry_info *odf_fill_info(struct odf_dentry_info *odi, struct 
dentry *odf_dentry)
+{
+       if (!odi)
+               return odf_alloc_info(odf_dentry);
+       odi->whiteout = __odf_is_wh(odf_dentry->d_inode);
+       odi->opaque = __odf_get_opaque(odf_dentry->d_inode);
+       dget(odf_dentry);
+       dput(odi->dentry);
+       odi->dentry = odf_dentry;
+       odi->inum = odf_dentry->d_inode->i_ino;
+       return odi;
+}
 
 /* 
  * Clears the odf_info data 
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index 1ec08bd..8eb89f3 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -40,10 +40,11 @@ char *odf_getoptions(void);
 int odf_putoptions(struct super_block* sb_union, struct unionfs_dentry_info 
*hidden_root);
 
 /* lookup */
-struct odf_dentry_info *odf_lookup(struct dentry *parent, struct dentry 
*dentry, int flags);
-struct odf_dentry_info *odf_lookup_name(struct dentry *parent, const char 
*name, int len, int flags);
+int odf_lookup(struct dentry *parent, struct dentry *dentry, int flags);
+struct odf_dentry_info *__odf_lookup(struct dentry *parent, const char *name, 
int len, int flags, struct odf_dentry_info *old_odi);
 struct odf_dentry_info *odf_getns(void);
-struct odf_dentry_info *odf_fill_info(struct dentry *odf_dentry);
+struct odf_dentry_info *odf_fill_info(struct odf_dentry_info *odi, struct 
dentry *odf_dentry);
+struct odf_dentry_info *odf_alloc_info(struct dentry *odf_dentry);
 void odf_put_info(struct odf_dentry_info *odi);
 
 int odf_rename(struct dentry *old_dentry, struct dentry *new_dentry);
@@ -55,17 +56,17 @@ int odf_reclaim(struct dentry *dentry);
 /* whiteouts */
 int odf_set_wh(struct dentry *dentry, int boolean);
 int odf_is_wh(struct dentry *dentry);
-int odf_set_wh_i(struct inode *i, int boolean);
-int odf_is_wh_i(struct inode *i);
+int __odf_set_wh(struct inode *i, int boolean);
+int __odf_is_wh(struct inode *i);
 int odf_create_wh(struct dentry *dentry);
 
 /* opaque */
 int odf_is_opaque(struct dentry *dentry);
 int odf_get_opaque(struct dentry *dentry);
 int odf_set_opaque(struct dentry *dentry, int branch);
-int odf_is_opaque_i(struct inode *i);
-int odf_get_opaque_i(struct inode *i);
-int odf_set_opaque_i(struct inode *i, int branch);
+int __odf_is_opaque(struct inode *i);
+int __odf_get_opaque(struct inode *i);
+int __odf_set_opaque(struct inode *i, int branch);
 
 /* Macros for locking an odf dentry info. */
 static inline void odf_lock(struct odf_dentry_info *odi)
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to