GIT: unionfs2-2.6.27.y: Unionfs: implement native unionfs_fsync/unionfs_fasync methods
Erez Zadok
ezk at fsl.cs.sunysb.edu
Thu Aug 12 23:16:49 EDT 2010
commit 040707d3fec11bb10ec773c41609fe9566bc48d1
Author: Erez_Zadok <ezk at cs.sunysb.edu>
Date: Sat Jul 21 23:56:16 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 <ezk at cs.sunysb.edu>
Conflicts:
fs/unionfs/file.c
diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
index 4ba8f6c..980f125 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 ab243cc..d08ef8b 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,
.splice_read = generic_file_splice_read,
};
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,
More information about the unionfs-cvs
mailing list