commit 79791573c46b079ebd621a953b1e26d9613b68c7
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Sun Mar 25 20:10:40 2007 -0400

    fixed opaqueness with remounts
    
    store opaque branch no in gid instead of inode flags
    removed old dbopaque code

diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
index eba60ca..8da5161 100644
--- a/fs/unionfs/commonfops.c
+++ b/fs/unionfs/commonfops.c
@@ -168,8 +168,8 @@ int unionfs_silly_rename(struct dentry *dentry, struct 
dentry *hidden_dentry)
                goto out;
        
        /* create a whiteout */
-       odi = __odf_lookup(UNIONFS_D(dentry->d_parent)->odf_info,
-                               UNIONFS_SB(dentry->d_sb)->odf, 
+       odi = __odf_lookup(UNIONFS_SB(dentry->d_sb)->odf, 
+                               UNIONFS_D(dentry->d_parent)->odf_info,
                                name, strlen(name), ODF_LOOKUP_WH, odi);
        BUG_ON(IS_ERR(odi) || odi == NULL);
 out:
diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index f8d12ff..af7bd82 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -116,8 +116,8 @@ static int readdir_util_callback(void *dirent, const char 
*name, int namelen,
        }
        
        /* check odf */
-       odi = __odf_lookup(UNIONFS_D(buf->dir)->odf_info, 
-                       UNIONFS_SB(buf->dir->d_sb)->odf,
+       odi = __odf_lookup(UNIONFS_SB(buf->dir->d_sb)->odf,
+                       UNIONFS_D(buf->dir)->odf_info, 
                        name, namelen, create_flag | ODF_LOOKUP_LOCKED, 0);
        if (IS_ERR(odi)){
                odi = NULL;
@@ -169,7 +169,7 @@ int check_empty(struct dentry *dentry, struct 
unionfs_dir_state **namelist)
 
        bstart = dbstart(dentry);
        bend = dbend(dentry);
-       bopaque = dbopaque(dentry);
+       bopaque = odf_get_opaque(sb, dentry);
        if (0 <= bopaque && bopaque < bend)
                bend = bopaque;
 
@@ -298,7 +298,7 @@ retry:
 
        bstart = dbstart(d_upper);
        bend = dbend(d_upper);
-       bopaque = dbopaque(d_upper);
+       bopaque = odf_get_opaque(sb, d_upper);
        if (0 <= bopaque && bopaque < bend)
                bend = bopaque;
 
diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
index 9e4a35f..a570c19 100644
--- a/fs/unionfs/fanout.h
+++ b/fs/unionfs/fanout.h
@@ -170,16 +170,6 @@ static inline void set_dbend(struct dentry *dent, int val)
        UNIONFS_D(dent)->bend = val;
 }
 
-static inline int dbopaque(const struct dentry *dent)
-{
-       return UNIONFS_D(dent)->bopaque;
-}
-
-static inline void set_dbopaque(struct dentry *dent, int val)
-{
-       UNIONFS_D(dent)->bopaque = val;
-}
-
 static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index,
                                   struct dentry *val)
 {
diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
index 17d37da..9dc02f6 100644
--- a/fs/unionfs/lookup.c
+++ b/fs/unionfs/lookup.c
@@ -75,7 +75,7 @@ struct dentry *unionfs_lookup_backend(struct dentry *dentry, 
struct nameidata *n
        /* Now start the actual lookup procedure. */
        bstart = dbstart(parent_dentry);
        bend = dbend(parent_dentry);
-       bopaque = dbopaque(parent_dentry);
+       bopaque = odf_get_opaque(parent_dentry->d_sb, parent_dentry);
        BUG_ON(bstart < 0);
        
        if (nd == NULL){ 
@@ -385,7 +385,6 @@ int new_dentry_private_data(struct dentry *dentry)
 
        info->bstart = -1;
        info->bend = -1;
-       info->bopaque = -1;
        info->bcount = sbmax(dentry->d_sb);
        info->odf_info = NULL;
        atomic_set(&info->generation,
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index 46a088d..c8749af 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -84,11 +84,9 @@ int unionfs_interpose(struct dentry *dentry, struct 
super_block *sb, int flag)
                        err = -ENOENT;
                        goto out;
                }               
-               opaque = UNIONFS_D(dentry)->odf_info->opaque;
-               if (opaque >= 0){
+               opaque = odf_get_opaque(sb, dentry);
+               if (opaque >= 0)
                        set_dbend(dentry, opaque);
-                       set_dbopaque(dentry, opaque);
-               }
 
                ino = UNIONFS_D(dentry)->odf_info->inum;
 
@@ -419,7 +417,6 @@ static struct unionfs_dentry_info 
*unionfs_parse_options(struct super_block *sb,
                goto out_error;
        hidden_root_info->bstart = -1;
        hidden_root_info->bend = -1;
-       hidden_root_info->bopaque = -1;
 
        while ((optname = strsep(&options, ",")) != NULL) {
                char *optarg;
@@ -637,13 +634,14 @@ static int unionfs_read_super(struct super_block *sb, 
void *raw_data,
                        /* we need to update the branch ids to whatever was 
stored in
                         * the odf and set high_branch_id to the greatest
                         */
-                       UNIONFS_SB(sb)->data[bindex].branch_id = bid[bindex];
+                       set_branch_id(sb, bindex, bid[bindex]);
                        if (bid[bindex] > high_bid)
                                high_bid = bid[bindex];
                }
        }
        if (high_bid > UNIONFS_SB(sb)->high_branch_id)
                 UNIONFS_SB(sb)->high_branch_id = high_bid;
+       UNIONFS_SB(sb)->odf->opaque_branch_id = branch_id(sb, 0);
 
        /* Unionfs: Max Bytes is the maximum bytes from highest priority branch 
*/
        unionfs_read_lock(sb);
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 9d9d6ce..3918c4c 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -367,8 +367,8 @@ int odf_lookup(struct dentry *parent, struct dentry 
*dentry, int flags)
 {      
        int err = 0;
        UNIONFS_D(dentry)->odf_info = __odf_lookup(
-                               UNIONFS_D(parent)->odf_info,
                                UNIONFS_SB(dentry->d_sb)->odf,
+                               UNIONFS_D(parent)->odf_info,
                                dentry->d_name.name,
                                dentry->d_name.len,
                                flags,
@@ -380,7 +380,7 @@ int odf_lookup(struct dentry *parent, struct dentry 
*dentry, int flags)
        return err;
 }
 
-struct odf_dentry_info *__odf_lookup(struct odf_dentry_info *parent, struct 
odf_sb_info *osi, const char *name, 
+struct odf_dentry_info *__odf_lookup(struct odf_sb_info *osi, struct 
odf_dentry_info *parent, const char *name, 
                                        int len, int flags,  struct 
odf_dentry_info *old_odi)
 {
        struct dentry *odf_dentry;
@@ -482,7 +482,7 @@ retry:
                }
 
                /* set opaqueness to 0 or -1 */
-               opaque = (flags & ODF_LOOKUP_OPQ) ? 0 : -1;
+               opaque = (flags & ODF_LOOKUP_OPQ) ? osi->opaque_branch_id : -1;
                whiteout = (flags & ODF_LOOKUP_WH) ? 1 : 0;
                __odf_set_opaque(odf_dentry->d_inode, opaque);
                __odf_set_wh(odf_dentry->d_inode,whiteout);
@@ -531,7 +531,7 @@ struct odf_dentry_info *odf_ic_dir(struct dentry *dir)
 
        memset(name,0,6);
        sprintf(name, "%x", breakdown[0]);
-       odis[0] = __odf_lookup(odi_ic, osi, name, strlen(name), ODF_LOOKUP_DIR, 
NULL);
+       odis[0] = __odf_lookup(osi, odi_ic, name, strlen(name), ODF_LOOKUP_DIR, 
NULL);
        if (IS_ERR(odis[0])) {
                err = PTR_ERR(odis[0]);
                odis[0] = NULL;
@@ -540,7 +540,7 @@ struct odf_dentry_info *odf_ic_dir(struct dentry *dir)
        for (i = 1; i < 4; i++) {
                memset(name,0,6);
                sprintf(name, "%x", breakdown[i]);
-               odis[i] = __odf_lookup(odis[i-1], osi, name, strlen(name), 
ODF_LOOKUP_DIR, NULL);
+               odis[i] = __odf_lookup(osi, odis[i-1], name, strlen(name), 
ODF_LOOKUP_DIR, NULL);
                if (IS_ERR(odis[i])) {
                        err = PTR_ERR(odis[i]);
                        odis[i] = NULL;
@@ -548,7 +548,7 @@ struct odf_dentry_info *odf_ic_dir(struct dentry *dir)
                }
        }
        
-       odi_ret = __odf_lookup(odis[3], osi, ODF_CONTENT, ODF_CONTENT_LEN, 
ODF_LOOKUP_FILE, NULL);
+       odi_ret = __odf_lookup(osi, odis[3], ODF_CONTENT, ODF_CONTENT_LEN, 
ODF_LOOKUP_FILE, NULL);
        if (IS_ERR(odi_ret)) {
                err = PTR_ERR(odi_ret);
                odi_ret = NULL;
@@ -855,6 +855,31 @@ int odf_is_opaque(struct dentry *dentry)
 {
        return __odf_is_opaque(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
 }
+
+/* The opaque number stored with the odf inode is that of the branch id
+ * which is not necessarily the same as the branch position, so we need to
+ * convert the branch id to the branch position
+ */
+int odf_get_opaque(struct super_block *sb, struct dentry *dentry) 
+{
+       int i, opaque = UNIONFS_D(dentry)->odf_info->opaque;
+       
+       if (opaque == -1)
+               return -1;
+
+       /* now check all branches for the branch id */
+       for (i = 0; i < sbmax(sb); i++) {
+               if (branch_id(sb, i) == opaque)
+                       return i;
+       }
+
+       /* if this is reached then the opaque branch was deleted, so dentry
+        * can no longer be considered opaque
+        */
+       odf_set_opaque(dentry, -1);
+       return -1;
+}
+
 int __odf_is_opaque(struct inode *i) 
 {
        if (!S_ISDIR(i->i_mode))
@@ -863,25 +888,16 @@ int __odf_is_opaque(struct inode *i)
                return 1;
        return 0;
 }
+
 /*
- * Gets opaque branch of a dentry, -1 if not opaque
- * The dentry version takes a UnionFS dentry, the inode one an ODF inode
+ * Gets opaque branch id from an inode, -1 if not opaque
  */
-int odf_get_opaque(struct dentry *dentry) 
-{
-       return __odf_get_opaque(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
-}
 int __odf_get_opaque(struct inode *i) 
 {
-       u32 res = 0;
        if (!__odf_is_opaque(i))
                return -1;
 
-       /* get bits 26-30 */
-       res = EXT2_I(i)->i_flags;
-       res <<= 1;
-       res >>= (ODF_OPQ_BASE + 1);
-       return res;
+       return i->i_gid;
 }
 
 /*
@@ -899,14 +915,12 @@ int odf_set_opaque(struct dentry *dentry, int branch)
 
 int __odf_set_opaque(struct inode *i, int branch) 
 {
-       u32 b = branch;
        int err = 0;
        if (branch < 0)
                EXT2_I(i)->i_flags &= ~ODF_OPAQUE;
        else {
-               b <<= ODF_OPQ_BASE + 1;
-               b >>= 1;
-               EXT2_I(i)->i_flags |= (ODF_OPAQUE|b);
+               EXT2_I(i)->i_flags |= ODF_OPAQUE;
+               i->i_gid = branch;
        }
        err = ext2_write_inode(i, 1);
        return err;
@@ -982,15 +996,6 @@ int odf_write_sb_data(struct odf_sb_info* osi, struct 
unionfs_data *data, struct
        d_odf_sb = osi->odi_sb->dentry;
        odf_mnt = osi->mnt;
 
-       /* check the number of branches */
-       if (branches >= (1 << ODF_OPQ_BITS)) {
-               printk(KERN_WARNING "unionfs: too many branches (%d), "
-                       "odf can only support %d branches\n",
-                       branches, (1 << ODF_OPQ_BITS) - 1);
-               err = -EINVAL;
-               goto out;
-       }
-
        d_content = lookup_one_len(ODF_CONTENT, d_odf_sb, ODF_CONTENT_LEN);
        if (IS_ERR(d_content) || !d_content) {
                err = -EINVAL;
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index fee8a1a..bcb8bb9 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -35,8 +35,6 @@
 /* Inode flags */ 
 #define ODF_WHITEOUT FS_SECRM_FL //0x01000000
 #define ODF_OPAQUE FS_COMPR_FL // 0x02000000
-#define ODF_OPQ_BASE 26 /* 0x04000000, bits 26 - 30 */
-#define ODF_OPQ_BITS 5
 
 #define ODF_DIRENT_MAGIC 0x0DFD1300
 
@@ -60,7 +58,7 @@ int odf_is_odf(struct dentry *d_odf);
 
 /* lookup */
 int odf_lookup(struct dentry *parent, struct dentry *dentry, int flags);
-struct odf_dentry_info *__odf_lookup(struct odf_dentry_info *parent, struct 
odf_sb_info *osi, const char *name, int len, int flags, struct odf_dentry_info 
*old_odi);
+struct odf_dentry_info *__odf_lookup(struct odf_sb_info *osi, struct 
odf_dentry_info *parent, const char *name, int len, int flags, struct 
odf_dentry_info *old_odi);
 
 struct odf_dentry_info *odf_getpath(struct dentry *d_odf, struct odf_sb_info 
*osi, const char *name);
 struct odf_dentry_info *odf_fill_info(struct odf_dentry_info *odi, struct 
odf_sb_info *osi, struct dentry *odf_dentry);
@@ -90,7 +88,7 @@ int odf_create_wh(struct dentry *dentry);
 
 /* opaque */
 int odf_is_opaque(struct dentry *dentry);
-int odf_get_opaque(struct dentry *dentry);
+int odf_get_opaque(struct super_block *sb, struct dentry *dentry);
 int odf_set_opaque(struct dentry *dentry, int branch);
 int __odf_is_opaque(struct inode *i);
 int __odf_get_opaque(struct inode *i);
diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
index ef8dac5..aa3de7a 100644
--- a/fs/unionfs/rename.c
+++ b/fs/unionfs/rename.c
@@ -140,7 +140,7 @@ static int do_unionfs_rename(struct inode *old_dir,
        int local_err = 0;
        int eio = 0;
        int revert = 0;
-       int new_opaque = UNIONFS_D(new_dentry->d_parent)->odf_info->opaque;
+       int new_opaque;
 
        old_bstart = dbstart(old_dentry);
        old_bend = dbend(old_dentry);
@@ -148,6 +148,7 @@ static int do_unionfs_rename(struct inode *old_dir,
 
        new_bstart = dbstart(new_dentry);
        new_bend = dbend(new_dentry);
+       new_opaque = odf_get_opaque(new_dentry->d_parent->d_sb, 
new_dentry->d_parent);
 
        if (new_bstart == new_bend &&  new_bstart == 0) {
                if (!unionfs_lower_dentry_idx(new_dentry, 0) ||
@@ -295,7 +296,7 @@ static int may_rename_dir(struct dentry *dentry)
                return err;
 
        bstart = dbstart(dentry);
-       if (dbend(dentry) == bstart || dbopaque(dentry) == bstart)
+       if (dbend(dentry) == bstart || odf_get_opaque(dentry->d_sb, dentry) == 
bstart)
                return 0;
 
        set_dbstart(dentry, bstart + 1);
diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
index 352a6db..510b81a 100644
--- a/fs/unionfs/super.c
+++ b/fs/unionfs/super.c
@@ -683,6 +683,7 @@ out_no_change:
                        new_branches);
        if (err)
                goto out_release;
+        UNIONFS_SB(sb)->odf->opaque_branch_id = new_data[0].branch_id;
 
        /*
         * OK, just before we actually put the new set of branches in place,
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 2752479..d5fc263 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -108,6 +108,7 @@ struct odf_sb_info {
        struct odf_dentry_info *odi_rc;
        struct odf_dentry_info *odi_ic;
        struct sioa_args *cleanup;
+       int opaque_branch_id; /* should always be the branch id of branch 0*/
 };
 
 /* unionfs inode data in memory */
@@ -140,7 +141,6 @@ struct unionfs_dentry_info {
        struct mutex lock;
        int bstart;
        int bend;
-       int bopaque;
        int bcount;
        atomic_t generation;
        struct odf_dentry_info *odf_info;
diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
index 14d513e..a6861da 100644
--- a/fs/unionfs/unlink.c
+++ b/fs/unionfs/unlink.c
@@ -78,7 +78,7 @@ out:
                dentry->d_inode->i_nlink--;
 
        /* We don't want to leave negative leftover dentries for revalidate. */
-       if (!err && (dbopaque(dentry) != -1))
+       if (!err && (odf_get_opaque(dentry->d_sb,dentry) != -1))
                update_bstart(dentry);
 
        return err;
@@ -147,7 +147,7 @@ static int unionfs_do_rmdir(struct inode *dir, struct 
dentry *dentry)
                        break;
        }
        /* FIXME: create wh for opaque dirs as well? or force to check all 
branches? */
-       if (err || dbopaque(dentry) != 1) {
+       if (err || odf_get_opaque(dentry->d_sb, dentry) != 1) {
                if (err == -EIO)
                        printk(KERN_WARNING 
                                "unionfs_rmdir: IO error removing from branch 
%d\n",
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to