commit 778c0b197b58a26d3a48ceef4670964a6e2f28b8
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date:   Tue May 29 00:35:09 2007 -0400

    fixed odf_parse_options to use strdup and strsep
    
    look for odf_keepcache instead of odfforce option
    fail if dirs specified with old odf

diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index 9741e94..70ddb22 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -620,10 +620,8 @@ static int unionfs_read_super(struct super_block *sb, void 
*raw_data,
         * then initialize odf sb data
         */
        err = odf_read_super(sb, raw_data);
-       if (err) {
-               printk(KERN_WARNING "unionfs_read_super: odf error\n");
+       if (err)
                goto out_free;
-       }
        odf = &UNIONFS_SB(sb)->odf;
 
        /* if this is an old odf reconstruct the dirs part of the mount time 
options
@@ -637,8 +635,6 @@ static int unionfs_read_super(struct super_block *sb, void 
*raw_data,
                        odf_options = NULL;
                        goto out_free;
                }
-               if (strstr(raw_data,"dirs="))
-                       printk(KERN_WARNING "unionfs: Ignoring dirs option\n");
                raw_data = odf_options;
        }
 
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index aea6a09..3ed0284 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -12,8 +12,8 @@ static inline struct dentry * __odf_create_dir(struct dentry 
*parent, char *name
        if (IS_ERR(dentry))
                goto out;
        if (unlikely(dentry->d_inode)) {
-       //      dput(dentry);
-       //      dentry = ERR_PTR(-EEXIST);
+               dput(dentry);
+               dentry = ERR_PTR(-EEXIST);
                goto out;
        }
        err = vfs_mkdir(parent->d_inode, dentry, S_IRWXUGO);
@@ -68,7 +68,7 @@ int __odf_create_hierarchy(struct dentry *odf_root)
                goto out;
        }
        if (unlikely(dentry->d_inode)){
-       //      err = -EEXIST;
+               err = -EEXIST;
                goto out;
        }
        err = vfs_create(odf_root->d_inode, dentry, S_IRWXUGO, NULL);
@@ -83,17 +83,17 @@ out:
  * Initialize any odf data we might need
  * Reads the odf file from the options
  */
-int odf_read_super(struct super_block *sb, char *options)
+int odf_read_super(struct super_block *sb, char *data)
 {
        struct nameidata nd;
        struct odf_sb_info *osi = &UNIONFS_SB(sb)->odf;
        char *odffile = NULL;
        struct sioa_args *sioa;
-       int err, odfforce;
+       int err, options;
 
-       odfforce = odf_parse_options(options, &odffile);
-       if (odfforce < 0) {
-               err = odfforce;
+       options = odf_parse_options(data, &odffile);
+       if (options < 0) {
+               err = options;
                goto out;
        }
 
@@ -128,6 +128,13 @@ int odf_read_super(struct super_block *sb, char *options)
                if (err)
                        goto out_free;
        }
+       /* dont allow dirs= options when odf is not new */
+       else if (options & ODF_OPT_DIRS) {
+               printk(KERN_WARNING
+                      "unionfs: dirs option not allowed with used odf\n");
+               err = -EINVAL;
+               goto out_free;
+       }
 
        osi->ns = odf_getdir(nd.dentry, ODF_NS, sizeof(ODF_NS) - 1);
        if (IS_ERR(osi->ns)){
@@ -177,7 +184,7 @@ int odf_read_super(struct super_block *sb, char *options)
        }
        sioa->cleanup.odf = osi;
        sioa->cleanup.attr = get_attributes();
-       sioa->cleanup.force = !odfforce; /* if set we dont force clean*/
+       sioa->cleanup.force = !(options & ODF_OPT_KEEPCACHE);
        osi->cleanup = sioa;
        osi->mnt = nd.mnt;
        mntget(osi->mnt);
@@ -228,8 +235,10 @@ void odf_put_super(struct odf_sb_info *osi)
        kfree(osi->branch_uuids);
        osi->branch_uuids = NULL;
 
-       dput(osi->mnt->mnt_sb->s_root);
-       mntput(osi->mnt);
+       if (osi->mnt) {
+               dput(osi->mnt->mnt_sb->s_root);
+               mntput(osi->mnt);
+       }
        if (osi->cleanup)
                complete_sioa(osi->cleanup);
        kfree(osi->cleanup);
@@ -258,58 +267,84 @@ struct dentry* odf_getdir(struct dentry *d_odf, const 
char *name, int len)
        return dentry;
 }
 
-/* returns 1 if odfforce found, 0 if not */
-int odf_parse_options(char *options, char **odf_path)
+/* parses the given options looking for odf-related options
+ * On success odf_path will contain the path to the odf file and
+ * the return value can contain a combination of these flags:
+ * ODF_OPT_KEEPCACHE and ODF_OPT_DIRS
+ */
+int odf_parse_options(const char *options, char **odf_path)
 {
-       int err = 0;
-       char *ptr, *ptrend;
+       int err = 0, odf = 0;
+       char *tmp_options, *optname;
 
-       /* check for odf= part of the options */
-       if (!strncmp(options, "odf=", 4))
-               ptr = options;
-       else
-               ptr = strstr(options,",odf=");
-       if (!ptr) {
-               err = -EINVAL;
-               printk("unionfs: odf option required\n");
+       tmp_options = kstrdup(options, GFP_KERNEL);
+       if (!tmp_options) {
+               err = -ENOMEM;
                goto out;
        }
-       if (ptr != options)
-               ptr++;
-       ptr+=4;
-       ptrend = (strchr(ptr, ','));
-       if (!ptrend)
-               ptrend = ptr + strlen(ptr);
 
-       if (ptr == ptrend) {
-               printk("unionfs: odf option requires an argument\n");
-               err = -EINVAL;
-               goto out;
-       }
-       *odf_path = kzalloc(ptrend - ptr + 1,GFP_KERNEL);
-       strncpy(*odf_path, ptr, ptrend - ptr);
+       while ((optname = strsep(&tmp_options, ",")) != NULL) {
+               char *optarg;
 
-       /* now check for odfforce */
-       if (!strncmp(options, "odfforce", 8))
-               ptr = options;
-       else
-               ptr = strstr(options,",odfforce");
-       if (ptr) {
-               if (ptr != options)
-                       ptr++;
-               ptr+=8;
-               ptrend = (strchr(ptr, ','));
-               if (!ptrend)
-                       ptrend = ptr + strlen(ptr);
-               if (ptr != ptrend) {
-                       printk("unionfs: odfforce option does not take an 
argument\n");
+               if (!optname || !*optname)
+                       continue;
+
+               optarg = strchr(optname, '=');
+               if (optarg)
+                       *optarg++ = '\0';
+
+               if (!strcmp("odf_keepcache", optname)) {
+                       if (optarg) {
+                               printk(KERN_WARNING
+                                      "unionfs: %s does not take an 
argument.\n",
+                                      optname);
+                               err = -EINVAL;
+                               goto out_error;
+                       }
+                       err |= ODF_OPT_KEEPCACHE;
+               }
+
+               if (!optarg) {
+                       printk(KERN_WARNING
+                              "unionfs: %s requires an argument.\n",
+                              optname);
                        err = -EINVAL;
-                       goto out;
+                       goto out_error;
+               }
+
+               if (!strcmp("odf", optname)) {
+                       if (++odf > 1) {
+                               printk(KERN_WARNING
+                                      "unionfs: multiple odf specified\n");
+                               err = -EINVAL;
+                               goto out_error;
+                       }
+                       *odf_path = kzalloc(strlen(optarg) + 1,GFP_KERNEL);
+                       strcpy(*odf_path, optarg);
                }
-               err = 1;
+
+               /* we only care if dirs is present, not its actual args */
+               if (!strcmp("dirs", optname))
+                       err |= ODF_OPT_DIRS;
+
+               /* dont throw error on unrecognized argsm because this will
+                * be caught by unionfs_parse_options, we should only be
+                * worried with options that affect the odf
+                */
+       }
+
+       if (odf != 1) {
+               printk(KERN_WARNING "unionfs: odf option required\n");
+               err = -EINVAL;
+               goto out_error;
        }
-       else err = 0;
+       goto out;
+
+out_error:
+       if (odf)
+               kfree(*odf_path);
 out:
+       kfree(tmp_options);
        return err;
 }
 
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index 787e4f1..e1e8c3c 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -38,14 +38,17 @@
 #define ODF_CLEAN_INODES 3
 #define ODF_CLEAN_BLOCKS 4
 
+/* Options flags */
+#define ODF_OPT_KEEPCACHE 0x01
+#define ODF_OPT_DIRS     0x02
 /* super */
-int odf_read_super(struct super_block *sb, char *options);
+int odf_read_super(struct super_block *sb, char *data);
 void odf_put_super(struct odf_sb_info *osi);
 int odf_is_new(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_parse_options(const char *options, char **odf_path);
 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)
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to