Whamcloud - gitweb
1f4de969d2aced842b47bc373b41abb9aeb35ca6
[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 /**
68  * Is called before the policy transitions into
69  * ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED; allocates and initializes a
70  * policy-specific private data structure.
71  *
72  * \param[in] policy The policy to start
73  *
74  * \retval -ENOMEM OOM error
75  * \retval  0      success
76  *
77  * \see nrs_policy_register()
78  * \see nrs_policy_ctl()
79  */
80 static int
81 nrs_fifo_start(struct ptlrpc_nrs_policy *policy)
82 {
83         struct nrs_fifo_head *head;
84
85         OBD_CPT_ALLOC_PTR(head, nrs_pol2cptab(policy), nrs_pol2cptid(policy));
86         if (head == NULL)
87                 return -ENOMEM;
88
89         CFS_INIT_LIST_HEAD(&head->fh_list);
90         policy->pol_private = head;
91         return 0;
92 }
93
94 /**
95  * Is called before the policy transitions into
96  * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED; deallocates the policy-specific
97  * private data structure.
98  *
99  * \param[in] policy The policy to stop
100  *
101  * \see nrs_policy_stop0()
102  */
103 static void
104 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
133 nrs_fifo_res_get(struct ptlrpc_nrs_policy *policy,
134                  struct ptlrpc_nrs_request *nrq,
135                  struct ptlrpc_nrs_resource *parent,
136                  struct ptlrpc_nrs_resource **resp, bool moving_req)
137 {
138         /**
139          * Just return the resource embedded inside nrs_fifo_head, and end this
140          * resource hierarchy reference request.
141          */
142         *resp = &((struct nrs_fifo_head *)policy->pol_private)->fh_res;
143         return 1;
144 }
145
146 /**
147  * Called when polling the fifo policy for a request.
148  *
149  * \param[in] policy The policy being polled
150  *
151  * \retval The request to be handled; this is the next request in the FIFO
152  *         queue
153  * \see ptlrpc_nrs_req_poll_nolock()
154  */
155 static struct ptlrpc_nrs_request *
156 nrs_fifo_req_poll(struct ptlrpc_nrs_policy *policy)
157 {
158         struct nrs_fifo_head *head = policy->pol_private;
159
160         LASSERT(head != NULL);
161
162         return cfs_list_empty(&head->fh_list) ? NULL :
163                cfs_list_entry(head->fh_list.next, struct ptlrpc_nrs_request,
164                               nr_u.fifo.fr_list);
165 }
166
167 /**
168  * Adds request \a nrq to \a policy's list of queued requests
169  *
170  * \param[in] policy The policy
171  * \param[in] nrq    The request to add
172  *
173  * \retval 0 success; nrs_request_enqueue() assumes this function will always
174  *                    succeed
175  */
176 static int
177 nrs_fifo_req_add(struct ptlrpc_nrs_policy *policy,
178                  struct ptlrpc_nrs_request *nrq)
179 {
180         struct nrs_fifo_head *head;
181
182         head = container_of(nrs_request_resource(nrq), struct nrs_fifo_head,
183                             fh_res);
184         /**
185          * Only used for debugging
186          */
187         nrq->nr_u.fifo.fr_sequence = head->fh_sequence++;
188         cfs_list_add_tail(&nrq->nr_u.fifo.fr_list, &head->fh_list);
189
190         return 0;
191 }
192
193 /**
194  * Removes request \a nrq from \a policy's list of queued requests.
195  *
196  * \param[in] policy The policy
197  * \param[in] nrq    The request to remove
198  */
199 static void
200 nrs_fifo_req_del(struct ptlrpc_nrs_policy *policy,
201                  struct ptlrpc_nrs_request *nrq)
202 {
203         LASSERT(!cfs_list_empty(&nrq->nr_u.fifo.fr_list));
204         cfs_list_del_init(&nrq->nr_u.fifo.fr_list);
205 }
206
207 /**
208  * Prints a debug statement right before the request \a nrq starts being
209  * handled.
210  *
211  * \param[in] policy The policy handling the request
212  * \param[in] nrq    The request being handled
213  */
214 static void
215 nrs_fifo_req_start(struct ptlrpc_nrs_policy *policy,
216                    struct ptlrpc_nrs_request *nrq)
217 {
218         struct ptlrpc_request *req = container_of(nrq, struct ptlrpc_request,
219                                                   rq_nrq);
220
221         CDEBUG(D_RPCTRACE, "NRS start %s request from %s, seq: "LPU64"\n",
222                nrs_request_policy(nrq)->pol_name, libcfs_id2str(req->rq_peer),
223                nrq->nr_u.fifo.fr_sequence);
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
237 nrs_fifo_req_stop(struct ptlrpc_nrs_policy *policy,
238                   struct ptlrpc_nrs_request *nrq)
239 {
240         struct ptlrpc_request *req = container_of(nrq, struct ptlrpc_request,
241                                                   rq_nrq);
242
243         CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: "LPU64"\n",
244                nrs_request_policy(nrq)->pol_name, libcfs_id2str(req->rq_peer),
245                nrq->nr_u.fifo.fr_sequence);
246 }
247
248 /**
249  * FIFO policy operations
250  */
251 static struct ptlrpc_nrs_pol_ops nrs_fifo_ops = {
252         .op_policy_start        = nrs_fifo_start,
253         .op_policy_stop         = nrs_fifo_stop,
254         .op_res_get             = nrs_fifo_res_get,
255         .op_req_poll            = nrs_fifo_req_poll,
256         .op_req_enqueue         = nrs_fifo_req_add,
257         .op_req_dequeue         = nrs_fifo_req_del,
258         .op_req_start           = nrs_fifo_req_start,
259         .op_req_stop            = nrs_fifo_req_stop,
260 };
261
262 /**
263  * FIFO policy descriptor
264  */
265 struct ptlrpc_nrs_pol_desc ptlrpc_nrs_fifo_desc = {
266         .pd_name                = "fifo",
267         .pd_ops                 = &nrs_fifo_ops,
268         .pd_compat              = nrs_policy_compat_all,
269         .pd_flags               = PTLRPC_NRS_FL_FALLBACK |
270                                   PTLRPC_NRS_FL_REG_START
271 };
272
273 /** @} fifo */
274
275 /** @} nrs */
276