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