commit f8d8cb13b7b2ca0aa633f520e72e406d8d8ba7d6
Author: Erez_Zadok <[EMAIL PROTECTED]>
Date:   Sat Jul 21 23:47:01 2007 -0400

    Unionfs: implement native unionfs_fsync/unionfs_fasync methods
    
    Unionfs is not a block-based file system, but it has to work with both
    block-based file systems and non-block-based ones (i.e., when
    CONFIG_BLOCK=n).  We used to define our ->fsync method to file_fsync, but
    that's wrong because file_fsync partially depends on CONFIG_BLOCK=y.  And we
    didn't define an fasync method: now we have both.  Moreover, at best,
    file_fsync would have caused unionfs to sync up one lower branch---but as a
    fanout file system, we need to sync up all valid lower branches.
    
    Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>

diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index 5ce533d..a45d4ca 100644
--- a/fs/unionfs/dirfops.c
+++ b/fs/unionfs/dirfops.c
@@ -273,4 +273,6 @@ struct file_operations unionfs_dir_fops = {
        .open           = unionfs_open,
        .release        = unionfs_file_release,
        .flush          = unionfs_flush,
+       .fsync          = unionfs_fsync,
+       .fasync         = unionfs_fasync,
 };
diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
index 7b0848f..4086e30 100644
--- a/fs/unionfs/file.c
+++ b/fs/unionfs/file.c
@@ -140,6 +140,94 @@ out:
        return err;
 }
 
+int unionfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+       int bindex, bstart, bend;
+       struct file *lower_file;
+       struct dentry *lower_dentry;
+       struct inode *lower_inode, *inode;
+       int err = -EINVAL;
+
+       unionfs_read_lock(file->f_path.dentry->d_sb);
+       if ((err = unionfs_file_revalidate(file, 1)))
+               goto out;
+       unionfs_check_file(file);
+
+       bstart = fbstart(file);
+       bend = fbend(file);
+       if (bstart < 0 || bend < 0)
+               goto out;
+
+       inode = dentry->d_inode;
+       if (!inode) {
+               printk(KERN_ERR
+                      "unionfs: null lower inode in unionfs_fsync\n");
+               goto out;
+       }
+       for (bindex = bstart; bindex <= bend; bindex++) {
+               lower_inode = unionfs_lower_inode_idx(inode, bindex);
+               if (!lower_inode || !lower_inode->i_fop->fsync)
+                       continue;
+               lower_file = unionfs_lower_file_idx(file, bindex);
+               lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
+               mutex_lock(&lower_inode->i_mutex);
+               err = lower_inode->i_fop->fsync(lower_file,
+                                               lower_dentry,
+                                               datasync);
+               mutex_unlock(&lower_inode->i_mutex);
+               if (err)
+                       goto out;
+       }
+
+out:
+       unionfs_read_unlock(file->f_path.dentry->d_sb);
+       unionfs_check_file(file);
+       return err;
+}
+
+int unionfs_fasync(int fd, struct file *file, int flag)
+{
+       int bindex, bstart, bend;
+       struct file *lower_file;
+       struct dentry *dentry;
+       struct inode *lower_inode, *inode;
+       int err = 0;
+
+       unionfs_read_lock(file->f_path.dentry->d_sb);
+       if ((err = unionfs_file_revalidate(file, 1)))
+               goto out;
+       unionfs_check_file(file);
+
+       bstart = fbstart(file);
+       bend = fbend(file);
+       if (bstart < 0 || bend < 0)
+               goto out;
+
+       dentry = file->f_path.dentry;
+       inode = dentry->d_inode;
+       if (!inode) {
+               printk(KERN_ERR
+                      "unionfs: null lower inode in unionfs_fasync\n");
+               goto out;
+       }
+       for (bindex = bstart; bindex <= bend; bindex++) {
+               lower_inode = unionfs_lower_inode_idx(inode, bindex);
+               if (!lower_inode || !lower_inode->i_fop->fasync)
+                       continue;
+               lower_file = unionfs_lower_file_idx(file, bindex);
+               mutex_lock(&lower_inode->i_mutex);
+               err = lower_inode->i_fop->fasync(fd, lower_file, flag);
+               mutex_unlock(&lower_inode->i_mutex);
+               if (err)
+                       goto out;
+       }
+
+out:
+       unionfs_read_unlock(file->f_path.dentry->d_sb);
+       unionfs_check_file(file);
+       return err;
+}
+
 struct file_operations unionfs_main_fops = {
        .llseek         = generic_file_llseek,
        .read           = unionfs_read,
@@ -152,6 +240,7 @@ struct file_operations unionfs_main_fops = {
        .open           = unionfs_open,
        .flush          = unionfs_flush,
        .release        = unionfs_file_release,
-       .fsync          = file_fsync,
+       .fsync          = unionfs_fsync,
+       .fasync         = unionfs_fasync,
        .sendfile       = generic_file_sendfile,
 };
diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
index a13052b..cd1f37c 100644
--- a/fs/unionfs/union.h
+++ b/fs/unionfs/union.h
@@ -316,6 +316,9 @@ extern int unionfs_file_release(struct inode *inode, struct 
file *file);
 extern int unionfs_flush(struct file *file, fl_owner_t id);
 extern long unionfs_ioctl(struct file *file, unsigned int cmd,
                          unsigned long arg);
+extern int unionfs_fsync(struct file *file, struct dentry *dentry,
+                        int datasync);
+extern int unionfs_fasync(int fd, struct file *file, int flag);
 
 /* Inode operations */
 extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to