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