LCOV - code coverage report
Current view: top level - net/sunrpc - backchannel_rqst.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 0 111 0.0 %
Date: 2020-09-30 20:25:40 Functions: 0 13 0.0 %
Branches: 0 54 0.0 %

           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 : }

Generated by: LCOV version 1.14