commit d0f64f007f50c13644be84b88247bae4a25c3ad8
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Wed Feb 7 21:59:53 2007 -0500

    Opaqueness and mkdir

diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index 303ef86..6caf0e3 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -500,122 +500,78 @@ out:
 static int unionfs_mkdir(struct inode *parent, struct dentry *dentry, int mode)
 {
        int err = 0;
-       struct dentry *hidden_dentry = NULL, *whiteout_dentry = NULL;
+       struct dentry *hidden_dentry = NULL;
        struct dentry *hidden_parent_dentry = NULL;
-       int bindex = 0, bstart;
        char *name = NULL;
-       int whiteout_unlinked = 0;
-       struct sioq_args args;
+       int i, bend, bindex;
 
        BUG_ON(!is_valid_dentry(dentry));
 
        unionfs_lock_dentry(dentry);
-       bstart = dbstart(dentry);
+       bindex = 0; /* always create at branch 0 */
+       bend = dbend(dentry);
 
-       hidden_dentry = unionfs_lower_dentry(dentry);
-
-       /* check if whiteout exists in this branch, i.e. lookup .wh.foo first */
-       name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
-       if (IS_ERR(name)) {
-               err = PTR_ERR(name);
+       if (is_robranch_super(dentry->d_sb, bindex)){
+               err = -EROFS;
                goto out;
        }
-
-       whiteout_dentry = lookup_one_len(name, hidden_dentry->d_parent,
-                          dentry->d_name.len + UNIONFS_WHLEN);
-       if (IS_ERR(whiteout_dentry)) {
-               err = PTR_ERR(whiteout_dentry);
-               goto out;
-       }
-
-       if (!whiteout_dentry->d_inode) {
-               dput(whiteout_dentry);
-               whiteout_dentry = NULL;
-       } else {
-               hidden_parent_dentry = lock_parent(whiteout_dentry);
-
-               /* found a.wh.foo entry, remove it then do vfs_mkdir */
-               if (!(err = is_robranch_super(dentry->d_sb, bstart))) {
-                       args.unlink.parent = hidden_parent_dentry->d_inode;
-                       args.unlink.dentry = whiteout_dentry;
-                       run_sioq(__unionfs_unlink, &args);
-                       err = args.err;
+       hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+       if (!hidden_dentry) {
+               hidden_dentry = create_parents(parent, dentry, bindex);
+               if (!hidden_dentry || IS_ERR(hidden_dentry)) {
+                       printk(KERN_DEBUG "hidden dentry NULL for "
+                               "bindex = %d\n", bindex);
+                       err = PTR_ERR(hidden_dentry);
+                       goto out;;
                }
-               dput(whiteout_dentry);
-
-               unlock_dir(hidden_parent_dentry);
-
-               if (err) {
-                       /* exit if the error returned was NOT -EROFS */
-                       if (!IS_COPYUP_ERR(err))
-                               goto out;
-                       bstart--;
-               } else
-                       whiteout_unlinked = 1;
        }
 
-       for (bindex = bstart; bindex >= 0; bindex--) {
-               int i;
-               int bend = dbend(dentry);
-
-               if (is_robranch_super(dentry->d_sb, bindex))
-                       continue;
-
-               hidden_dentry = unionfs_lower_dentry_idx(dentry, bindex);
-               if (!hidden_dentry) {
-                       hidden_dentry = create_parents(parent, dentry, bindex);
-                       if (!hidden_dentry || IS_ERR(hidden_dentry)) {
-                               printk(KERN_DEBUG "hidden dentry NULL for "
-                                       "bindex = %d\n", bindex);
-                               continue;
-                       }
-               }
-
-               hidden_parent_dentry = lock_parent(hidden_dentry);
+       hidden_parent_dentry = lock_parent(hidden_dentry);
 
-               if (IS_ERR(hidden_parent_dentry)) {
-                       err = PTR_ERR(hidden_parent_dentry);
-                       goto out;
-               }
-
-               err = vfs_mkdir(hidden_parent_dentry->d_inode, hidden_dentry, 
mode);
-
-               unlock_dir(hidden_parent_dentry);
-
-               /* did the mkdir suceed? */
-               if (err)
-                       break;
+       if (IS_ERR(hidden_parent_dentry)) {
+               err = PTR_ERR(hidden_parent_dentry);
+               goto out;
+       }
 
-               for (i = bindex + 1; i < bend; i++) {
-                       if (unionfs_lower_dentry_idx(dentry, i)) {
-                               dput(unionfs_lower_dentry_idx(dentry, i));
-                               unionfs_set_lower_dentry_idx(dentry, i, NULL);
-                       }
-               }
-               set_dbend(dentry, bindex);
+       err = vfs_mkdir(hidden_parent_dentry->d_inode, hidden_dentry, mode);
 
-               err = unionfs_interpose(dentry, parent->i_sb, 0);
-               if (!err) {
-                       fsstack_copy_attr_times(parent,
-                                       hidden_parent_dentry->d_inode);
-                       fsstack_copy_inode_size(parent,
-                                       hidden_parent_dentry->d_inode);
+       unlock_dir(hidden_parent_dentry);
 
-                       /* update number of links on parent directory */
-                       parent->i_nlink = unionfs_get_nlinks(parent);
+       /* did the mkdir suceed? */
+       if (err)
+               goto out;
+       
+       /* update number of links on parent directory */
+       parent->i_nlink = unionfs_get_nlinks(parent);
+       
+       for (i = bindex + 1; i < bend; i++) {
+               if (unionfs_lower_dentry_idx(dentry, i)) {
+                       dput(unionfs_lower_dentry_idx(dentry, i));
+                       unionfs_set_lower_dentry_idx(dentry, i, NULL);
                }
+       }
 
-               err = make_dir_opaque(dentry, dbstart(dentry));
-               if (err) {
-                       printk(KERN_ERR "mkdir: error creating "
-                               ".wh.__dir_opaque: %d\n", err);
-                       goto out;
-               }
+       set_dbend(dentry, bindex);
 
-               /* we are done! */
-               break;
+       /* add to odf with opaque branch set to 0 */
+       UNIONFS_D(dentry)->odf_info =
+               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);
+               goto out;
        }
-
+       err = unionfs_interpose(dentry, parent->i_sb, bindex);
+       if (!err) {
+               fsstack_copy_attr_times(parent,
+                               hidden_parent_dentry->d_inode);
+               fsstack_copy_inode_size(parent,
+                               hidden_parent_dentry->d_inode);
+
+               /* update number of links on parent directory */
+               parent->i_nlink = unionfs_get_nlinks(parent);
+       }
+       
 out:
        if (!dentry->d_inode)
                d_drop(dentry);
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 59532ee..7ea5b60 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -368,7 +368,7 @@ out_positive:
        if (err)
                goto out_drop;
 
-       /* check for whiteout */
+       /* check for whiteout && opaqueness */
        if (UNIONFS_D(dentry)->odf_info) {
                if (UNIONFS_D(dentry)->odf_info->whiteout){
                        err = -ENOENT;
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index 415a744..3fefa3d 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -29,6 +29,7 @@ int unionfs_interpose(struct dentry *dentry, struct 
super_block *sb, int flag)
        struct inode *inode;
        int is_negative_dentry = 1, odf_flag = ODF_LOOKUP_FILE;
        int bindex, bstart, bend;
+       int opaque;
 
        verify_locked(dentry);
 
@@ -79,11 +80,17 @@ int unionfs_interpose(struct dentry *dentry, struct 
super_block *sb, int flag)
                        err = PTR_ERR(UNIONFS_D(dentry)->odf_info);
                        goto out;
                }
+               /* check whiteouts and opaqueness */
                if (UNIONFS_D(dentry)->odf_info->whiteout){
                        err = -ENOENT;
                        goto out;
+               }               
+               opaque = UNIONFS_D(dentry)->odf_info->opaque;
+               if (opaque >= 0){
+                       set_dbend(dentry, opaque);
+                       set_dbopaque(dentry, opaque);
                }
-               
+
                ino = UNIONFS_D(dentry)->odf_info->inum;
 
                inode = iget(sb, ino);
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index a864b96..546cfea 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -212,7 +212,7 @@ 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,
                                -!(flags & ODF_LOOKUP_OPQ));
@@ -280,12 +280,14 @@ int odf_remove(struct dentry *dentry, int flags)
        
        /* refresh odi */
        UNIONFS_D(dentry)->odf_info = odf_lookup(dentry->d_parent, dentry, 0);
-       odi =  UNIONFS_D(dentry)->odf_info;
-       if (IS_ERR(odi) || !odi) {
+       odi = UNIONFS_D(dentry)->odf_info;
+       if (IS_ERR(odi)) {
+               err = PTR_ERR(odi);
                odi = NULL;
-               err = -ENOENT;
                goto out;
        }
+       if (!odi)
+               goto out;
        
        /* should we remove? */
        if (odf_is_wh(dentry)) {
@@ -313,7 +315,7 @@ int odf_remove(struct dentry *dentry, int flags)
 
        /* clean up */
        odf_put_info(UNIONFS_D(dentry)->odf_info);
-
+       UNIONFS_D(dentry)->odf_info = NULL;
 out_unlock:
        odf_unlock(odf_dir);
 out:
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index 004ebe2..7c2976e 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -68,12 +68,12 @@ int odf_set_opaque_i(struct inode *i, int branch);
 /* Macros for locking an odf dentry info. */
 static inline void odf_lock(struct odf_dentry_info *odi)
 {
-        mutex_lock(&odi->lock);
+       mutex_lock(&odi->lock);
 }
 
 static inline void odf_unlock(struct odf_dentry_info *odi)
 {
-        mutex_unlock(&odi->lock);
+       mutex_unlock(&odi->lock);
 }
 
 
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
index 8224d11..ce1dee8 100644
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -54,7 +54,9 @@ static int unionfs_do_unlink(struct inode *dir, struct dentry 
*dentry)
 
        if (err) {
                if (err == -EIO)
-                       printk(KERN_WARNING "unionfs_unlink: IO error unlinking 
from branch %d\n", bindex);
+                       printk(KERN_WARNING 
+                               "unionfs_unlink: IO error unlinking from branch 
%d\n", 
+                               bindex);
                err = odf_create_wh(dentry);
        }
 
@@ -130,9 +132,12 @@ static int unionfs_do_rmdir(struct inode *dir, struct 
dentry *dentry)
                if (err)
                        break;
        }
-       if (err) {
+       /* FIXME: create wh for opaque dirs as well? or force to check all 
branches? */
+       if (err || dbopaque(dentry) != 1) {
                if (err == -EIO)
-                       printk(KERN_WARNING "unionfs_unlink: IO error unlinking 
from branch %d\n", bindex);
+                       printk(KERN_WARNING 
+                               "unionfs_unlink: IO error unlinking from branch 
%d\n",
+                               bindex);
                err = odf_create_wh(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