Unionfs: support splice(2)
authorErez Zadok <ezk@cs.sunysb.edu>
Sun, 25 Nov 2007 01:05:47 +0000 (20:05 -0500)
committerErez Zadok <ezk@cs.sunysb.edu>
Tue, 31 Jan 2012 04:57:08 +0000 (23:57 -0500)
Also remove redundant variable from unionfs_readpage (saves a bit on stack
space).

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/unionfs/file.c
fs/unionfs/mmap.c

index cfbfb8e9cbbbc31e4be7efc4d18598e0614f30d3..b7d0d555cc62508a194998320d58837e2076eaf7 100644 (file)
@@ -246,4 +246,5 @@ struct file_operations unionfs_main_fops = {
        .fsync          = unionfs_fsync,
        .fasync         = unionfs_fasync,
        .splice_read    = generic_file_splice_read,
+       .splice_write   = generic_file_splice_write,
 };
index fa358ef3a6df0b6396dda2e359982b78eb746150..623a91362ffd05674a0e27e8747b43adb806ffce 100644 (file)
@@ -147,7 +147,7 @@ static int unionfs_readpage(struct file *file, struct page *page)
        struct inode *inode;
        mm_segment_t old_fs;
        char *page_data = NULL;
-       loff_t offset;
+       mode_t orig_mode;
 
        unionfs_read_lock(file->f_path.dentry->d_sb);
        err = unionfs_file_revalidate(file, false);
@@ -175,11 +175,17 @@ static int unionfs_readpage(struct file *file, struct page *page)
         * the necessary magic for us.
         */
        lower_file->f_pos = page_offset(page);
-       offset = page_offset(page);
        old_fs = get_fs();
        set_fs(KERNEL_DS);
+       /*
+        * generic_file_splice_write may call us on a file not opened for
+        * reading, so temporarily allow reading.
+        */
+       orig_mode = lower_file->f_mode;
+       lower_file->f_mode |= FMODE_READ;
        err = vfs_read(lower_file, page_data, PAGE_CACHE_SIZE,
                       &lower_file->f_pos);
+       lower_file->f_mode = orig_mode;
        set_fs(old_fs);
        if (err >= 0 && err < PAGE_CACHE_SIZE)
                memset(page_data + err, 0, PAGE_CACHE_SIZE - err);