This patch solves the first two sample problems of my last mail. Also
you need my next patches.
- validation of the specified file.
- file size check in get_uin().

Junjiro Okajima


diff -u -p -r1.1 -r1.2
--- unionfs-20060117-2031/persistent_inode.c    18 Jan 2006 03:02:19 -0000      
1.1
+++ unionfs-20060117-2031/persistent_inode.c    18 Jan 2006 08:16:46 -0000      
1.2
@@ -16,7 +16,37 @@
  */
 
 #include "unionfs.h"
 
+static ssize_t __fread(struct file *filp, void *buf, size_t size, loff_t *pos)
+{
+       int err;
+       mm_segment_t oldfs;
+
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       if (filp->f_op->read)
+               err = filp->f_op->read(filp, (char __user*)buf, size, pos);
+       else
+               err = do_sync_read(filp, (char __user*)buf, size, pos);
+       set_fs(oldfs);
+       return err;
+}
+
+static ssize_t __fwrite(struct file *filp, void *buf, size_t size, loff_t *pos)
+{
+       int err;
+       mm_segment_t oldfs;
+
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       if (filp->f_op->write)
+               err = filp->f_op->write(filp, (const char __user*)buf, size, 
pos);
+       else
+               err = do_sync_write(filp, (const char __user*)buf, size, pos);
+       set_fs(oldfs);
+       return err;
+}
+
 /*
  * verify_forwardmap(super_block *sb)
  * sb: pointer to a superblock containing the forwardmap.
@@ -33,7 +63,6 @@ static int verify_forwardmap(struct supe
        struct file *forwardmap = NULL;
        struct fmaphdr header;
        struct unionfs_sb_info *spd = NULL;
-       mm_segment_t oldfs;
        print_entry_location();
 
        spd = stopd(sb);
@@ -44,12 +73,8 @@ static int verify_forwardmap(struct supe
                err = -EINVAL;
                goto out;
        }
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       bytesread =
-           forwardmap->f_op->read(forwardmap, (char __user *)&header,
-                                  sizeof(struct fmaphdr), &readpos);
-       set_fs(oldfs);
+       bytesread = __fread(forwardmap, &header, sizeof(struct fmaphdr),
+                           &readpos);
        if (bytesread < sizeof(struct fmaphdr)) {
                err = -EINVAL;
                goto out;
@@ -61,27 +86,20 @@ static int verify_forwardmap(struct supe
        }
        spd->usi_bmap =
            KMALLOC(sizeof(struct bmapent) * header.usedbranches, GFP_KERNEL);
-       spd->usi_num_bmapents = header.usedbranches;
+       //spd->usi_num_bmapents = header.usedbranches;
        if (!spd->usi_bmap) {
                err = -ENOMEM;
                goto out;
        }
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
        while (bindex < header.usedbranches) {
-               bytesread =
-                   forwardmap->f_op->read(forwardmap,
-                                          (char __user *)&stopd(sb)->
-                                          usi_bmap[bindex],
-                                          sizeof(struct bmapent), &readpos);
+               bytesread = __fread(forwardmap, &stopd(sb)->usi_bmap[bindex],
+                                   sizeof(struct bmapent), &readpos);
                if (bytesread < sizeof(struct bmapent)) {
                        err = -EINVAL;
-                       set_fs(oldfs);
                        goto out_err;
                }
                bindex++;
        }
-       set_fs(oldfs);
        mallocsize = sizeof(int) * header.usedbranches;
        spd->usi_fsnum_table = KMALLOC(mallocsize, GFP_KERNEL);
        if (!spd->usi_fsnum_table) {
@@ -123,7 +141,6 @@ static int verify_reversemap(struct supe
        struct file *forwardmap, *reversemap;
        struct fmaphdr fheader;
        struct rmaphdr rheader;
-       mm_segment_t oldfs;
        struct kstatfs st;
        struct unionfs_sb_info *spd = NULL;
 
@@ -142,26 +159,19 @@ static int verify_reversemap(struct supe
                err = -EINVAL;
                goto out;
        }
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       bytesread =
-           forwardmap->f_op->read(forwardmap, (char __user *)&fheader,
-                                  sizeof(struct fmaphdr), &readpos);
+       bytesread = __fread(forwardmap, &fheader, sizeof(struct fmaphdr),
+                           &readpos);
        if (bytesread < sizeof(struct fmaphdr)) {
-               set_fs(oldfs);
                err = -EINVAL;
                goto out;
        }
        readpos = 0;
-       bytesread =
-           reversemap->f_op->read(reversemap, (char __user *)&rheader,
-                                  sizeof(struct rmaphdr), &readpos);
+       bytesread = __fread(reversemap, &rheader, sizeof(struct rmaphdr),
+                           &readpos);
        if (bytesread < sizeof(struct rmaphdr)) {
-               set_fs(oldfs);
                err = -EINVAL;
                goto out;
        }
-       set_fs(oldfs);
        if (rheader.magic != REVERSEMAP_MAGIC
            || rheader.version != REVERSEMAP_VERSION) {
                err = -EINVAL;
@@ -176,7 +186,7 @@ static int verify_reversemap(struct supe
         * we go through all the branches in the union and see which ones it
         * matches with*/
        for (i = 0; i < spd->usi_num_bmapents && !found; i++) {
-               if (!memcmp
+               if (memcmp
                    (rheader.revuuid, spd->usi_bmap[i].uuid,
                     sizeof(rheader.revuuid)))
                        continue;
@@ -207,7 +217,7 @@ static int verify_reversemap(struct supe
                                fsid.val[1] = MINOR(dev);
                        }
 
-                       if (!memcmp(&fsid, &rheader.fsid, sizeof(fsid)))
+                       if (memcmp(&fsid, &rheader.fsid, sizeof(fsid)))
                                continue;
 
                        if (spd->usi_fsnum_table[i] == -1)
@@ -253,20 +263,20 @@ int init_imap_data(struct super_block *s
 
        mallocsize = sizeof(struct file *) * (hidden_root_info->udi_bend + 1);
        spd->usi_reversemaps = KZALLOC(mallocsize, GFP_KERNEL);
-       if (IS_ERR(spd->usi_reversemaps)) {
+       if (!spd->usi_reversemaps) {
                err = -ENOMEM;
                goto out_error;
        }
 
        spd->usi_map_table = KZALLOC(mallocsize, GFP_KERNEL);
-       if (IS_ERR(spd->usi_map_table)) {
+       if (!spd->usi_map_table) {
                err = -ENOMEM;
                goto out_error;
        }
 
        mallocsize = sizeof(int) * (hidden_root_info->udi_bend + 1);
        spd->usi_bnum_table = KMALLOC(mallocsize, GFP_KERNEL);
-       if (IS_ERR(spd->usi_bnum_table)) {
+       if (!spd->usi_bnum_table) {
                err = -ENOMEM;
                goto out_error;
        }
@@ -365,9 +375,6 @@ int parse_imap_option(struct super_block
                                spd->usi_forwardmap = NULL;
                                goto out_error;
                        }
-                       err = verify_forwardmap(sb);
-                       if (err)
-                               goto out_error;
                } else {
                        spd->usi_reversemaps[count] =
                            filp_open(name, O_RDWR, 0);
@@ -378,10 +385,6 @@ int parse_imap_option(struct super_block
 
                        }
                        count++;
-                       err =
-                           verify_reversemap(sb, count - 1, hidden_root_info);
-                       if (err)
-                               goto out_error;
                }
        }
        if (count <= 0) {
@@ -411,6 +414,14 @@ int parse_imap_option(struct super_block
                spd->usi_next_avail = FIRST_VALID_INODE;
 
        spd->usi_num_bmapents = count;
+       err = verify_forwardmap(sb);
+       if (err)
+               goto out_error;
+       while (count > 0) {
+               err = verify_reversemap(sb, --count, hidden_root_info);
+               if (err)
+                       goto out_error;
+       }
        spd->usi_persistent = 1;
 
        goto out;
@@ -426,6 +437,87 @@ int parse_imap_option(struct super_block
        return err;
 }
 
+ /*
+ * get @ino from @hidden_ino.
+ */
+static int __get_uin(struct unionfs_sb_info *sbi, ino_t hidden_ino, int bindex,
+                    ino_t *ino)
+{
+       int err;
+       struct file *rev;
+       loff_t pos;
+       ssize_t sz;
+       uint64_t ino64;
+       const int elmnt = sizeof(ino64);
+
+       rev = sbi->usi_map_table[bindex];
+       pos = sizeof(struct rmaphdr) + elmnt*hidden_ino;
+       *ino = 0;
+       err = 0;
+       if (pos+elmnt > rev->f_dentry->d_inode->i_size)
+               goto out;
+
+       sz = __fread(rev, &ino64, elmnt, &pos);
+       err = sz;
+       if (err < 0)
+               goto out;
+       err = 0;
+       *ino = -1;
+       if (sz != elmnt || ino64 > *ino)
+               err = -EIO;
+       *ino = ino64;
+ out:
+       print_exit_status(err);
+       return err;
+}
+
+/*
+ * put unionfs @ino for @hidden_ino on @bindex.
+ */
+static int __write_uin(struct unionfs_sb_info *sbi, ino_t ino, int bindex,
+                      ino_t hidden_ino)
+{
+       struct file *fwd, *rev;
+       struct fmapent ent;
+       loff_t pos;
+       ssize_t sz;
+       int err;
+       uint64_t ino64;
+       const int fwdhdr = sizeof(struct fmaphdr) + sizeof(struct bmapent[256]);
+       const int fwd_elmnt = sizeof(ent);
+       const int rev_elmnt = sizeof(ino64);
+
+       err = -ENOSPC;
+       if (ino < FIRST_VALID_INODE)
+               goto out;
+
+       fwd = sbi->usi_forwardmap;
+       ent.fsnum = sbi->usi_bnum_table[bindex];
+       ent.inode = ino;
+       pos = fwdhdr + fwd_elmnt*hidden_ino;
+       sz = __fwrite(fwd, &ent, fwd_elmnt, &pos);
+       err = sz;
+       if (err < 0)
+               goto out;
+       err = -EIO;
+       if (sz != fwd_elmnt)
+               goto out;
+
+       rev = sbi->usi_map_table[bindex];
+       pos = sizeof(struct rmaphdr) + rev_elmnt*hidden_ino;
+       ino64 = ino;
+       sz = __fwrite(rev, &ino64, rev_elmnt, &pos);
+       err = sz;
+       if (err < 0)
+               goto out;
+       err = 0;
+       if (sz != rev_elmnt)
+               err = -EIO;
+ out:
+       print_exit_status(err);
+       return err;
+}
+
 /*
  * get_uin(struct super_block *sb, uint8_t branchnum, ino_t inode_number, int 
flag)
  * fsnum: branch to reference when getting the inode number
@@ -438,16 +530,8 @@ int parse_imap_option(struct super_block
 ino_t get_uin(struct super_block * sb, uint8_t branchnum, ino_t inode_number,
              int flag)
 {
-       struct file *reversemap;
-       struct file *forwardmap;
-       struct fmapent tmp_ent;
-       mm_segment_t oldfs;
-       loff_t seekpos = 0;
-       loff_t isize = 0;
-       int bytesread = 0, byteswritten = 0;
-       ino_t err = 0;
-       uint64_t uino = 0;
-       struct unionfs_sb_info *spd = NULL;
+       ino_t ino, err = 0;
+       struct unionfs_sb_info *spd;
 
        print_entry_location();
 
@@ -456,75 +540,37 @@ ino_t get_uin(struct super_block * sb, u
 
        /* Find appropriate reverse map and then read from the required 
position */
        /* get it from the array. */
-       reversemap = spd->usi_map_table[branchnum];
-       seekpos = sizeof(struct rmaphdr) + (sizeof(uint64_t) * inode_number);
-       isize = reversemap->f_dentry->d_inode->i_size;
-       if (seekpos > isize) {
-               if (flag & O_CREAT) {
-                       goto create;
+       err = __get_uin(spd, inode_number, branchnum, &ino);
+       if (err || ino)
+               goto out;
 
-               } else {
-                       err = -ENOENT;
-                       goto out;
-               }
-       }
-       oldfs = get_fs();
-       set_fs(KERNEL_DS);
-       bytesread =
-           reversemap->f_op->read(reversemap, (char __user *)&uino,
-                                  sizeof(uint64_t), &seekpos);
-       set_fs(oldfs);
-       if (bytesread != sizeof(uint64_t)) {
-               err = -EIO;
+       err = -EIO;
+       if (!(flag & O_CREAT))
                goto out;
-       }
+
        /* If we haven't found an entry and we have the O_CREAT flag set we 
want to
         * create a new entry write it out to the file and return its index
         */
-      create:
-       if (uino <= 0 && (flag & O_CREAT)) {
-               forwardmap = spd->usi_forwardmap;
-               tmp_ent.fsnum = spd->usi_bnum_table[branchnum];
-               tmp_ent.inode = inode_number;
-               seekpos =
-                   sizeof(struct fmaphdr) + sizeof(struct bmapent[256]) +
-                   (sizeof(struct fmapent) * spd->usi_next_avail);
-               oldfs = get_fs();
-               set_fs(KERNEL_DS);
-               byteswritten =
-                   forwardmap->f_op->write(forwardmap,
-                                           (const char __user *)&tmp_ent,
-                                           sizeof(struct fmapent), &seekpos);
-               set_fs(oldfs);
-               if (byteswritten != sizeof(struct fmapent)) {
-                       err = -EIO;
-                       goto out;
-               }
-               uino = spd->usi_next_avail++;
-
-               seekpos =
-                   sizeof(struct rmaphdr) + (sizeof(uint64_t) * inode_number);
-               oldfs = get_fs();
-               set_fs(KERNEL_DS);
-
-               byteswritten =
-                   reversemap->f_op->write(reversemap,
-                                           (const char __user *)&uino,
-                                           sizeof(uint64_t), &seekpos);
-               set_fs(oldfs);
-               if (byteswritten != sizeof(uint64_t)) {
-                       err = -EIO;
-                       goto out;
-               }
-       } else if (uino >= FIRST_VALID_INODE)
-               goto out;
-       else
-               err = -ENOENT;
-      out:
+       ino = spd->usi_next_avail++;
+       down(&sb->s_lock);
+       err = __write_uin(spd, ino, branchnum, inode_number);
+       if (err)
+               spd->usi_next_avail--;
+       up(&sb->s_lock);
+out:
+       print_exit_status((int)err);
        if (!err)
-               err = uino;
+               err = ino;
+       return err;
+}
 
-       print_exit_status((int)err);
+int write_uin(struct super_block *sb, ino_t ino, int bindex, ino_t hidden_ino)
+{
+       int err;
+
+       print_entry_location();
+       err = __write_uin(stopd(sb), ino, bindex, hidden_ino);
+       print_exit_status(err);
        return err;
 }
 
diff -u -p -r1.1 -r1.2
--- unionfs-20060117-2031/unionfs.h     18 Jan 2006 03:02:19 -0000      1.1
+++ unionfs-20060117-2031/unionfs.h     18 Jan 2006 08:16:46 -0000      1.2
@@ -747,6 +747,8 @@ struct fmapent {
 /* Persistant Inode functions */
 extern ino_t get_uin(struct super_block *sb, uint8_t branchnum,
                     ino_t inode_number, int flag);
+extern int write_uin(struct super_block *sb, ino_t ino, int bindex,
+                    ino_t hidden_ino);
 extern int get_lin(struct super_block *sb, ino_t inode_number,
                   struct fmapent *entry);
 extern int parse_imap_option(struct super_block *sb,


_______________________________________________
unionfs mailing list
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs

Reply via email to