commit fdbb4e29ac25e58b3cff1613e69be47d879bd5a9
Author: Yiannis Pericleous <[EMAIL PROTECTED]>
Date: Fri Mar 30 18:23:56 2007 -0400
store uuids in memory and keep them consinstent throughout remounts
diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
index 1d8298e..203056b 100644
--- a/fs/unionfs/main.c
+++ b/fs/unionfs/main.c
@@ -611,6 +611,14 @@ static int unionfs_read_super(struct super_block *sb, void
*raw_data,
/* if new bit set, unset it and save branch conf */
if (odf_is_new(UNIONFS_SB(sb)->odf)) {
+
+ /* generate new uuids */
+ err = odf_update_uuids(UNIONFS_SB(sb)->odf, NULL, 0,
+ hidden_root_info->lower_paths,
+ hidden_root_info->bend -
hidden_root_info->bstart + 1);
+ if (err)
+ goto out_free;
+
err = odf_write_sb_data(
UNIONFS_SB(sb)->odf,
UNIONFS_SB(sb)->data,
diff --git a/fs/unionfs/odf.c b/fs/unionfs/odf.c
index 007f84a..38e1490 100644
--- a/fs/unionfs/odf.c
+++ b/fs/unionfs/odf.c
@@ -82,7 +82,7 @@ out_free:
odf_put_info(osi->odi_rc);
odf_put_info(osi->odi_sb);
odf_put_info(osi->odi_ic);
-
+ kfree(osi->branch_uuids);
kfree(osi);
osi = ERR_PTR(err);
out_release:
@@ -996,6 +996,59 @@ void odf_unset_newbit(struct odf_sb_info *osi)
}
/*
+ * Generates uuids for branches and makes sure branches belonging to the same
+ * filesystem get the same uuid.
+ */
+int odf_update_uuids(struct odf_sb_info *odf, struct path *old_paths, int
old_branches,
+ struct path *new_paths, int new_branches)
+{
+ struct vfsmount *m;
+ char *old_uuids = odf->branch_uuids;
+ char *new_uuids;
+ int err = 0, bindex, i;
+
+ new_uuids = kmalloc(new_branches * UUID_LEN, GFP_KERNEL);
+ if (!new_uuids) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ for (bindex = 0; bindex < new_branches; bindex++) {
+
+ m = new_paths[bindex].mnt;
+
+ /* check if this fs was in the old uuids */
+ for (i = 0; i < old_branches; i++) {
+ if (m == old_paths[i].mnt)
+ break;
+ }
+
+ /* if yes, then give it the old uuid */
+ if (i != old_branches) {
+ memcpy(new_uuids + bindex * UUID_LEN, old_uuids + i *
UUID_LEN, UUID_LEN);
+ continue;
+ }
+
+ /* now check the processed new branches */
+ for (i = 0; i < bindex; i++) {
+ if (m == new_paths[i].mnt)
+ break;
+ }
+
+ if (i != bindex)
+ memcpy(new_uuids + bindex * UUID_LEN, new_uuids + i *
UUID_LEN, UUID_LEN);
+
+ else /* if this is a new fs in the union give it a new uuid
*/
+ generate_random_uuid(new_uuids + bindex * UUID_LEN);
+ }
+
+ kfree(odf->branch_uuids);
+ odf->branch_uuids = new_uuids;
+
+out:
+ return err;
+}
+/*
* Writes the superblock data for new odf's, generates branch UUID's
* Superblock contains:
* odf version number, numbers of branches
@@ -1007,12 +1060,10 @@ int odf_write_sb_data(struct odf_sb_info* osi, struct
unionfs_data *data, struct
struct dentry *d, *d_odf_sb, *d_content;
struct vfsmount *m, *odf_mnt;
struct file *file;
- char *name;
- int count, len, bindex, i;
+ char *name, *uuid;
+ int len, bindex;
int err = 0;
__le32 le32;
- unsigned char *uuid = NULL;
- u32 *buuid = NULL;
char *branch_entry = kmalloc(ODF_BRANCH_PATH, GFP_KERNEL);
char *branch_path = kmalloc(ODF_BRANCH_PATH, GFP_KERNEL);
mm_segment_t oldfs;
@@ -1077,14 +1128,6 @@ int odf_write_sb_data(struct odf_sb_info* osi, struct
unionfs_data *data, struct
goto out_close;
}
- buuid = kmalloc(branches * sizeof(u32), GFP_KERNEL);
- uuid = kmalloc(branches * UUID_LEN, GFP_KERNEL);
- if (!buuid || !uuid) {
- err = -ENOMEM;
- goto out_close;
- }
- count = 0;
-
/* now info about each branch */
for (bindex = 0; bindex < branches; bindex++) {
@@ -1096,18 +1139,6 @@ int odf_write_sb_data(struct odf_sb_info* osi, struct
unionfs_data *data, struct
name = d_path(d, m, branch_path, ODF_BRANCH_PATH);
len = strlen(name);
- /* generate UUIDs, we want to have same ids for same fss*/
- /* XXX: Right now we lose previous UUIDs on remounts */
- for (i = 0; i < count; i++) {
- if ((u32)m == buuid[i])
- break;
- }
- if (i == count)
- generate_random_uuid(uuid + count * UUID_LEN);
- else
- memcpy(uuid + count * UUID_LEN, uuid + i * UUID_LEN,
UUID_LEN);
- buuid[count] = (u32)m;
-
/* write branch ids */
le32 = cpu_to_le32(data[bindex].branch_id);
err = file->f_op->write(file, (char*)&le32, sizeof(__le32),
&file->f_pos);
@@ -1140,12 +1171,12 @@ int odf_write_sb_data(struct odf_sb_info* osi, struct
unionfs_data *data, struct
}
/* branch uuid */
- err = file->f_op->write(file, (char*)uuid + count * UUID_LEN,
UUID_LEN, &file->f_pos);
+ uuid = odf_get_branch_uuid(osi, bindex);
+ err = file->f_op->write(file, uuid, UUID_LEN, &file->f_pos);
if (err != UUID_LEN) {
err = -EIO;
goto out_close;
}
- count++;
}
err = 0;
@@ -1153,8 +1184,6 @@ out_close:
set_fs(oldfs);
filp_close(file,NULL);
out:
- kfree(uuid);
- kfree(buuid);
kfree(branch_path);
kfree(branch_entry);
return err;
@@ -1246,6 +1275,13 @@ char *odf_read_sb_data(struct odf_sb_info *odf_sb, int
**bid)
goto out_close;
}
+ BUG_ON(odf_sb->branch_uuids);
+ odf_sb->branch_uuids = kmalloc(count * UUID_LEN, GFP_KERNEL);
+ if (!odf_sb->branch_uuids) {
+ err = -ENOMEM;
+ goto out_close;
+ }
+
i = 0;
while (i < count) {
/* branch id */
@@ -1289,6 +1325,7 @@ char *odf_read_sb_data(struct odf_sb_info *odf_sb, int
**bid)
err = -EIO;
goto out_close;
}
+ memcpy(odf_sb->branch_uuids + i * UUID_LEN, uuid, UUID_LEN);
/* add the branch permissions to the options string */
ptr+=len;
@@ -1306,6 +1343,8 @@ char *odf_read_sb_data(struct odf_sb_info *odf_sb, int
**bid)
out_close:
set_fs(oldfs);
filp_close(file,NULL);
+ kfree(odf_sb->branch_uuids);
+ odf_sb->branch_uuids = NULL;
out_err:
kfree(options);
options = ERR_PTR(err);
diff --git a/fs/unionfs/odf.h b/fs/unionfs/odf.h
index f954dec..80546d9 100644
--- a/fs/unionfs/odf.h
+++ b/fs/unionfs/odf.h
@@ -47,16 +47,24 @@ 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_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)
+{
+ return (odf->branch_uuids + UUID_LEN * branch);
+}
/* lookup */
int odf_lookup(struct dentry *parent, struct dentry *dentry, int flags);
-struct odf_dentry_info *__odf_lookup(struct odf_sb_info *osi, struct
odf_dentry_info *parent, const char *name, int len, int flags, struct
odf_dentry_info *old_odi);
-
+struct odf_dentry_info *__odf_lookup(struct odf_sb_info *osi, struct
odf_dentry_info *parent,
+ const char *name, int len, int flags, struct odf_dentry_info
*old_odi);
struct odf_dentry_info *odf_getpath(struct dentry *d_odf, struct odf_sb_info
*osi, const char *name);
-struct odf_dentry_info *odf_fill_info(struct odf_dentry_info *odi, struct
odf_sb_info *osi, struct dentry *odf_dentry);
+struct odf_dentry_info *odf_fill_info(struct odf_dentry_info *odi,
+ struct odf_sb_info *osi, struct dentry *odf_dentry);
struct odf_dentry_info *odf_alloc_info(struct odf_sb_info *osi, struct dentry
*odf_dentry);
void odf_put_info(struct odf_dentry_info *odi);
diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
index 4ae492f..d02ba17 100644
--- a/fs/unionfs/super.c
+++ b/fs/unionfs/super.c
@@ -686,9 +686,19 @@ out_no_change:
new_lower_paths = tmp_lower_paths;
}
- /* now update the odf. rewrite the superblock data file with all
+
+
+ /*
+ * Update the odf. rewrite the superblock data file with all
* the new branch information
*/
+
+ /* first we need to update the uuids */
+ err = odf_update_uuids(odf, UNIONFS_D(sb->s_root)->lower_paths,
+ cur_branches, new_lower_paths, new_branches );
+ if(err)
+ goto out_release;
+
err = odf_write_sb_data(odf, new_data, new_lower_paths, new_branches);
if (err)
goto out_release;
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index 430a472..6493f49 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -104,12 +104,13 @@ struct odf_dentry_info {
/* odf sb data */
struct odf_sb_info {
- struct vfsmount *mnt;
- struct odf_dentry_info *odi_ns;
- struct odf_dentry_info *odi_sb;
- struct odf_dentry_info *odi_rc;
- struct odf_dentry_info *odi_ic;
- struct sioa_args *cleanup;
+ struct vfsmount *mnt; /* odf vmsmount */
+ struct odf_dentry_info *odi_ns; /* namespace (/ns) */
+ struct odf_dentry_info *odi_sb; /* superblock (/sb) */
+ struct odf_dentry_info *odi_rc; /* reclaim (/reclaim) */
+ struct odf_dentry_info *odi_ic; /* inode cache (/ic) */
+ struct sioa_args *cleanup; /* our cleanup thread */
+ char *branch_uuids; /* not null terminated string of all branch
uuids*/
int opaque_branch_id; /* should always be the branch id of branch 0*/
};
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs