mmap: file revalidation and fanout invariant validation
authorErez_Zadok <ezk@cs.sunysb.edu>
Sat, 19 May 2007 23:59:13 +0000 (19:59 -0400)
committerErez_Zadok <ezk@cs.sunysb.edu>
Mon, 23 Jul 2007 00:50:41 +0000 (20:50 -0400)
Added the newer checks to file revalidation and fanout invariants to the
newly merged mmap code.  Also minor mmap related comments added.

fs/unionfs/commonfops.c
fs/unionfs/copyup.c
fs/unionfs/file.c
fs/unionfs/inode.c
fs/unionfs/mmap.c

index b0ec71b03b0180b24fa27ca69580e409c2684acf..0ae465a40f592ef6c7284ba314aabdb9b005e7cb 100644 (file)
@@ -609,13 +609,6 @@ int unionfs_file_release(struct inode *inode, struct file *file)
        int bindex, bstart, bend;
        int fgen, err = 0;
 
-       unionfs_read_lock(sb);
-       if ((err = unionfs_file_revalidate(file, 1)))
-               goto out;
-       fileinfo = UNIONFS_F(file);
-       BUG_ON(file->f_dentry->d_inode != inode);
-       inodeinfo = UNIONFS_I(inode);
-
        unionfs_check_file(file);
        unionfs_read_lock(sb);
        /*
@@ -625,6 +618,9 @@ int unionfs_file_release(struct inode *inode, struct file *file)
         */
        if ((err = unionfs_file_revalidate(file, 1)))
                goto out;
+       fileinfo = UNIONFS_F(file);
+       BUG_ON(file->f_dentry->d_inode != inode);
+       inodeinfo = UNIONFS_I(inode);
 
        /* fput all the hidden files */
        fgen = atomic_read(&fileinfo->generation);
index ea8f24e2b57554bd746f4bab35edb2ae604918d2..18203a33994c638c9e0a773740435ceec9210b20 100644 (file)
@@ -275,7 +275,8 @@ static int __copyup_reg_data(struct dentry *dentry,
        kfree(buf);
 
        if (!err)
-               err = output_file->f_op->fsync(output_file, new_hidden_dentry, 0);
+               err = output_file->f_op->fsync(output_file,
+                                              new_hidden_dentry, 0);
 
        if (err)
                goto out_close_out;
index 1c20844e705a24aebd25ac55cadeeea667db1463..59b1c918f134540e037974f2d09ab008e1857504 100644 (file)
@@ -28,6 +28,7 @@ static ssize_t unionfs_read(struct file *file, char __user *buf,
        int err;
 
        unionfs_read_lock(file->f_dentry->d_sb);
+       unionfs_check_file(file);
        if ((err = unionfs_file_revalidate(file, 0)))
                goto out;
 
@@ -46,30 +47,35 @@ out:
 static ssize_t unionfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos)
 {
-       int err;
-#error fixme fxn check_file? read_unlock?
+       int err = 0;
+       struct file *file = iocb->ki_filp;
+
+       unionfs_read_lock(file->f_dentry->d_sb);
+       unionfs_check_file(file);
+       if ((err = unionfs_file_revalidate(file, 0)))
+               goto out;
+
        err = generic_file_aio_read(iocb, iov, nr_segs, pos);
 
        if (err == -EIOCBQUEUED)
                err = wait_on_sync_kiocb(iocb);
 
        if (err >= 0)
-               touch_atime(unionfs_lower_mnt(iocb->ki_filp->f_path.dentry),
-                           unionfs_lower_dentry(iocb->ki_filp->f_path.dentry));
+               touch_atime(unionfs_lower_mnt(file->f_path.dentry),
+                           unionfs_lower_dentry(file->f_path.dentry));
 
-#if 0
 out:
        unionfs_read_unlock(file->f_dentry->d_sb);
        unionfs_check_file(file);
-#endif
        return err;
 }
 static ssize_t unionfs_write(struct file * file, const char __user * buf,
-                       size_t count, loff_t * ppos)
+                            size_t count, loff_t *ppos)
 {
        int err = 0;
 
        unionfs_read_lock(file->f_dentry->d_sb);
+       unionfs_check_file(file);
        if ((err = unionfs_file_revalidate(file, 1)))
                goto out;
 
@@ -93,6 +99,10 @@ static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
        int willwrite;
 
        unionfs_read_lock(file->f_dentry->d_sb);
+       unionfs_check_file(file);
+       if ((err = unionfs_file_revalidate(file, 1)))
+               goto out;
+
        /* This might be deferred to mmap's writepage */
        willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
        if ((err = unionfs_file_revalidate(file, willwrite)))
index 79abe8aa45c483cccc076f0c4b604ba7b78ff629..d3e0a4f1ba3ccbe9f5befbb723f28998605e1e98 100644 (file)
@@ -1084,6 +1084,7 @@ static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
                break;
        }
 
+       /* for mmap */
        if (ia->ia_valid & ATTR_SIZE) {
                if (ia->ia_size != i_size_read(inode)) {
                        err = vmtruncate(inode, ia->ia_size);
index 93aba3ae81a8e335fa288ef53c7235c1cc22fae2..ccad33f3b131c2409380121efabfd7291d568d4c 100644 (file)
@@ -163,8 +163,9 @@ int unionfs_readpage(struct file *file, struct page *page)
        int err;
 
        unionfs_read_lock(file->f_dentry->d_sb);
+       unionfs_check_file(file);
        if ((err = unionfs_file_revalidate(file, 0)))
-               goto out_err;
+               goto out;
 
        err = unionfs_do_readpage(file, page);
 
@@ -177,9 +178,9 @@ int unionfs_readpage(struct file *file, struct page *page)
         * page.  but we no longer have to wakeup on our page here, b/c
         * UnlockPage does it
         */
-
-out_err:
+out:
        unlock_page(page);
+       unionfs_check_file(file);
        unionfs_read_unlock(file->f_dentry->d_sb);
 
        return err;
@@ -191,7 +192,9 @@ int unionfs_prepare_write(struct file *file, struct page *page, unsigned from,
        int err;
 
        unionfs_read_lock(file->f_dentry->d_sb);
+       unionfs_check_file(file);
        err = unionfs_file_revalidate(file, 1);
+       unionfs_check_file(file);
        unionfs_read_unlock(file->f_dentry->d_sb);
 
        return err;
@@ -211,6 +214,7 @@ int unionfs_commit_write(struct file *file, struct page *page, unsigned from,
        BUG_ON(file == NULL);
 
        unionfs_read_lock(file->f_dentry->d_sb);
+       unionfs_check_file(file);
        if ((err = unionfs_file_revalidate(file, 1)))
                goto out;
 
@@ -220,7 +224,8 @@ int unionfs_commit_write(struct file *file, struct page *page, unsigned from,
        if (UNIONFS_F(file) != NULL)
                lower_file = unionfs_lower_file(file);
 
-       BUG_ON(lower_file == NULL);     /* FIXME: is this assertion right here? */
+       /* FIXME: is this assertion right here? */
+       BUG_ON(lower_file == NULL);
 
        page_data = (char *)kmap(page);
        lower_file->f_pos = (page->index << PAGE_CACHE_SHIFT) + from;
@@ -261,6 +266,7 @@ out:
                ClearPageUptodate(page);
 
        unionfs_read_unlock(file->f_dentry->d_sb);
+       unionfs_check_file(file);
        return err;             /* assume all is ok */
 }
 
@@ -281,6 +287,10 @@ void unionfs_sync_page(struct page *page)
 
        /* do the actual sync */
        mapping = lower_page->mapping;
+       /*
+        * XXX: can we optimize ala RAIF and set the lower page to be
+        * discarded after a successful sync_page?
+        */
        if (mapping && mapping->a_ops && mapping->a_ops->sync_page)
                mapping->a_ops->sync_page(lower_page);