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