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

Reply via email to