2 * Copyright (c) 2009 Simon Wilkinson. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 /* Linux specific store operations
27 * The idea of these operations is to reduce the number of copies
28 * that data incurs when passing from the disk cache through to the
29 * RX layer, and vice versa.
31 * In kernels which support it, we use the splice() operation - in
32 * older kernels, the filesystem's sendpage() operation is used directly.
33 * Either way, this means that we can get direct access to the page contents,
34 * rather than getting a copy.
37 #include <afsconfig.h>
38 #include "afs/param.h"
41 #if defined(HAVE_SPLICE_DIRECT_TO_ACTOR)
42 # include <linux/splice.h>
44 # include <linux/pipe_fs_i.h>
47 #include "afs/sysincludes.h"
48 #include "afsincludes.h"
50 #if defined(HAVE_SPLICE_DIRECT_TO_ACTOR)
52 afs_linux_splice_actor(struct pipe_inode_info *pipe,
53 struct pipe_buffer *buf,
54 struct splice_desc *sd)
56 struct rxfs_storeVariables *svar = sd->u.data;
60 code = buf->ops->confirm(pipe, buf);
66 /* Eventually, this could be rx_WritePage */
67 code = rx_Write(svar->call, page_address(buf->page), size);
69 return -33; /* Can't get a proper rx error out from here */
76 afs_linux_ds_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
78 return __splice_from_pipe(pipe, sd, afs_linux_splice_actor);
81 /* This is a store proc which uses splice to reduce the number
84 afs_linux_storeproc(struct storeOps *ops, void *rock, struct dcache *tdc,
85 int *shouldwake, afs_size_t *bytesXferred)
87 struct rxfs_storeVariables *svar = rock;
89 struct splice_desc sd = {
91 .total_len = tdc->f.chunkBytes,
97 /* Open the file, splice its contents */
99 cacheFp = afs_linux_raw_open(&tdc->f.inode);
100 code = splice_direct_to_actor(cacheFp, &sd, afs_linux_ds_actor);
101 filp_close(cacheFp, NULL);
104 /* If we're being called from a backing request, then wake up that
105 * request once the file server says its happy. Potentially, we should
106 * do this each time we rx_Write, but that would mean acquiring the
107 * GLOCK in the middle of our actor */
108 if (shouldwake && *shouldwake && ((*ops->status)(rock) == 0)) {
110 afs_wakeup(svar->vcache);
124 afs_linux_read_actor(read_descriptor_t *desc, struct page *page,
125 unsigned long offset, unsigned long size)
127 struct rxfs_storeVariables *svar = desc->arg.data;
128 unsigned long count = desc->count;
134 /* Eventually, this could be rx_WritePage */
135 code = rx_Write(svar->call, page_address(page) + offset, size);
138 return -33; /* Can't get a proper rx error out from here */
141 desc->count = count - size;
142 desc->written += size;
148 afs_linux_storeproc(struct storeOps *ops, void *rock, struct dcache *tdc,
149 int *shouldwake, afs_size_t *bytesXferred)
151 struct rxfs_storeVariables *svar = rock;
152 struct file *cacheFp;
156 /* Open the file, splice its contents */
158 cacheFp = afs_linux_raw_open(&tdc->f.inode);
159 code = cacheFp->f_op->sendfile(cacheFp, &offset, tdc->f.chunkBytes,
160 afs_linux_read_actor, rock);
161 filp_close(cacheFp, NULL);
164 /* If we're being called from a backing request, then wake up that
165 * request once the file server says its happy. Potentially, we should
166 * do this each time we rx_Write, but that would mean acquiring the
167 * GLOCK in the middle of our actor */
168 if (shouldwake && *shouldwake && ((*ops->status)(rock) == 0)) {
170 afs_wakeup(svar->vcache);