From: Erez Zadok Date: Tue, 15 Apr 2008 20:20:17 +0000 (-0400) Subject: Unionfs: implement splice_read/write methods directly X-Git-Tag: unionfs-2.3.3~14 X-Git-Url: https://git.fsl.cs.sunysb.edu/?a=commitdiff_plain;h=0c9ceaa3ee6cac81d52e11b08f3fdf5cd35bbb75;p=unionfs-2.6.22.y.git Unionfs: implement splice_read/write methods directly Must implement splice_read/write directly, using VFS helpers, because we can no longer rely on generic_file_splice_read/write: they need address_space_operations implemented, which we no longer have. Signed-off-by: Erez Zadok --- diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c index ee8dd6f6355..6141efc6ccc 100644 --- a/fs/unionfs/file.c +++ b/fs/unionfs/file.c @@ -173,6 +173,66 @@ out: return err; } +static ssize_t unionfs_splice_read(struct file *file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + ssize_t err; + struct file *lower_file; + struct dentry *dentry = file->f_path.dentry; + + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); + err = unionfs_file_revalidate(file, false); + if (unlikely(err)) + goto out; + + lower_file = unionfs_lower_file(file); + err = vfs_splice_to(lower_file, ppos, pipe, len, flags); + /* update our inode atime upon a successful lower splice-read */ + if (err >= 0) { + fsstack_copy_attr_atime(dentry->d_inode, + lower_file->f_path.dentry->d_inode); + unionfs_check_file(file); + } + +out: + unionfs_unlock_dentry(dentry); + unionfs_read_unlock(dentry->d_sb); + return err; +} + +static ssize_t unionfs_splice_write(struct pipe_inode_info *pipe, + struct file *file, loff_t *ppos, + size_t len, unsigned int flags) +{ + ssize_t err = 0; + struct file *lower_file; + struct dentry *dentry = file->f_path.dentry; + + unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT); + unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD); + err = unionfs_file_revalidate(file, true); + if (unlikely(err)) + goto out; + + lower_file = unionfs_lower_file(file); + err = vfs_splice_from(pipe, lower_file, ppos, len, flags); + /* update our inode times+sizes upon a successful lower write */ + if (err >= 0) { + fsstack_copy_inode_size(dentry->d_inode, + lower_file->f_path.dentry->d_inode); + fsstack_copy_attr_times(dentry->d_inode, + lower_file->f_path.dentry->d_inode); + unionfs_check_file(file); + } + +out: + unionfs_unlock_dentry(dentry); + unionfs_read_unlock(dentry->d_sb); + return err; +} + struct file_operations unionfs_main_fops = { .llseek = generic_file_llseek, .read = do_sync_read, @@ -188,4 +248,6 @@ struct file_operations unionfs_main_fops = { .fsync = unionfs_fsync, .fasync = unionfs_fasync, .sendfile = generic_file_sendfile, + .splice_read = unionfs_splice_read, + .splice_write = unionfs_splice_write, };