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