Branch data Line data Source code
1 : : /****************************************************************************** 2 : : 3 : : (c) 2007 Network Appliance, Inc. All Rights Reserved. 4 : : (c) 2009 NetApp. All Rights Reserved. 5 : : 6 : : NetApp provides this source code under the GPL v2 License. 7 : : The GPL v2 license is available at 8 : : http://opensource.org/licenses/gpl-license.php. 9 : : 10 : : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 11 : : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 12 : : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 13 : : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 14 : : CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 15 : : EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 16 : : PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 17 : : PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 18 : : LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 19 : : NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 20 : : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 : : 22 : : ******************************************************************************/ 23 : : 24 : : #include <linux/tcp.h> 25 : : #include <linux/slab.h> 26 : : #include <linux/sunrpc/xprt.h> 27 : : #include <linux/export.h> 28 : : #include <linux/sunrpc/bc_xprt.h> 29 : : 30 : : #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 31 : : #define RPCDBG_FACILITY RPCDBG_TRANS 32 : : #endif 33 : : 34 : : #define BC_MAX_SLOTS 64U 35 : : 36 : 0 : unsigned int xprt_bc_max_slots(struct rpc_xprt *xprt) 37 : : { 38 : 0 : return BC_MAX_SLOTS; 39 : : } 40 : : 41 : : /* 42 : : * Helper routines that track the number of preallocation elements 43 : : * on the transport. 44 : : */ 45 : : static inline int xprt_need_to_requeue(struct rpc_xprt *xprt) 46 : : { 47 : 0 : return xprt->bc_alloc_count < xprt->bc_alloc_max; 48 : : } 49 : : 50 : : /* 51 : : * Free the preallocated rpc_rqst structure and the memory 52 : : * buffers hanging off of it. 53 : : */ 54 : 0 : static void xprt_free_allocation(struct rpc_rqst *req) 55 : : { 56 : : struct xdr_buf *xbufp; 57 : : 58 : : dprintk("RPC: free allocations for req= %p\n", req); 59 : 0 : WARN_ON_ONCE(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); 60 : : xbufp = &req->rq_rcv_buf; 61 : 0 : free_page((unsigned long)xbufp->head[0].iov_base); 62 : : xbufp = &req->rq_snd_buf; 63 : 0 : free_page((unsigned long)xbufp->head[0].iov_base); 64 : 0 : kfree(req); 65 : 0 : } 66 : : 67 : 0 : static int xprt_alloc_xdr_buf(struct xdr_buf *buf, gfp_t gfp_flags) 68 : : { 69 : : struct page *page; 70 : : /* Preallocate one XDR receive buffer */ 71 : : page = alloc_page(gfp_flags); 72 : 0 : if (page == NULL) 73 : : return -ENOMEM; 74 : : xdr_buf_init(buf, page_address(page), PAGE_SIZE); 75 : 0 : return 0; 76 : : } 77 : : 78 : : static 79 : 0 : struct rpc_rqst *xprt_alloc_bc_req(struct rpc_xprt *xprt, gfp_t gfp_flags) 80 : : { 81 : : struct rpc_rqst *req; 82 : : 83 : : /* Pre-allocate one backchannel rpc_rqst */ 84 : 0 : req = kzalloc(sizeof(*req), gfp_flags); 85 : 0 : if (req == NULL) 86 : : return NULL; 87 : : 88 : 0 : req->rq_xprt = xprt; 89 : 0 : INIT_LIST_HEAD(&req->rq_bc_list); 90 : : 91 : : /* Preallocate one XDR receive buffer */ 92 : 0 : if (xprt_alloc_xdr_buf(&req->rq_rcv_buf, gfp_flags) < 0) { 93 : 0 : printk(KERN_ERR "Failed to create bc receive xbuf\n"); 94 : 0 : goto out_free; 95 : : } 96 : 0 : req->rq_rcv_buf.len = PAGE_SIZE; 97 : : 98 : : /* Preallocate one XDR send buffer */ 99 : 0 : if (xprt_alloc_xdr_buf(&req->rq_snd_buf, gfp_flags) < 0) { 100 : 0 : printk(KERN_ERR "Failed to create bc snd xbuf\n"); 101 : 0 : goto out_free; 102 : : } 103 : : return req; 104 : : out_free: 105 : 0 : xprt_free_allocation(req); 106 : 0 : return NULL; 107 : : } 108 : : 109 : : /* 110 : : * Preallocate up to min_reqs structures and related buffers for use 111 : : * by the backchannel. This function can be called multiple times 112 : : * when creating new sessions that use the same rpc_xprt. The 113 : : * preallocated buffers are added to the pool of resources used by 114 : : * the rpc_xprt. Anyone of these resources may be used used by an 115 : : * incoming callback request. It's up to the higher levels in the 116 : : * stack to enforce that the maximum number of session slots is not 117 : : * being exceeded. 118 : : * 119 : : * Some callback arguments can be large. For example, a pNFS server 120 : : * using multiple deviceids. The list can be unbound, but the client 121 : : * has the ability to tell the server the maximum size of the callback 122 : : * requests. Each deviceID is 16 bytes, so allocate one page 123 : : * for the arguments to have enough room to receive a number of these 124 : : * deviceIDs. The NFS client indicates to the pNFS server that its 125 : : * callback requests can be up to 4096 bytes in size. 126 : : */ 127 : 0 : int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs) 128 : : { 129 : 0 : if (!xprt->ops->bc_setup) 130 : : return 0; 131 : 0 : return xprt->ops->bc_setup(xprt, min_reqs); 132 : : } 133 : : EXPORT_SYMBOL_GPL(xprt_setup_backchannel); 134 : : 135 : 0 : int xprt_setup_bc(struct rpc_xprt *xprt, unsigned int min_reqs) 136 : : { 137 : : struct rpc_rqst *req; 138 : : struct list_head tmp_list; 139 : : int i; 140 : : 141 : : dprintk("RPC: setup backchannel transport\n"); 142 : : 143 : 0 : if (min_reqs > BC_MAX_SLOTS) 144 : : min_reqs = BC_MAX_SLOTS; 145 : : 146 : : /* 147 : : * We use a temporary list to keep track of the preallocated 148 : : * buffers. Once we're done building the list we splice it 149 : : * into the backchannel preallocation list off of the rpc_xprt 150 : : * struct. This helps minimize the amount of time the list 151 : : * lock is held on the rpc_xprt struct. It also makes cleanup 152 : : * easier in case of memory allocation errors. 153 : : */ 154 : : INIT_LIST_HEAD(&tmp_list); 155 : 0 : for (i = 0; i < min_reqs; i++) { 156 : : /* Pre-allocate one backchannel rpc_rqst */ 157 : 0 : req = xprt_alloc_bc_req(xprt, GFP_KERNEL); 158 : 0 : if (req == NULL) { 159 : 0 : printk(KERN_ERR "Failed to create bc rpc_rqst\n"); 160 : : goto out_free; 161 : : } 162 : : 163 : : /* Add the allocated buffer to the tmp list */ 164 : : dprintk("RPC: adding req= %p\n", req); 165 : 0 : list_add(&req->rq_bc_pa_list, &tmp_list); 166 : : } 167 : : 168 : : /* 169 : : * Add the temporary list to the backchannel preallocation list 170 : : */ 171 : : spin_lock(&xprt->bc_pa_lock); 172 : 0 : list_splice(&tmp_list, &xprt->bc_pa_list); 173 : 0 : xprt->bc_alloc_count += min_reqs; 174 : 0 : xprt->bc_alloc_max += min_reqs; 175 : 0 : atomic_add(min_reqs, &xprt->bc_slot_count); 176 : : spin_unlock(&xprt->bc_pa_lock); 177 : : 178 : : dprintk("RPC: setup backchannel transport done\n"); 179 : 0 : return 0; 180 : : 181 : : out_free: 182 : : /* 183 : : * Memory allocation failed, free the temporary list 184 : : */ 185 : 0 : while (!list_empty(&tmp_list)) { 186 : 0 : req = list_first_entry(&tmp_list, 187 : : struct rpc_rqst, 188 : : rq_bc_pa_list); 189 : : list_del(&req->rq_bc_pa_list); 190 : 0 : xprt_free_allocation(req); 191 : : } 192 : : 193 : : dprintk("RPC: setup backchannel transport failed\n"); 194 : : return -ENOMEM; 195 : : } 196 : : 197 : : /** 198 : : * xprt_destroy_backchannel - Destroys the backchannel preallocated structures. 199 : : * @xprt: the transport holding the preallocated strucures 200 : : * @max_reqs: the maximum number of preallocated structures to destroy 201 : : * 202 : : * Since these structures may have been allocated by multiple calls 203 : : * to xprt_setup_backchannel, we only destroy up to the maximum number 204 : : * of reqs specified by the caller. 205 : : */ 206 : 0 : void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) 207 : : { 208 : 0 : if (xprt->ops->bc_destroy) 209 : 0 : xprt->ops->bc_destroy(xprt, max_reqs); 210 : 0 : } 211 : : EXPORT_SYMBOL_GPL(xprt_destroy_backchannel); 212 : : 213 : 0 : void xprt_destroy_bc(struct rpc_xprt *xprt, unsigned int max_reqs) 214 : : { 215 : : struct rpc_rqst *req = NULL, *tmp = NULL; 216 : : 217 : : dprintk("RPC: destroy backchannel transport\n"); 218 : : 219 : 0 : if (max_reqs == 0) 220 : : goto out; 221 : : 222 : : spin_lock_bh(&xprt->bc_pa_lock); 223 : 0 : xprt->bc_alloc_max -= min(max_reqs, xprt->bc_alloc_max); 224 : 0 : list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { 225 : : dprintk("RPC: req=%p\n", req); 226 : : list_del(&req->rq_bc_pa_list); 227 : 0 : xprt_free_allocation(req); 228 : 0 : xprt->bc_alloc_count--; 229 : 0 : atomic_dec(&xprt->bc_slot_count); 230 : 0 : if (--max_reqs == 0) 231 : : break; 232 : : } 233 : : spin_unlock_bh(&xprt->bc_pa_lock); 234 : : 235 : : out: 236 : : dprintk("RPC: backchannel list empty= %s\n", 237 : : list_empty(&xprt->bc_pa_list) ? "true" : "false"); 238 : 0 : } 239 : : 240 : 0 : static struct rpc_rqst *xprt_get_bc_request(struct rpc_xprt *xprt, __be32 xid, 241 : : struct rpc_rqst *new) 242 : : { 243 : : struct rpc_rqst *req = NULL; 244 : : 245 : : dprintk("RPC: allocate a backchannel request\n"); 246 : 0 : if (list_empty(&xprt->bc_pa_list)) { 247 : 0 : if (!new) 248 : : goto not_found; 249 : 0 : if (atomic_read(&xprt->bc_slot_count) >= BC_MAX_SLOTS) 250 : : goto not_found; 251 : 0 : list_add_tail(&new->rq_bc_pa_list, &xprt->bc_pa_list); 252 : 0 : xprt->bc_alloc_count++; 253 : 0 : atomic_inc(&xprt->bc_slot_count); 254 : : } 255 : 0 : req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst, 256 : : rq_bc_pa_list); 257 : 0 : req->rq_reply_bytes_recvd = 0; 258 : 0 : memcpy(&req->rq_private_buf, &req->rq_rcv_buf, 259 : : sizeof(req->rq_private_buf)); 260 : 0 : req->rq_xid = xid; 261 : 0 : req->rq_connect_cookie = xprt->connect_cookie; 262 : : dprintk("RPC: backchannel req=%p\n", req); 263 : : not_found: 264 : 0 : return req; 265 : : } 266 : : 267 : : /* 268 : : * Return the preallocated rpc_rqst structure and XDR buffers 269 : : * associated with this rpc_task. 270 : : */ 271 : 0 : void xprt_free_bc_request(struct rpc_rqst *req) 272 : : { 273 : 0 : struct rpc_xprt *xprt = req->rq_xprt; 274 : : 275 : 0 : xprt->ops->bc_free_rqst(req); 276 : 0 : } 277 : : 278 : 0 : void xprt_free_bc_rqst(struct rpc_rqst *req) 279 : : { 280 : 0 : struct rpc_xprt *xprt = req->rq_xprt; 281 : : 282 : : dprintk("RPC: free backchannel req=%p\n", req); 283 : : 284 : 0 : req->rq_connect_cookie = xprt->connect_cookie - 1; 285 : 0 : smp_mb__before_atomic(); 286 : 0 : clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); 287 : 0 : smp_mb__after_atomic(); 288 : : 289 : : /* 290 : : * Return it to the list of preallocations so that it 291 : : * may be reused by a new callback request. 292 : : */ 293 : : spin_lock_bh(&xprt->bc_pa_lock); 294 : 0 : if (xprt_need_to_requeue(xprt)) { 295 : 0 : list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list); 296 : 0 : xprt->bc_alloc_count++; 297 : 0 : atomic_inc(&xprt->bc_slot_count); 298 : : req = NULL; 299 : : } 300 : : spin_unlock_bh(&xprt->bc_pa_lock); 301 : 0 : if (req != NULL) { 302 : : /* 303 : : * The last remaining session was destroyed while this 304 : : * entry was in use. Free the entry and don't attempt 305 : : * to add back to the list because there is no need to 306 : : * have anymore preallocated entries. 307 : : */ 308 : : dprintk("RPC: Last session removed req=%p\n", req); 309 : 0 : xprt_free_allocation(req); 310 : : } 311 : 0 : xprt_put(xprt); 312 : 0 : } 313 : : 314 : : /* 315 : : * One or more rpc_rqst structure have been preallocated during the 316 : : * backchannel setup. Buffer space for the send and private XDR buffers 317 : : * has been preallocated as well. Use xprt_alloc_bc_request to allocate 318 : : * to this request. Use xprt_free_bc_request to return it. 319 : : * 320 : : * We know that we're called in soft interrupt context, grab the spin_lock 321 : : * since there is no need to grab the bottom half spin_lock. 322 : : * 323 : : * Return an available rpc_rqst, otherwise NULL if non are available. 324 : : */ 325 : 0 : struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid) 326 : : { 327 : : struct rpc_rqst *req, *new = NULL; 328 : : 329 : : do { 330 : : spin_lock(&xprt->bc_pa_lock); 331 : 0 : list_for_each_entry(req, &xprt->bc_pa_list, rq_bc_pa_list) { 332 : 0 : if (req->rq_connect_cookie != xprt->connect_cookie) 333 : 0 : continue; 334 : 0 : if (req->rq_xid == xid) 335 : : goto found; 336 : : } 337 : 0 : req = xprt_get_bc_request(xprt, xid, new); 338 : : found: 339 : : spin_unlock(&xprt->bc_pa_lock); 340 : 0 : if (new) { 341 : 0 : if (req != new) 342 : 0 : xprt_free_allocation(new); 343 : : break; 344 : 0 : } else if (req) 345 : : break; 346 : 0 : new = xprt_alloc_bc_req(xprt, GFP_KERNEL); 347 : 0 : } while (new); 348 : 0 : return req; 349 : : } 350 : : 351 : : /* 352 : : * Add callback request to callback list. The callback 353 : : * service sleeps on the sv_cb_waitq waiting for new 354 : : * requests. Wake it up after adding enqueing the 355 : : * request. 356 : : */ 357 : 0 : void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) 358 : : { 359 : 0 : struct rpc_xprt *xprt = req->rq_xprt; 360 : 0 : struct svc_serv *bc_serv = xprt->bc_serv; 361 : : 362 : : spin_lock(&xprt->bc_pa_lock); 363 : : list_del(&req->rq_bc_pa_list); 364 : 0 : xprt->bc_alloc_count--; 365 : : spin_unlock(&xprt->bc_pa_lock); 366 : : 367 : 0 : req->rq_private_buf.len = copied; 368 : 0 : set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); 369 : : 370 : : dprintk("RPC: add callback request to list\n"); 371 : 0 : xprt_get(xprt); 372 : : spin_lock(&bc_serv->sv_cb_lock); 373 : 0 : list_add(&req->rq_bc_list, &bc_serv->sv_cb_list); 374 : 0 : wake_up(&bc_serv->sv_cb_waitq); 375 : : spin_unlock(&bc_serv->sv_cb_lock); 376 : 0 : }