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