commit a05ffc666dec202b33d2143e82b4d7dd3408d587
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Sun Feb 25 15:59:06 2007 -0500

    inode: removed loops when creating & force remove if it already exists
    
    at branch 0 (and is a whiteout)

diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index fe6c9a4..a8b59ec 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -55,6 +55,25 @@ struct unionfs_rdutil_callback {
        struct unionfs_dir_state *rdstate;
        int mode;
 };
+struct unionfs_rmdir_callback {
+       int err;
+       int bindex;
+       int filldir_called;
+       struct dentry *dir;
+       struct vfsmount *mnt;
+};
+static int rmdir_util_callback(void *dirent, const char *name, int namelen,
+                                loff_t offset, u64 ino, unsigned int d_type)
+{
+       int err = 0;
+       struct unionfs_rmdir_callback *buf = dirent;
+       struct dentry *dentry;
+       
+       buf->filldir_called++;
+
+       if (name[0] == '.' &&
+               (namelen == 1 || (name[1] == '.' && namelen == 2)))
+                       goto out;
 
 /* callback structure for odf_cleanup*/
 struct unionfs_cleanup_callback {
@@ -817,3 +836,60 @@ out:
 
        return err;
 }
+
+/* This function recursively rermoves all the entries of a lower directory
+ * at a specific branch and then the directory itself. It does not
+ * cross branches, and does nothing visible to the union. It should
+ * only be used when both a whiteout and a dir at top branch exists
+ * and we need to create a new dentry
+ */
+int unionfs_force_rmdir(struct vfsmount *mnt, struct dentry *hidden_dentry, 
int bindex)
+{
+       int err = 0;
+       struct file *hidden_file;
+       struct unionfs_rmdir_callback *buf = NULL;
+
+       buf = kmalloc(sizeof(struct unionfs_rmdir_callback), GFP_KERNEL);
+       if (!buf) {
+               err = -ENOMEM;
+               goto out;
+       }
+       buf->err = 0;
+       buf->bindex = bindex;
+       buf->dir = hidden_dentry;
+       buf->mnt = mnt;
+
+       if (!hidden_dentry->d_inode)
+               goto out;
+       if (!S_ISDIR(hidden_dentry->d_inode->i_mode))
+               goto out;
+
+       dget(hidden_dentry);
+       mntget(mnt);
+       hidden_file = dentry_open(hidden_dentry, mnt, O_RDONLY);
+       if (IS_ERR(hidden_file)) {
+               err = PTR_ERR(hidden_file);
+               dput(hidden_dentry);
+               goto out;
+       }
+
+       do {
+               buf->filldir_called = 0;
+               err = vfs_readdir(hidden_file, rmdir_util_callback, buf);
+               if (buf->err)
+                       err = buf->err;
+       } while ((err >= 0) && buf->filldir_called);
+
+       /* fput calls dput for hidden_dentry */
+       fput(hidden_file);
+
+       if (err < 0)
+               goto out;
+
+       err = vfs_rmdir(hidden_dentry->d_parent->d_inode, hidden_dentry);
+
+out:
+       kfree(buf);
+
+       return err;
+}
diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
index e964c2d..9253545 100644
--- a/fs/unionfs/inode.c
+++ b/fs/unionfs/inode.c
@@ -18,6 +18,24 @@
 
 #include "union.h"
 
+static int do_force_rm(struct dentry *dentry, struct dentry *hidden_dentry, 
int bindex)
+{
+       int err;
+
+       /* this should only happen if its a wh */
+       BUG_ON(!UNIONFS_D(dentry)->odf_info->whiteout);
+               
+       /* try to remove it! */
+       if (S_ISDIR(hidden_dentry->d_inode->i_mode))
+               err = unionfs_force_rmdir(unionfs_lower_mnt_idx(dentry, 
bindex), 
+                                       hidden_dentry, bindex);
+
+       else
+               err = vfs_unlink(hidden_dentry->d_parent->d_inode,
+                                               hidden_dentry);
+       return err;
+}
+
 static int unionfs_create(struct inode *parent, struct dentry *dentry,
                          int mode, struct nameidata *nd)
 {
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 7e61a66..8ab7d3b 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -1557,7 +1557,7 @@ out:
 int odf_purge_dir_cache(struct dentry *dentry)
 {
        int err = 0;
-       struct iattr attr;
+       //struct iattr attr;
        struct odf_dentry_info *odi = NULL;
 
        odi = odf_ic_dir(dentry);
@@ -1779,13 +1779,6 @@ int __odf_set_opaque(struct inode *i, int branch)
        return err;
 }
 
-void print_uuid(unsigned char *uuid)
-{
-       int i;
-       for (i = 0; i < 4; i++){
-               printk("%x-", *((unsigned int *) ((uuid+i*4))));                
}
-       printk("\n");
-}
 /* 
  * checks the sb/content file exists 
  */
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to