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