commit ba36e26c681252e0fe11c3a0c4ed4d3fd2d6ad4f
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Wed Apr 11 18:34:19 2007 -0400

    on mount, expect an empty odf dir and create the hierarchy

diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
index b03a061..840e6e3 100644
--- a/fs/unionfs/dirhelper.c
+++ b/fs/unionfs/dirhelper.c
@@ -441,26 +441,16 @@ out_sb:
        return err;
 }
 
-/* Remove the hidden dentry by:
- *     a) rmdir if its a physically empty dir
- *     b) silly rename if its not physically empty
- *     c) unlink if not a dir
+/* Checks if the given directory is physically empty
+ * Returns 0 if it is empty and -ENOTEMPTY if not
  */
-int unionfs_force_rm(struct dentry *dentry, struct dentry **hidden_dentry, int 
bindex) 
+int check_empty_lower(struct dentry *lower_dentry, struct vfsmount *mnt) 
 {
-       struct file *hidden_file;
-       struct super_block *sb;
+       struct file *lower_file;
        struct unionfs_rdutil_callback *buf = NULL;
        int err;
 
-       sb = dentry->d_sb;
-       if (!S_ISDIR((*hidden_dentry)->d_inode->i_mode)) {
-               err = vfs_unlink((*hidden_dentry)->d_parent->d_inode, 
-                                               (*hidden_dentry));
-               if (err)
-                       goto out;
-               goto refresh;
-       }
+       BUG_ON(!S_ISDIR(lower_dentry->d_inode->i_mode));
 
        /* check if dir is empty */
        buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
@@ -474,29 +464,51 @@ int unionfs_force_rm(struct dentry *dentry, struct dentry 
**hidden_dentry, int b
        buf->dir = NULL;
        buf->filp = NULL;
 
-       dget(*hidden_dentry);
-       mntget(unionfs_lower_mnt_idx(dentry, bindex));
-       branchget(sb, bindex);
-       hidden_file = dentry_open(*hidden_dentry, 
-                       unionfs_lower_mnt_idx(dentry, bindex),
-                       O_RDONLY);
-       if (IS_ERR(hidden_file)) {
-               err = PTR_ERR(hidden_file);
-               dput(*hidden_dentry);
-               branchput(sb, bindex);
+       dget(lower_dentry);
+       mntget(mnt);
+       lower_file = dentry_open(lower_dentry, mnt, O_RDONLY);
+       if (IS_ERR(lower_file)) {
+               err = PTR_ERR(lower_file);
+               dput(lower_dentry);
+               mntput(mnt);
                goto out;
        }
 
        do {
                buf->filldir_called = 0;
-               err = vfs_readdir(hidden_file,
-                                 readdir_util_callback, buf);
-                       if (buf->err)
-                               err = buf->err;
+               err = vfs_readdir(lower_file, readdir_util_callback, buf);
+               if (buf->err)
+                       err = buf->err;
        } while ((err >= 0) && buf->filldir_called);
 
-       /* fput calls dput for hidden_dentry */
-       fput(hidden_file);
+       fput(lower_file);
+out:
+       kfree(buf);
+       return err;
+}
+
+/* Remove the hidden dentry by:
+ *     a) rmdir if its a physically empty dir
+ *     b) silly rename if its not physically empty
+ *     c) unlink if not a dir
+ */
+int unionfs_force_rm(struct dentry *dentry, struct dentry **hidden_dentry, int 
bindex) 
+{
+       struct super_block *sb;
+       int err;
+
+       sb = dentry->d_sb;
+       if (!S_ISDIR((*hidden_dentry)->d_inode->i_mode)) {
+               err = vfs_unlink((*hidden_dentry)->d_parent->d_inode, 
+                                               (*hidden_dentry));
+               if (err)
+                       goto out;
+               goto refresh;
+       }
+
+       /* check if dir is empty */
+       branchget(sb, bindex);
+       err = check_empty_lower(*hidden_dentry, unionfs_lower_mnt_idx(dentry, 
bindex));
        branchput(sb, bindex);
 
        if (err == 0)
@@ -524,8 +536,6 @@ refresh:
        }
        unionfs_set_lower_dentry_idx(dentry, bindex, *hidden_dentry);
 out:
-       if (buf)
-               kfree(buf);
        return err;
 }
 
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index 63b5c0c..4a6f81a 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -611,7 +611,7 @@ static int unionfs_read_super(struct super_block *sb, void 
*raw_data,
                goto out_free;
        }
 
-       /* if new bit set, unset it and save branch conf */           
+       /* if odf is new, save branch conf */           
        if (odf_is_new(odf)) {
 
                /* generate new uuids */
@@ -626,8 +626,6 @@ static int unionfs_read_super(struct super_block *sb, void 
*raw_data,
                                hidden_root_info->bend - 
hidden_root_info->bstart + 1);
                if (err)
                        goto out_free;
-               /* here we can safely mark the odf as not new */
-               odf_unset_newbit(odf);
        }
 
        /* set the hidden superblock field of upper superblock */
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 812cd53..65a75f0 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -1,4 +1,85 @@
 #include "union.h"
+
+/* Create a directory in odf
+ * Fails if the directory already exists
+ */
+static inline struct dentry * __odf_create_dir(struct dentry *parent, char 
*name)
+{
+       struct dentry *dentry = NULL;
+       int err;
+
+       dentry = lookup_one_len(name, parent, strlen(name));
+       if (IS_ERR(dentry))
+               goto out;
+       if (unlikely(dentry->d_inode)) {
+               dput(dentry);
+               dentry = ERR_PTR(-EINVAL);
+               goto out;
+       }
+       err = vfs_mkdir(parent->d_inode, dentry, S_IRWXUGO);
+       if (err) {
+               dput(dentry);
+               dentry = ERR_PTR(err);
+       }
+out:
+       return dentry;
+}
+
+/* Creates the hierarchy for a fresh odf file.
+ * It fails if any of the dirs/files to be created existed before
+ */
+int __odf_create_hierarchy(struct dentry *odf_root)
+{
+       struct dentry *dentry = NULL, *dentry_wh = NULL;
+       int err = 0;
+
+       dentry = __odf_create_dir(odf_root, ODF_NS);
+       if (IS_ERR(dentry)){
+               err = PTR_ERR(dentry);
+               dentry = NULL;
+               goto out;
+       }
+       dput(dentry);
+       dentry = __odf_create_dir(odf_root, ODF_IC);
+       if (IS_ERR(dentry)){
+               err = PTR_ERR(dentry);
+               dentry = NULL;
+               goto out;
+       }
+       dput(dentry);
+       dentry = __odf_create_dir(odf_root, ODF_RC);
+       if (IS_ERR(dentry)){
+               err = PTR_ERR(dentry);
+               dentry = NULL;
+               goto out;
+       }
+       dput(dentry);
+       dentry = __odf_create_dir(odf_root, ODF_SB);
+       if (IS_ERR(dentry)){
+               err = PTR_ERR(dentry);
+               dentry = NULL;
+               goto out;
+       }
+       dentry_wh = lookup_one_len(ODF_WH_NAME, dentry, ODF_WH_LEN);
+       if (IS_ERR(dentry_wh)) {
+               err = PTR_ERR(dentry_wh);
+               dentry_wh = NULL;
+               goto out;
+       }
+       if (unlikely(dentry_wh->d_inode)){
+               err = -EINVAL;
+               goto out;
+       }
+       err = vfs_create(dentry->d_inode, dentry_wh, S_IRWXUGO, NULL );
+       if (err)
+               goto out;
+out:
+       dput(dentry);
+       dput(dentry_wh);
+       return err;
+}
+
+
 /*
  * Initialize any odf data we might need
  * Reads the odf file from the options
@@ -6,58 +87,84 @@
 struct odf_sb_info* odf_read_super(char *options)
 {
        struct nameidata nd;
-       struct odf_sb_info *osi;
+       struct odf_sb_info *osi = NULL;
        char *odffile = NULL;
        struct sioa_args *sioa;
-       int err, odfforce;
+       int err, odfforce, new = 0;
        
        odfforce = odf_parse_options(options, &odffile);
        if (odfforce < 0) {
-               osi = ERR_PTR(odfforce);
+               err = odfforce;
                goto out;
        }
        
        err = path_lookup(odffile, LOOKUP_FOLLOW, &nd); 
        if (err) {      
-               printk(KERN_WARNING "unionfs_odf: Cannot access odf\n");
-               osi = ERR_PTR(err);
+               printk(KERN_WARNING "unionfs: Cannot access odf\n");
                goto out;
        }
-
-       err = odf_is_odf(nd.dentry);
-       if (err) {
-               osi = ERR_PTR(err);
+       if (!nd.dentry->d_inode || !S_ISDIR(nd.dentry->d_inode->i_mode)) {
+               printk(KERN_WARNING "unionfs: Invalid odf\n");
+               err = -EINVAL;
                goto out_release;
        }
+
+       /* if this odf is fresh, create the hierarchy */
+       if (check_empty_lower(nd.dentry, nd.mnt) == 0) {
+               err = __odf_create_hierarchy(nd.dentry);
+               if (err)
+                       goto out_release;
+               new = 1;
+       }
        osi = kzalloc(sizeof(struct odf_sb_info), GFP_KERNEL);
        if (!osi) {
-               osi = ERR_PTR(-ENOMEM);
+               err = -ENOMEM;
                goto out_release;
        }
+
        osi->odi_ns = odf_getpath(nd.dentry, osi, ODF_NS);
        if (IS_ERR(osi->odi_ns)){
                err = PTR_ERR(osi->odi_ns);
                osi->odi_ns = NULL;
                goto out_free;
        }
+       if (!osi->odi_ns) {
+               err = -EINVAL;
+               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;
        }
+       if (!osi->odi_sb) {
+               err = -EINVAL;
+               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;
        }
+       if (!osi->odi_rc) {
+               err = -EINVAL;
+               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;
        }
+       if (!osi->odi_ic) {
+               err = -EINVAL;
+               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);
@@ -65,10 +172,16 @@ struct odf_sb_info* odf_read_super(char *options)
                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;
+               err = -EINVAL;
+               goto out_free;
        }
