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