commit 6b1e537d50e76c03a4d8b23b60a0b9e9bcb2cc14
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date: Tue Apr 10 13:36:47 2007 -0400
whiteouts as hardlinks, removed ext2 dependancy
diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
index 3a52717..167e74f 100644
--- a/fs/unionfs/Makefile
+++ b/fs/unionfs/Makefile
@@ -3,6 +3,6 @@ obj-$(CONFIG_UNION_FS) += unionfs.o
unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
branchman.o rdstate.o copyup.o dirhelper.o rename.o \
unlink.o lookup.o commonfops.o dirfops.o sioq.o odf.o \
- config.o ../ext2/ext2.o
+ config.o
unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
index ce67381..7fe6728 100644
--- a/fs/unionfs/copyup.c
+++ b/fs/unionfs/copyup.c
@@ -435,7 +435,7 @@ static int copyup_named_dentry(struct inode *dir, struct
dentry *dentry,
if (!d_deleted(dentry))
unionfs_reinterpose(dentry);
- err = odf_copyup_link(sb, old_hidden_dentry, new_hidden_dentry,
old_bindex, new_bindex);
+// err = odf_copyup_link(sb, old_hidden_dentry, new_hidden_dentry,
old_bindex, new_bindex);
goto out_unlock;
/****/
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 3a545ef..867099b 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -39,26 +39,36 @@ struct odf_sb_info* odf_read_super(char *options)
err = PTR_ERR(osi->odi_ns);
osi->odi_ns = NULL;
goto out_free;
- }
+ }
osi->odi_sb = odf_getpath(nd.dentry, osi, ODF_SB);
if (IS_ERR(osi->odi_sb)){
err = PTR_ERR(osi->odi_sb);
osi->odi_sb = NULL;
goto out_free;
- }
+ }
osi->odi_rc = odf_getpath(nd.dentry, osi, ODF_RC);
if (IS_ERR(osi->odi_rc)){
err = PTR_ERR(osi->odi_rc);
osi->odi_rc = NULL;
goto out_free;
- }
+ }
osi->odi_ic = odf_getpath(nd.dentry, osi, ODF_IC);
if (IS_ERR(osi->odi_ic)){
err = PTR_ERR(osi->odi_ic);
osi->odi_ic = NULL;
goto out_free;
- }
-
+ }
+ osi->whiteout = lookup_one_len(ODF_WH_NAME, osi->odi_sb->dentry,
ODF_WH_LEN);
+ if (IS_ERR(osi->whiteout)) {
+ err = PTR_ERR(osi->whiteout);
+ osi->whiteout = NULL;
+ goto out_free;
+ }
+ if (!osi->whiteout->d_inode) {
+ err = vfs_create(osi->odi_sb->dentry->d_inode, osi->whiteout,
S_IRWXUGO, NULL );
+ if (err)
+ goto out_free;
+ }
/* start the reclaim sioa */
sioa = kmalloc(sizeof(struct sioa_args), GFP_KERNEL);
if (!sioa) {
@@ -80,6 +90,7 @@ out_free:
odf_put_info(osi->odi_rc);
odf_put_info(osi->odi_sb);
odf_put_info(osi->odi_ic);
+ dput(osi->whiteout);
kfree(osi->branch_uuids);
kfree(osi);
osi = ERR_PTR(err);
@@ -101,6 +112,7 @@ void odf_put_super(struct odf_sb_info *osi)
odf_put_info(osi->odi_sb);
odf_put_info(osi->odi_ic);
dput(osi->mnt->mnt_sb->s_root);
+ dput(osi->whiteout);
mntput(osi->mnt);
if (osi->cleanup)
complete_sioa(osi->cleanup);
@@ -851,7 +863,7 @@ struct odf_dentry_info *__odf_lookup(struct odf_sb_info
*osi,
struct dentry *odf_dentry;
struct odf_dentry_info *odi = old_odi;
struct inode *odf_i_dir = parent->dentry->d_inode;
- int opaque, whiteout, err = 0, cleaned = 0;
+ int opaque, err = 0, cleaned = 0;
uid_t olduid;
gid_t oldgid;
@@ -870,16 +882,16 @@ struct odf_dentry_info *__odf_lookup(struct odf_sb_info
*osi,
/* if create flags are set, remove existing whiteout */
if (odf_dentry->d_inode && (flags & ODF_LOOKUP_RMV_WH)) {
- if (__odf_is_wh(odf_dentry->d_inode)){
+ if (__odf_is_wh(osi, odf_dentry)){
vfs_unlink(odf_i_dir, odf_dentry);
dput(odf_dentry);
odf_dentry = lookup_one_len(name, parent->dentry, len);
}
}
- /* if we should not lookup_wh if a non-wh entry exists */
+ /* we should not lookup_wh if a non-wh entry exists */
if (flags & ODF_LOOKUP_WH)
- BUG_ON(odf_dentry->d_inode &&
!__odf_is_wh(odf_dentry->d_inode));
+ BUG_ON(odf_dentry->d_inode && !__odf_is_wh(osi, odf_dentry));
/* create inode in odf if dont exist */
if (!odf_dentry->d_inode) {
@@ -901,13 +913,18 @@ retry:
if (link && (flags & (ODF_LOOKUP_FILE | ODF_LOOKUP_LINK))) {
/* link to the given dentry */
- vfs_link(link, parent->dentry->d_inode, odf_dentry);
+ vfs_link(link, odf_dentry->d_parent->d_inode,
odf_dentry);
}
- else if (flags & ODF_LOOKUP_FILE || flags & ODF_LOOKUP_WH) {
+ else if (flags & ODF_LOOKUP_FILE) {
current->fsuid = 0;
current->fsgid = 0;
err = vfs_create(odf_i_dir, odf_dentry, S_IRWXUGO, 0 );
}
+ else if (flags & ODF_LOOKUP_WH) {
+ current->fsuid = 0;
+ current->fsgid = 0;
+ err = vfs_link(osi->whiteout, odf_i_dir, odf_dentry);
+ }
else if (flags & ODF_LOOKUP_DIR) {
current->fsuid = 0;
current->fsgid = 0;
@@ -953,9 +970,7 @@ retry:
/* set opaqueness to 0 or -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);
}
else {
/* hardlinks, check if link inode is same as odf_dentry inode,
@@ -1205,20 +1220,18 @@ int odf_create_wh(struct dentry *dentry)
struct dentry *odf_dentry;
if (UNIONFS_D(dentry)->odf_info) {
odf_dentry = UNIONFS_D(dentry)->odf_info->dentry;
- if (__odf_is_wh(odf_dentry->d_inode))
+ if (__odf_is_wh(UNIONFS_D(dentry)->odf_info->osi, odf_dentry))
goto out; /* nothing to be done */
-
/* remove entry if existed */
err = odf_remove(dentry, ODF_RMV_ANY);
if (err)
goto out;
}
/* now create a new file and make it a whiteout */
- err = odf_lookup(dentry->d_parent, dentry, ODF_LOOKUP_FILE);
+ err = odf_lookup(dentry->d_parent, dentry, ODF_LOOKUP_WH);
+
if (err)
goto out;
-
- err = odf_set_wh(dentry,1);
odf_put_info(UNIONFS_D(dentry)->odf_info);
UNIONFS_D(dentry)->odf_info = NULL;
out:
@@ -1245,14 +1258,12 @@ int odf_remove(struct dentry *dentry, int flags)
odi = NULL;
goto out;
}
-
BUG_ON(!UNIONFS_D(dentry)->odf_info);
odi = UNIONFS_D(dentry)->odf_info;
if (!odi)
goto out;
-
/* should we remove? */
- if (odf_is_wh(dentry)) {
+ if (__odf_is_wh(odi->osi, odi->dentry)) {
if (flags & ODF_RMV_WH)
rmv = 1;
}
@@ -1260,7 +1271,6 @@ int odf_remove(struct dentry *dentry, int flags)
if (flags & ODF_RMV_NOTWH)
rmv = 1;
}
-
if (!rmv)
goto out;
@@ -1272,7 +1282,6 @@ int odf_remove(struct dentry *dentry, int flags)
err = odf_reclaim(dentry);
else
err = vfs_unlink(odi->dentry->d_parent->d_inode, odi->dentry);
-
if (err)
goto out_unlock;
@@ -1285,53 +1294,6 @@ out:
return err;
}
-/*
- * Sets the whiteout flag, the boolean decides whether to set whiteout on/off
- * The dentry version takes a UnionFS dentry, the inode one an ODF inode
- */
-/* 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(UNIONFS_D(dentry)->odf_info->dentry->d_inode,
boolean);
- if (!err)
- UNIONFS_D(dentry)->odf_info->whiteout = boolean;
- return err;
-}
-int __odf_set_wh(struct inode *i, int boolean)
-{
- int err = 0;
- if (boolean)
- EXT2_I(i)->i_flags |= ODF_WHITEOUT;
- else
- EXT2_I(i)->i_flags &= ~ODF_WHITEOUT;
- err = ext2_write_inode(i, 1);
- return err;
-}
-
-/*
- * Checks if the whiteout flag is set for a dentry
- * The dentry version takes a UnionFS dentry, the inode one an ODF inode
- */
-int odf_is_wh(struct dentry *dentry)
-{
- return __odf_is_wh(UNIONFS_D(dentry)->odf_info->dentry->d_inode);
-}
-int __odf_is_wh(struct inode *i)
-{
- if (EXT2_I(i)->i_flags & ODF_WHITEOUT)
- return 1;
- return 0;
-}
-
-/*
- * Checks if a dentry is opaque
- * The dentry version takes a UnionFS dentry, the inode one an ODF inode
- */
-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
@@ -1357,28 +1319,9 @@ int odf_get_opaque(struct super_block *sb, struct dentry
*dentry)
return i;
}
-int __odf_is_opaque(struct inode *i)
-{
- if (!S_ISDIR(i->i_mode))
- return 0;
- if (EXT2_I(i)->i_flags & ODF_OPAQUE)
- return 1;
- return 0;
-}
-
-/*
- * Gets opaque branch id from an inode, -1 if not opaque
- */
-int __odf_get_opaque(struct inode *i)
-{
- if (!__odf_is_opaque(i))
- return -1;
-
- return i->i_gid;
-}
-
/*
- * Sets a dentry as opaque, if not use -1 for branch
+ * Sets a dentry as opaque. The branch must be the branch_id as stored in
unionfs sb.
+ * If the dentry is not to be opaque, then branch must be -1
* The dentry version takes a UnionFS dentry, the inode one an ODF inode
*/
int odf_set_opaque(struct dentry *dentry, int branch)
@@ -1392,15 +1335,10 @@ int odf_set_opaque(struct dentry *dentry, int branch)
int __odf_set_opaque(struct inode *i, int branch)
{
- int err = 0;
- if (branch < 0)
- EXT2_I(i)->i_flags &= ~ODF_OPAQUE;
- else {
- EXT2_I(i)->i_flags |= ODF_OPAQUE;
- i->i_gid = branch;
- }
- err = ext2_write_inode(i, 1);
- return err;
+ struct iattr ia;
+ ia.ia_valid = ATTR_GID;
+ ia.ia_gid = branch + 1; /* since gid is unsigned */
+ return inode_setattr(i, &ia);
}
/*
@@ -1540,7 +1478,7 @@ int odf_write_sb_data(struct odf_sb_info* osi, struct
unionfs_data *data, struct
}
}
else {
- err = vfs_create(d_odf_sb->d_inode, d_content, 0, NULL );
+ err = vfs_create(d_odf_sb->d_inode, d_content, S_IRWXUGO, NULL
);
if (err)
goto out;
}
@@ -1806,7 +1744,7 @@ struct odf_dentry_info *odf_alloc_info(struct odf_sb_info
*osi, struct dentry *o
{
struct odf_dentry_info *odi =
kzalloc(sizeof(struct odf_dentry_info),GFP_KERNEL);
- odi->whiteout = __odf_is_wh(odf_dentry->d_inode);
+ odi->whiteout = __odf_is_wh(osi, odf_dentry);
odi->opaque = __odf_get_opaque(odf_dentry->d_inode);
odi->dentry = odf_dentry;
odi->inum = odf_dentry->d_inode->i_ino;
@@ -1819,7 +1757,7 @@ struct odf_dentry_info *odf_fill_info(struct
odf_dentry_info *odi, struct odf_sb
{
if (!odi)
return odf_alloc_info(osi, odf_dentry);
- odi->whiteout = __odf_is_wh(odf_dentry->d_inode);
+ odi->whiteout = __odf_is_wh(osi, odf_dentry);
odi->opaque = __odf_get_opaque(odf_dentry->d_inode);
dget(odf_dentry);
dput(odi->dentry);
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index 8126cc5..03ebbee 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -39,8 +39,11 @@
#define ODF_DIRENT_MAGIC 0x0DFD1300
+/* special filenames */
#define ODF_CONTENT "content"
#define ODF_CONTENT_LEN 7
+#define ODF_WH_NAME "whiteout"
+#define ODF_WH_LEN 8
#define ODF_CLEAN_ALL 1
#define ODF_CLEAN_CACHE 2
@@ -100,19 +103,26 @@ int odf_remove(struct dentry *dentry, int flags);
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(struct inode *i, int boolean);
-int __odf_is_wh(struct inode *i);
int odf_create_wh(struct dentry *dentry);
+static inline int __odf_is_wh(struct odf_sb_info *osi, struct dentry *dentry)
+{
+ if (!osi->whiteout)
+ return 0;
+ return osi->whiteout->d_inode->i_ino == dentry->d_inode->i_ino;
+}
+static inline int odf_is_wh(struct odf_dentry_info *odi)
+{
+ return __odf_is_wh(odi->osi, odi->dentry);
+}
/* opaque */
int odf_is_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);
+//int __odf_get_opaque(struct inode *i);
int __odf_set_opaque(struct inode *i, int branch);
+#define __odf_get_opaque(i) (i->i_gid -1)
/* cleanup thread functions */
extern void __odf_cleanup(void *args);
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 05dd8b2..c1b5f27 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -112,6 +112,7 @@ struct odf_sb_info {
struct sioa_args *cleanup; /* our cleanup thread */
char *branch_uuids; /* not null terminated string of all branch
uuids*/
int opaque_branch_id; /* should always be the branch id of branch 0*/
+ struct dentry *whiteout;
};
/* unionfs inode data in memory */
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs