GNU Linux-libre 4.14.294-gnu1
[releases.git] / drivers / staging / lustre / lustre / ptlrpc / nrs_fifo.c
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  * 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
46 #include <obd_support.h>
47 #include <obd_class.h>
48 #include <linux/libcfs/libcfs.h>
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
79         head = kzalloc_node(sizeof(*head), GFP_NOFS,
80                             cfs_cpt_spread_node(nrs_pol2cptab(policy),
81                                                 nrs_pol2cptid(policy)));
82         if (!head)
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
103         LASSERT(head);
104         LASSERT(list_empty(&head->fh_list));
105
106         kfree(head);
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
158 struct ptlrpc_nrs_request *nrs_fifo_req_get(struct ptlrpc_nrs_policy *policy,
159                                             bool peek, bool force)
160 {
161         struct nrs_fifo_head *head = policy->pol_private;
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
168         if (likely(!peek && nrq)) {
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
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);
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
237         CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: %llu\n",
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 */