svcrdma: Add a type for keeping NFS RPC mapping
[safe/jmp/linux-2.6] / net / sunrpc / xprtrdma / svc_rdma.c
1 /*
2  * Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the BSD-type
8  * license below:
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  *      Redistributions of source code must retain the above copyright
15  *      notice, this list of conditions and the following disclaimer.
16  *
17  *      Redistributions in binary form must reproduce the above
18  *      copyright notice, this list of conditions and the following
19  *      disclaimer in the documentation and/or other materials provided
20  *      with the distribution.
21  *
22  *      Neither the name of the Network Appliance, Inc. nor the names of
23  *      its contributors may be used to endorse or promote products
24  *      derived from this software without specific prior written
25  *      permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  * Author: Tom Tucker <tom@opengridcomputing.com>
40  */
41 #include <linux/module.h>
42 #include <linux/init.h>
43 #include <linux/fs.h>
44 #include <linux/sysctl.h>
45 #include <linux/sunrpc/clnt.h>
46 #include <linux/sunrpc/sched.h>
47 #include <linux/sunrpc/svc_rdma.h>
48
49 #define RPCDBG_FACILITY RPCDBG_SVCXPRT
50
51 /* RPC/RDMA parameters */
52 unsigned int svcrdma_ord = RPCRDMA_ORD;
53 static unsigned int min_ord = 1;
54 static unsigned int max_ord = 4096;
55 unsigned int svcrdma_max_requests = RPCRDMA_MAX_REQUESTS;
56 static unsigned int min_max_requests = 4;
57 static unsigned int max_max_requests = 16384;
58 unsigned int svcrdma_max_req_size = RPCRDMA_MAX_REQ_SIZE;
59 static unsigned int min_max_inline = 4096;
60 static unsigned int max_max_inline = 65536;
61
62 atomic_t rdma_stat_recv;
63 atomic_t rdma_stat_read;
64 atomic_t rdma_stat_write;
65 atomic_t rdma_stat_sq_starve;
66 atomic_t rdma_stat_rq_starve;
67 atomic_t rdma_stat_rq_poll;
68 atomic_t rdma_stat_rq_prod;
69 atomic_t rdma_stat_sq_poll;
70 atomic_t rdma_stat_sq_prod;
71
72 /* Temporary NFS request map cache */
73 struct kmem_cache *svc_rdma_map_cachep;
74
75 /*
76  * This function implements reading and resetting an atomic_t stat
77  * variable through read/write to a proc file. Any write to the file
78  * resets the associated statistic to zero. Any read returns it's
79  * current value.
80  */
81 static int read_reset_stat(ctl_table *table, int write,
82                            struct file *filp, void __user *buffer, size_t *lenp,
83                            loff_t *ppos)
84 {
85         atomic_t *stat = (atomic_t *)table->data;
86
87         if (!stat)
88                 return -EINVAL;
89
90         if (write)
91                 atomic_set(stat, 0);
92         else {
93                 char str_buf[32];
94                 char *data;
95                 int len = snprintf(str_buf, 32, "%d\n", atomic_read(stat));
96                 if (len >= 32)
97                         return -EFAULT;
98                 len = strlen(str_buf);
99                 if (*ppos > len) {
100                         *lenp = 0;
101                         return 0;
102                 }
103                 data = &str_buf[*ppos];
104                 len -= *ppos;
105                 if (len > *lenp)
106                         len = *lenp;
107                 if (len && copy_to_user(buffer, str_buf, len))
108                         return -EFAULT;
109                 *lenp = len;
110                 *ppos += len;
111         }
112         return 0;
113 }
114
115 static struct ctl_table_header *svcrdma_table_header;
116 static ctl_table svcrdma_parm_table[] = {
117         {
118                 .procname       = "max_requests",
119                 .data           = &svcrdma_max_requests,
120                 .maxlen         = sizeof(unsigned int),
121                 .mode           = 0644,
122                 .proc_handler   = &proc_dointvec_minmax,
123                 .strategy       = &sysctl_intvec,
124                 .extra1         = &min_max_requests,
125                 .extra2         = &max_max_requests
126         },
127         {
128                 .procname       = "max_req_size",
129                 .data           = &svcrdma_max_req_size,
130                 .maxlen         = sizeof(unsigned int),
131                 .mode           = 0644,
132                 .proc_handler   = &proc_dointvec_minmax,
133                 .strategy       = &sysctl_intvec,
134                 .extra1         = &min_max_inline,
135                 .extra2         = &max_max_inline
136         },
137         {
138                 .procname       = "max_outbound_read_requests",
139                 .data           = &svcrdma_ord,
140                 .maxlen         = sizeof(unsigned int),
141                 .mode           = 0644,
142                 .proc_handler   = &proc_dointvec_minmax,
143                 .strategy       = &sysctl_intvec,
144                 .extra1         = &min_ord,
145                 .extra2         = &max_ord,
146         },
147
148         {
149                 .procname       = "rdma_stat_read",
150                 .data           = &rdma_stat_read,
151                 .maxlen         = sizeof(atomic_t),
152                 .mode           = 0644,
153                 .proc_handler   = &read_reset_stat,
154         },
155         {
156                 .procname       = "rdma_stat_recv",
157                 .data           = &rdma_stat_recv,
158                 .maxlen         = sizeof(atomic_t),
159                 .mode           = 0644,
160                 .proc_handler   = &read_reset_stat,
161         },
162         {
163                 .procname       = "rdma_stat_write",
164                 .data           = &rdma_stat_write,
165                 .maxlen         = sizeof(atomic_t),
166                 .mode           = 0644,
167                 .proc_handler   = &read_reset_stat,
168         },
169         {
170                 .procname       = "rdma_stat_sq_starve",
171                 .data           = &rdma_stat_sq_starve,
172                 .maxlen         = sizeof(atomic_t),
173                 .mode           = 0644,
174                 .proc_handler   = &read_reset_stat,
175         },
176         {
177                 .procname       = "rdma_stat_rq_starve",
178                 .data           = &rdma_stat_rq_starve,
179                 .maxlen         = sizeof(atomic_t),
180                 .mode           = 0644,
181                 .proc_handler   = &read_reset_stat,
182         },
183         {
184                 .procname       = "rdma_stat_rq_poll",
185                 .data           = &rdma_stat_rq_poll,
186                 .maxlen         = sizeof(atomic_t),
187                 .mode           = 0644,
188                 .proc_handler   = &read_reset_stat,
189         },
190         {
191                 .procname       = "rdma_stat_rq_prod",
192                 .data           = &rdma_stat_rq_prod,
193                 .maxlen         = sizeof(atomic_t),
194                 .mode           = 0644,
195                 .proc_handler   = &read_reset_stat,
196         },
197         {
198                 .procname       = "rdma_stat_sq_poll",
199                 .data           = &rdma_stat_sq_poll,
200                 .maxlen         = sizeof(atomic_t),
201                 .mode           = 0644,
202                 .proc_handler   = &read_reset_stat,
203         },
204         {
205                 .procname       = "rdma_stat_sq_prod",
206                 .data           = &rdma_stat_sq_prod,
207                 .maxlen         = sizeof(atomic_t),
208                 .mode           = 0644,
209                 .proc_handler   = &read_reset_stat,
210         },
211         {
212                 .ctl_name = 0,
213         },
214 };
215
216 static ctl_table svcrdma_table[] = {
217         {
218                 .procname       = "svc_rdma",
219                 .mode           = 0555,
220                 .child          = svcrdma_parm_table
221         },
222         {
223                 .ctl_name = 0,
224         },
225 };
226
227 static ctl_table svcrdma_root_table[] = {
228         {
229                 .ctl_name       = CTL_SUNRPC,
230                 .procname       = "sunrpc",
231                 .mode           = 0555,
232                 .child          = svcrdma_table
233         },
234         {
235                 .ctl_name = 0,
236         },
237 };
238
239 void svc_rdma_cleanup(void)
240 {
241         dprintk("SVCRDMA Module Removed, deregister RPC RDMA transport\n");
242         if (svcrdma_table_header) {
243                 unregister_sysctl_table(svcrdma_table_header);
244                 svcrdma_table_header = NULL;
245         }
246         svc_unreg_xprt_class(&svc_rdma_class);
247         kmem_cache_destroy(svc_rdma_map_cachep);
248 }
249
250 int svc_rdma_init(void)
251 {
252         dprintk("SVCRDMA Module Init, register RPC RDMA transport\n");
253         dprintk("\tsvcrdma_ord      : %d\n", svcrdma_ord);
254         dprintk("\tmax_requests     : %d\n", svcrdma_max_requests);
255         dprintk("\tsq_depth         : %d\n",
256                 svcrdma_max_requests * RPCRDMA_SQ_DEPTH_MULT);
257         dprintk("\tmax_inline       : %d\n", svcrdma_max_req_size);
258         if (!svcrdma_table_header)
259                 svcrdma_table_header =
260                         register_sysctl_table(svcrdma_root_table);
261
262         /* Create the temporary map cache */
263         svc_rdma_map_cachep = kmem_cache_create("svc_rdma_map_cache",
264                                                 sizeof(struct svc_rdma_req_map),
265                                                 0,
266                                                 SLAB_HWCACHE_ALIGN,
267                                                 NULL);
268         if (!svc_rdma_map_cachep) {
269                 printk(KERN_INFO "Could not allocate map cache.\n");
270                 goto err;
271         }
272
273         /* Register RDMA with the SVC transport switch */
274         svc_reg_xprt_class(&svc_rdma_class);
275         return 0;
276
277  err:
278         unregister_sysctl_table(svcrdma_table_header);
279         return -ENOMEM;
280 }
281 MODULE_AUTHOR("Tom Tucker <tom@opengridcomputing.com>");
282 MODULE_DESCRIPTION("SVC RDMA Transport");
283 MODULE_LICENSE("Dual BSD/GPL");
284 module_init(svc_rdma_init);
285 module_exit(svc_rdma_cleanup);