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 */
nrs_fifo_start(struct ptlrpc_nrs_policy * policy)79 static 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 */
nrs_fifo_stop(struct ptlrpc_nrs_policy * policy)101 static 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 */
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)129 static 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 */
159 static
nrs_fifo_req_get(struct ptlrpc_nrs_policy * policy,bool peek,bool force)160 struct 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 */
nrs_fifo_req_add(struct ptlrpc_nrs_policy * policy,struct ptlrpc_nrs_request * nrq)194 static 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 */
nrs_fifo_req_del(struct ptlrpc_nrs_policy * policy,struct ptlrpc_nrs_request * nrq)216 static 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 */
nrs_fifo_req_stop(struct ptlrpc_nrs_policy * policy,struct ptlrpc_nrs_request * nrq)233 static 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 */
247 static 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 */
260 struct 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