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