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_LINUX_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_LINUX_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, kmap(buf->page), size);
70 size = -33; /* Can't get a proper rx error out from here */
78 afs_linux_ds_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
80 return __splice_from_pipe(pipe, sd, afs_linux_splice_actor);
83 /* This is a store proc which uses splice to reduce the number
86 afs_linux_storeproc(struct storeOps *ops, void *rock, struct dcache *tdc,
87 int *shouldwake, afs_size_t *bytesXferred)
89 struct rxfs_storeVariables *svar = rock;
91 struct splice_desc sd = {
93 .total_len = tdc->f.chunkBytes,
99 /* Open the file, splice its contents */
101 cacheFp = afs_linux_raw_open(&tdc->f.inode);
102 code = splice_direct_to_actor(cacheFp, &sd, afs_linux_ds_actor);
103 filp_close(cacheFp, NULL);
106 /* If we're being called from a backing request, then wake up that
107 * request once the file server says its happy. Potentially, we should
108 * do this each time we rx_Write, but that would mean acquiring the
109 * GLOCK in the middle of our actor */
110 if (shouldwake && *shouldwake && ((*ops->status)(rock) == 0)) {
112 afs_wakeup(svar->vcache);
126 afs_linux_read_actor(read_descriptor_t *desc, struct page *page,
127 unsigned long offset, unsigned long size)
129 #ifdef READ_DESCRIPTOR_T_HAS_BUF
130 struct rxfs_storeVariables *svar = (void *) desc->buf;
132 struct rxfs_storeVariables *svar = desc->arg.data;
134 unsigned long count = desc->count;
140 /* Eventually, this could be rx_WritePage */
141 code = rx_Write(svar->call, kmap(page) + offset, size);
145 return -33; /* Can't get a proper rx error out from here */
148 desc->count = count - size;
149 desc->written += size;
155 afs_linux_storeproc(struct storeOps *ops, void *rock, struct dcache *tdc,
156 int *shouldwake, afs_size_t *bytesXferred)
158 struct rxfs_storeVariables *svar = rock;
159 struct file *cacheFp;
163 /* Open the file, splice its contents */
165 cacheFp = afs_linux_raw_open(&tdc->f.inode);
166 code = cacheFp->f_op->sendfile(cacheFp, &offset, tdc->f.chunkBytes,
167 afs_linux_read_actor, rock);
168 filp_close(cacheFp, NULL);
171 /* If we're being called from a backing request, then wake up that
172 * request once the file server says its happy. Potentially, we should
173 * do this each time we rx_Write, but that would mean acquiring the
174 * GLOCK in the middle of our actor */
175 if (shouldwake && *shouldwake && ((*ops->status)(rock) == 0)) {
177 afs_wakeup(svar->vcache);