+
+       /* if this odf was not fresh, but doesn't have sb/content, then fail */
+       if (!new && odf_is_new(osi)) {
+               err = -EINVAL;
+               goto out_free;
+       }
+
        /* start the reclaim sioa */
        sioa = kmalloc(sizeof(struct sioa_args), GFP_KERNEL);
        if (!sioa) {
@@ -93,10 +206,11 @@ out_free:
        dput(osi->whiteout);
        kfree(osi->branch_uuids);
        kfree(osi);
-       osi = ERR_PTR(err);
 out_release:
        path_release(&nd);
 out:
+       if (err)
+               osi = ERR_PTR(err);
        kfree(odffile);
        return osi;
 
@@ -137,6 +251,7 @@ struct odf_dentry_info* odf_getpath(struct dentry *d_odf, 
struct odf_sb_info *os
        else if (!dentry->d_inode) {
                odi = ERR_PTR(-EINVAL);
                dput(dentry);
+               goto out;
        }
        odi = odf_fill_info(NULL, osi, dentry);
        dput(dentry);
@@ -144,39 +259,6 @@ out:
        return odi;
 }
 
-/*
- * Returns 0 if the given path is a valid odf file
- */
-int odf_is_odf(struct dentry *d_odf)
-{
-       struct dentry *magic;
-       int err = 0;
-       
-       if (!d_odf->d_inode) {
-               err = -EINVAL;
-               goto out;
-       }
-
-       if (!S_ISDIR(d_odf->d_inode->i_mode)) {
-               err = -EINVAL;
-               goto out;
-       }
-
-       magic = lookup_one_len(ODF_MAGIC_FILE, d_odf, strlen(ODF_MAGIC_FILE));
-       if (IS_ERR(magic) || !magic) {
-               err = -EINVAL;
-               goto out;
-       }
-       else if (!magic->d_inode)
-               err = -EINVAL;
-
-       dput(magic);
-out:
-       if (err)
-               printk("unionfs: Invalid odf\n");
-       return err;
-}
-
 /* returns 1 if odfforce found, 0 if not */
 int odf_parse_options(char *options, char **odf_path)
 {
@@ -1342,42 +1424,23 @@ int __odf_set_opaque(struct inode *i, int branch)
 }
 
 /* 
- * checks the newbit 
+ * checks the sb/content file exists 
  */
 int odf_is_new(struct odf_sb_info *osi)
 {
-       struct dentry *newbit;
+       struct dentry *dentry;
 
-       /* check the new bit, for now check if file newbit exists */
-       newbit = lookup_one_len(ODF_NEWBIT, osi->odi_sb->dentry, 
strlen(ODF_NEWBIT));
-       if (IS_ERR(newbit) || !newbit)
-               return 0;
-       else if (likely(!newbit->d_inode)) {
-               dput(newbit);
-               return 0;
+       /* check if sb/content exists */
+       dentry = lookup_one_len(ODF_CONTENT, osi->odi_sb->dentry, 
ODF_CONTENT_LEN);
+       if (IS_ERR(dentry) || !dentry)
+               return 1;
+       else if (unlikely(!dentry->d_inode)) {
+               dput(dentry);
+               return 1;
        }
 
-       dput(newbit);
-       return 1;
-}
-
-/*
- * Unsets the newbit
- */
-void odf_unset_newbit(struct odf_sb_info *osi)
-{
-       struct dentry *newbit;
-
-       /* check the new bit, for now check if file newbit exists */
-       newbit = lookup_one_len(ODF_NEWBIT, osi->odi_sb->dentry, 
strlen(ODF_NEWBIT));
-       if (IS_ERR(newbit) || !newbit)
-               return;
-       else if (unlikely(!newbit->d_inode)) {
-               dput(newbit);
-               return;
-       }
-       vfs_unlink(newbit->d_parent->d_inode, newbit);
-       dput(newbit);
+       dput(dentry);
+       return 0;
 }
 
 /*
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index 086ec4b..aadda01 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -11,8 +11,6 @@
 #define ODF_IC "ic"
 #define ODF_RC "reclaim"
 #define ODF_NS "ns"
-#define ODF_NEWBIT "newbit"
-#define ODF_MAGIC_FILE "odfmagic"
 
 /* Some string constants */
 #define ODF_BRANCH_PATH 255
@@ -54,12 +52,10 @@
 struct odf_sb_info* odf_read_super(char *options);
 void odf_put_super(struct odf_sb_info *osi);
 int odf_is_new(struct odf_sb_info *osi);
-void odf_unset_newbit(struct odf_sb_info *osi);
 char *odf_read_sb_data(struct odf_sb_info *odf_sb, int **bid);
 int odf_write_sb_data(struct odf_sb_info* osi, struct unionfs_data *data,
                struct path *lower_paths, int branches);
 int odf_parse_options(char *options, char **odf_path);
-int odf_is_odf(struct dentry *d_odf);
 int odf_update_uuids(struct odf_sb_info *odf, struct path *old_paths, int 
old_branches, 
                struct path *new_paths, int new_branches);
 static inline char *odf_get_branch_uuid(struct odf_sb_info *odf, int branch)
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index c1b5f27..7bfc369 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -291,6 +291,7 @@ extern int unionfs_get_nlinks(struct inode *inode);
 /* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */
 extern int check_empty(struct dentry *dentry,
                       struct unionfs_dir_state **namelist);
+extern int check_empty_lower(struct dentry *lower_dentry, struct vfsmount 
*mnt);
 
 /* Re-lookup a hidden dentry. */
 extern int unionfs_refresh_hidden_dentry(struct dentry *dentry, int bindex);
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to