[SPLICE]: Don't assume regular pages in splice_to_pipe()
authorJens Axboe <jens.axboe@oracle.com>
Wed, 7 Nov 2007 07:29:47 +0000 (23:29 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 22:53:30 +0000 (14:53 -0800)
Allow caller to pass in a release function, there might be
other resources that need releasing as well. Needed for
network receive.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
fs/splice.c
include/linux/splice.h

index 56b802bfbfa4879021cc2af03f175e69cec621d8..0a0b79b01d059a1c71b632de1807100578be8269 100644 (file)
@@ -254,11 +254,16 @@ ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
        }
 
        while (page_nr < spd_pages)
-               page_cache_release(spd->pages[page_nr++]);
+               spd->spd_release(spd, page_nr++);
 
        return ret;
 }
 
+static void spd_release_page(struct splice_pipe_desc *spd, unsigned int i)
+{
+       page_cache_release(spd->pages[i]);
+}
+
 static int
 __generic_file_splice_read(struct file *in, loff_t *ppos,
                           struct pipe_inode_info *pipe, size_t len,
@@ -277,6 +282,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
                .partial = partial,
                .flags = flags,
                .ops = &page_cache_pipe_buf_ops,
+               .spd_release = spd_release_page,
        };
 
        index = *ppos >> PAGE_CACHE_SHIFT;
@@ -1432,6 +1438,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
                .partial = partial,
                .flags = flags,
                .ops = &user_page_pipe_buf_ops,
+               .spd_release = spd_release_page,
        };
 
        pipe = pipe_info(file->f_path.dentry->d_inode);
index 33e447f98a545c891192ab8b76acc78c92d6fc34..528dcb93c2f21b08cad24fd56e3a6ae8e707dbc0 100644 (file)
@@ -53,6 +53,7 @@ struct splice_pipe_desc {
        int nr_pages;                   /* number of pages in map */
        unsigned int flags;             /* splice flags */
        const struct pipe_buf_operations *ops;/* ops associated with output pipe */
+       void (*spd_release)(struct splice_pipe_desc *, unsigned int);
 };
 
 typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,