Whamcloud - gitweb
94fafee78f522fb98212e6d104949c361636ce40
[fs/lustre-release.git] / 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  * 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 #ifndef __KERNEL__
51 #include <liblustre.h>
52 #endif
53 #include <obd_support.h>
54 #include <obd_class.h>
55 #include <libcfs/libcfs.h>
56 #include "ptlrpc_internal.h"
57
58 /**
59  * \name fifo
60  *
61  * The FIFO policy is a logical wrapper around previous, non-NRS functionality.
62  * It schedules RPCs in the same order as they are queued from LNet.
63  *
64  * @{
65  */
66
67 #define NRS_POL_NAME_FIFO       "fifo"
68
69 /**
70  * Is called before the policy transitions into
71  * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED; allocates and initializes a
72  * policy-specific private data structure.
73  *
74  * \param[in] policy The policy to start
75  *
76  * \retval -ENOMEM OOM error
77  * \retval  0      success
78  *
79  * \see nrs_policy_register()
80  * \see nrs_policy_ctl()
81  */
82 static int nrs_fifo_start(struct ptlrpc_nrs_policy *policy, char *arg)
83 {
84         struct nrs_fifo_head *head;
85
86         OBD_CPT_ALLOC_PTR(head, nrs_pol2cptab(policy), nrs_pol2cptid(policy));
87         if (head == NULL)
88                 return -ENOMEM;
89
90         CFS_INIT_LIST_HEAD(&head->fh_list);
91         policy->pol_private = head;
92         return 0;
93 }
94
95 /**
96  * Is called before the policy transitions into
97  * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED; deallocates the policy-specific
98  * private data structure.
99  *
100  * \param[in] policy The policy to stop
101  *
102  * \see nrs_policy_stop0()
103  */
104 static void nrs_fifo_stop(struct ptlrpc_nrs_policy *policy)
105 {
106         struct nrs_fifo_head *head = policy->pol_private;
107
108         LASSERT(head != NULL);
109         LASSERT(cfs_list_empty(&head->fh_list));
110
111         OBD_FREE_PTR(head);
112 }
113
114 /**
115  * Is called for obtaining a FIFO policy resource.
116  *
117  * \param[in]  policy     The policy on which the request is being asked for
118  * \param[in]  nrq        The request for which resources are being taken
119  * \param[in]  parent     Parent resource, unused in this policy
120  * \param[out] resp       Resources references are placed in this array
121  * \param[in]  moving_req Signifies limited caller context; unused in this
122  *                        policy
123  *
124  * \retval 1 The FIFO policy only has a one-level resource hierarchy, as since
125  *           it implements a simple scheduling algorithm in which request
126  *           priority is determined on the request arrival order, it does not
127  *           need to maintain a set of resources that would otherwise be used
128  *           to calculate a request's priority.
129  *
130  * \see nrs_resource_get_safe()
131  */
132 static int nrs_fifo_res_get(struct ptlrpc_nrs_policy *policy,
133                             struct ptlrpc_nrs_request *nrq,
134                             const struct ptlrpc_nrs_resource *parent,
135                             struct ptlrpc_nrs_resource **resp, bool moving_req)
136 {
137         /**
138          * Just return the resource embedded inside nrs_fifo_head, and end this
139          * resource hierarchy reference request.
140          */
141         *resp = &((struct nrs_fifo_head *)policy->pol_private)->fh_res;
142         return 1;
143 }
144
145 /**
146  * Called when getting a request from the FIFO policy for handling, or just
147  * peeking; removes the request from the policy when it is to be handled.
148  *
149  * \param[in] policy The policy
150  * \param[in] peek   When set, signifies that we just want to examine the
151  *                   request, and not handle it, so the request is not removed
152  *                   from the policy.
153  * \param[in] force  Force the policy to return a request; unused in this
154  *                   policy
155  *
156  * \retval The request to be handled; this is the next request in the FIFO
157  *         queue
158  *
159  * \see ptlrpc_nrs_req_get_nolock()
160  * \see nrs_request_get()
161  */
162 static
163 struct ptlrpc_nrs_request * nrs_fifo_req_get(struct ptlrpc_nrs_policy *policy,
164                                              bool peek, bool force)
165 {
166         struct nrs_fifo_head      *head = policy->pol_private;
167         struct ptlrpc_nrs_request *nrq;
168
169         nrq = unlikely(cfs_list_empty(&head->fh_list)) ? NULL :
170               cfs_list_entry(head->fh_list.next, struct ptlrpc_nrs_request,
171                              nr_u.fifo.fr_list);
172
173         if (likely(!peek && nrq != NULL)) {
174                 struct ptlrpc_request *req = container_of(nrq,
175                                                           struct ptlrpc_request,
176                                                           rq_nrq);
177
178                 cfs_list_del_init(&nrq->nr_u.fifo.fr_list);
179
180                 CDEBUG(D_RPCTRACE, "NRS start %s request from %s, seq: "LPU64
181                        "\n", policy->pol_desc->pd_name,
182                        libcfs_id2str(req->rq_peer), nrq->nr_u.fifo.fr_sequence);
183         }
184
185         return nrq;
186 }
187
188 /**
189  * Adds request \a nrq to \a policy's list of queued requests
190  *
191  * \param[in] policy The policy
192  * \param[in] nrq    The request to add
193  *
194  * \retval 0 success; nrs_request_enqueue() assumes this function will always
195  *                    succeed
196  */
197 static int nrs_fifo_req_add(struct ptlrpc_nrs_policy *policy,
198                             struct ptlrpc_nrs_request *nrq)
199 {
200         struct nrs_fifo_head *head;
201
202         head = container_of(nrs_request_resource(nrq), struct nrs_fifo_head,
203                             fh_res);
204         /**
205          * Only used for debugging
206          */
207         nrq->nr_u.fifo.fr_sequence = head->fh_sequence++;
208         cfs_list_add_tail(&nrq->nr_u.fifo.fr_list, &head->fh_list);
209
210         return 0;
211 }
212
213 /**
214  * Removes request \a nrq from \a policy's list of queued requests.
215  *
216  * \param[in] policy The policy
217  * \param[in] nrq    The request to remove
218  */
219 static void nrs_fifo_req_del(struct ptlrpc_nrs_policy *policy,
220                              struct ptlrpc_nrs_request *nrq)
221 {
222         LASSERT(!cfs_list_empty(&nrq->nr_u.fifo.fr_list));
223         cfs_list_del_init(&nrq->nr_u.fifo.fr_list);
224 }
225
226 /**
227  * Prints a debug statement right before the request \a nrq stops being
228  * handled.
229  *
230  * \param[in] policy The policy handling the request
231  * \param[in] nrq    The request being handled
232  *
233  * \see ptlrpc_server_finish_request()
234  * \see ptlrpc_nrs_req_stop_nolock()
235  */
236 static void nrs_fifo_req_stop(struct ptlrpc_nrs_policy *policy,
237                               struct ptlrpc_nrs_request *nrq)
238 {
239         struct ptlrpc_request *req = container_of(nrq, struct ptlrpc_request,
240                                                   rq_nrq);
241
242         CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: "LPU64"\n",
243                policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer),
244                nrq->nr_u.fifo.fr_sequence);
245 }
246
247 /**
248  * FIFO policy operations
249  */
250 static const struct ptlrpc_nrs_pol_ops nrs_fifo_ops = {
251         .op_policy_start        = nrs_fifo_start,
252         .op_policy_stop         = nrs_fifo_stop,
253         .op_res_get             = nrs_fifo_res_get,
254         .op_req_get             = nrs_fifo_req_get,
255         .op_req_enqueue         = nrs_fifo_req_add,
256         .op_req_dequeue         = nrs_fifo_req_del,
257         .op_req_stop            = nrs_fifo_req_stop,
258 };
259
260 /**
261  * FIFO policy configuration
262  */
263 struct ptlrpc_nrs_pol_conf nrs_conf_fifo = {
264         .nc_name                = NRS_POL_NAME_FIFO,
265         .nc_ops                 = &nrs_fifo_ops,
266         .nc_compat              = nrs_policy_compat_all,
267         .nc_flags               = PTLRPC_NRS_FL_FALLBACK |
268                                   PTLRPC_NRS_FL_REG_START
269 };
270
271 /** @} fifo */
272
273 /** @} nrs */
274