linux/drivers/staging/lustre/lustre/ptlrpc/nrs_fifo.c
<<
>>
Prefs
   1/*
   2 * GPL HEADER START
   3 *
   4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 only,
   8 * as published by the Free Software Foundation.
   9
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License version 2 for more details.  A copy is
  14 * included in the COPYING file that accompanied this code.
  15
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 *
  20 * GPL HEADER END
  21 */
  22/*
  23 * Copyright (c) 2011 Intel Corporation
  24 *
  25 * Copyright 2012 Xyratex Technology Limited
  26 */
  27/*
  28 * lustre/ptlrpc/nrs_fifo.c
  29 *
  30 * Network Request Scheduler (NRS) FIFO policy
  31 *
  32 * Handles RPCs in a FIFO manner, as received from the network. This policy is
  33 * a logical wrapper around previous, non-NRS functionality. It is used as the
  34 * default and fallback policy for all types of RPCs on all PTLRPC service
  35 * partitions, for both regular and high-priority NRS heads. Default here means
  36 * the policy is the one enabled at PTLRPC service partition startup time, and
  37 * fallback means the policy is used to handle RPCs that are not handled
  38 * successfully or are not handled at all by any primary policy that may be
  39 * enabled on a given NRS head.
  40 *
  41 * Author: Liang Zhen <liang@whamcloud.com>
  42 * Author: Nikitas Angelinas <nikitas_angelinas@xyratex.com>
  43 */
  44/**
  45 * \addtogoup nrs
  46 * @{
  47 */
  48
  49#define DEBUG_SUBSYSTEM S_RPC
  50#include "../include/obd_support.h"
  51#include "../include/obd_class.h"
  52#include "../../include/linux/libcfs/libcfs.h"
  53#include "ptlrpc_internal.h"
  54
  55/**
  56 * \name fifo
  57 *
  58 * The FIFO policy is a logical wrapper around previous, non-NRS functionality.
  59 * It schedules RPCs in the same order as they are queued from LNet.
  60 *
  61 * @{
  62 */
  63
  64#define NRS_POL_NAME_FIFO       "fifo"
  65
  66/**
  67 * Is called before the policy transitions into
  68 * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED; allocates and initializes a
  69 * policy-specific private data structure.
  70 *
  71 * \param[in] policy The policy to start
  72 *
  73 * \retval -ENOMEM OOM error
  74 * \retval  0      success
  75 *
  76 * \see nrs_policy_register()
  77 * \see nrs_policy_ctl()
  78 */
  79static int nrs_fifo_start(struct ptlrpc_nrs_policy *policy)
  80{
  81        struct nrs_fifo_head *head;
  82
  83        OBD_CPT_ALLOC_PTR(head, nrs_pol2cptab(policy), nrs_pol2cptid(policy));
  84        if (head == NULL)
  85                return -ENOMEM;
  86
  87        INIT_LIST_HEAD(&head->fh_list);
  88        policy->pol_private = head;
  89        return 0;
  90}
  91
  92/**
  93 * Is called before the policy transitions into
  94 * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED; deallocates the policy-specific
  95 * private data structure.
  96 *
  97 * \param[in] policy The policy to stop
  98 *
  99 * \see nrs_policy_stop0()
 100 */
 101static void nrs_fifo_stop(struct ptlrpc_nrs_policy *policy)
 102{
 103        struct nrs_fifo_head *head = policy->pol_private;
 104
 105        LASSERT(head != NULL);
 106        LASSERT(list_empty(&head->fh_list));
 107
 108        OBD_FREE_PTR(head);
 109}
 110
 111/**
 112 * Is called for obtaining a FIFO policy resource.
 113 *
 114 * \param[in]  policy     The policy on which the request is being asked for
 115 * \param[in]  nrq        The request for which resources are being taken
 116 * \param[in]  parent     Parent resource, unused in this policy
 117 * \param[out] resp       Resources references are placed in this array
 118 * \param[in]  moving_req Signifies limited caller context; unused in this
 119 *                        policy
 120 *
 121 * \retval 1 The FIFO policy only has a one-level resource hierarchy, as since
 122 *           it implements a simple scheduling algorithm in which request
 123 *           priority is determined on the request arrival order, it does not
 124 *           need to maintain a set of resources that would otherwise be used
 125 *           to calculate a request's priority.
 126 *
 127 * \see nrs_resource_get_safe()
 128 */
 129static int nrs_fifo_res_get(struct ptlrpc_nrs_policy *policy,
 130                            struct ptlrpc_nrs_request *nrq,
 131                            const struct ptlrpc_nrs_resource *parent,
 132                            struct ptlrpc_nrs_resource **resp, bool moving_req)
 133{
 134        /**
 135         * Just return the resource embedded inside nrs_fifo_head, and end this
 136         * resource hierarchy reference request.
 137         */
 138        *resp = &((struct nrs_fifo_head *)policy->pol_private)->fh_res;
 139        return 1;
 140}
 141
 142/**
 143 * Called when getting a request from the FIFO policy for handling, or just
 144 * peeking; removes the request from the policy when it is to be handled.
 145 *
 146 * \param[in] policy The policy
 147 * \param[in] peek   When set, signifies that we just want to examine the
 148 *                   request, and not handle it, so the request is not removed
 149 *                   from the policy.
 150 * \param[in] force  Force the policy to return a request; unused in this
 151 *                   policy
 152 *
 153 * \retval The request to be handled; this is the next request in the FIFO
 154 *         queue
 155 *
 156 * \see ptlrpc_nrs_req_get_nolock()
 157 * \see nrs_request_get()
 158 */
 159static
 160struct ptlrpc_nrs_request *nrs_fifo_req_get(struct ptlrpc_nrs_policy *policy,
 161                                             bool peek, bool force)
 162{
 163        struct nrs_fifo_head      *head = policy->pol_private;
 164        struct ptlrpc_nrs_request *nrq;
 165
 166        nrq = unlikely(list_empty(&head->fh_list)) ? NULL :
 167              list_entry(head->fh_list.next, struct ptlrpc_nrs_request,
 168                             nr_u.fifo.fr_list);
 169
 170        if (likely(!peek && nrq != NULL)) {
 171                struct ptlrpc_request *req = container_of(nrq,
 172                                                          struct ptlrpc_request,
 173                                                          rq_nrq);
 174
 175                list_del_init(&nrq->nr_u.fifo.fr_list);
 176
 177                CDEBUG(D_RPCTRACE, "NRS start %s request from %s, seq: %llu\n",
 178                       policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer),
 179                       nrq->nr_u.fifo.fr_sequence);
 180        }
 181
 182        return nrq;
 183}
 184
 185/**
 186 * Adds request \a nrq to \a policy's list of queued requests
 187 *
 188 * \param[in] policy The policy
 189 * \param[in] nrq    The request to add
 190 *
 191 * \retval 0 success; nrs_request_enqueue() assumes this function will always
 192 *                    succeed
 193 */
 194static int nrs_fifo_req_add(struct ptlrpc_nrs_policy *policy,
 195                            struct ptlrpc_nrs_request *nrq)
 196{
 197        struct nrs_fifo_head *head;
 198
 199        head = container_of(nrs_request_resource(nrq), struct nrs_fifo_head,
 200                            fh_res);
 201        /**
 202         * Only used for debugging
 203         */
 204        nrq->nr_u.fifo.fr_sequence = head->fh_sequence++;
 205        list_add_tail(&nrq->nr_u.fifo.fr_list, &head->fh_list);
 206
 207        return 0;
 208}
 209
 210/**
 211 * Removes request \a nrq from \a policy's list of queued requests.
 212 *
 213 * \param[in] policy The policy
 214 * \param[in] nrq    The request to remove
 215 */
 216static void nrs_fifo_req_del(struct ptlrpc_nrs_policy *policy,
 217                             struct ptlrpc_nrs_request *nrq)
 218{
 219        LASSERT(!list_empty(&nrq->nr_u.fifo.fr_list));
 220        list_del_init(&nrq->nr_u.fifo.fr_list);
 221}
 222
 223/**
 224 * Prints a debug statement right before the request \a nrq stops being
 225 * handled.
 226 *
 227 * \param[in] policy The policy handling the request
 228 * \param[in] nrq    The request being handled
 229 *
 230 * \see ptlrpc_server_finish_request()
 231 * \see ptlrpc_nrs_req_stop_nolock()
 232 */
 233static void nrs_fifo_req_stop(struct ptlrpc_nrs_policy *policy,
 234                              struct ptlrpc_nrs_request *nrq)
 235{
 236        struct ptlrpc_request *req = container_of(nrq, struct ptlrpc_request,
 237                                                  rq_nrq);
 238
 239        CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: %llu\n",
 240               policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer),
 241               nrq->nr_u.fifo.fr_sequence);
 242}
 243
 244/**
 245 * FIFO policy operations
 246 */
 247static const struct ptlrpc_nrs_pol_ops nrs_fifo_ops = {
 248        .op_policy_start        = nrs_fifo_start,
 249        .op_policy_stop         = nrs_fifo_stop,
 250        .op_res_get             = nrs_fifo_res_get,
 251        .op_req_get             = nrs_fifo_req_get,
 252        .op_req_enqueue         = nrs_fifo_req_add,
 253        .op_req_dequeue         = nrs_fifo_req_del,
 254        .op_req_stop            = nrs_fifo_req_stop,
 255};
 256
 257/**
 258 * FIFO policy configuration
 259 */
 260struct ptlrpc_nrs_pol_conf nrs_conf_fifo = {
 261        .nc_name                = NRS_POL_NAME_FIFO,
 262        .nc_ops                 = &nrs_fifo_ops,
 263        .nc_compat              = nrs_policy_compat_all,
 264        .nc_flags               = PTLRPC_NRS_FL_FALLBACK |
 265                                  PTLRPC_NRS_FL_REG_START
 266};
 267
 268/** @} fifo */
 269
 270/** @} nrs */
 271