4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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.
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
23 * Copyright (c) 2011 Intel Corporation
25 * Copyright 2012 Xyratex Technology Limited
28 * lustre/ptlrpc/nrs_crr.c
30 * Network Request Scheduler (NRS) CRR-N policy
32 * Request ordering in a batched Round-Robin manner over client NIDs
34 * Author: Liang Zhen <liang@whamcloud.com>
35 * Author: Nikitas Angelinas <nikitas_angelinas@xyratex.com>
41 #ifdef HAVE_SERVER_SUPPORT
43 #define DEBUG_SUBSYSTEM S_RPC
45 #include <liblustre.h>
47 #include <obd_support.h>
48 #include <obd_class.h>
49 #include <lustre_net.h>
50 #include <lprocfs_status.h>
51 #include "ptlrpc_internal.h"
56 * Client Round-Robin scheduling over client NIDs
62 #define NRS_POL_NAME_CRRN "crrn"
65 * Binary heap predicate.
67 * Uses ptlrpc_nrs_request::nr_u::crr::cr_round and
68 * ptlrpc_nrs_request::nr_u::crr::cr_sequence to compare two binheap nodes and
69 * produce a binary predicate that shows their relative priority, so that the
70 * binary heap can perform the necessary sorting operations.
72 * \param[in] e1 the first binheap node to compare
73 * \param[in] e2 the second binheap node to compare
78 static int crrn_req_compare(cfs_binheap_node_t *e1, cfs_binheap_node_t *e2)
80 struct ptlrpc_nrs_request *nrq1;
81 struct ptlrpc_nrs_request *nrq2;
83 nrq1 = container_of(e1, struct ptlrpc_nrs_request, nr_node);
84 nrq2 = container_of(e2, struct ptlrpc_nrs_request, nr_node);
86 if (nrq1->nr_u.crr.cr_round < nrq2->nr_u.crr.cr_round)
88 else if (nrq1->nr_u.crr.cr_round > nrq2->nr_u.crr.cr_round)
91 return nrq1->nr_u.crr.cr_sequence < nrq2->nr_u.crr.cr_sequence;
94 static cfs_binheap_ops_t nrs_crrn_heap_ops = {
97 .hop_compare = crrn_req_compare,
101 * libcfs_hash operations for nrs_crrn_net::cn_cli_hash
103 * This uses ptlrpc_request::rq_peer.nid as its key, in order to hash
104 * nrs_crrn_client objects.
106 #define NRS_NID_BKT_BITS 8
107 #define NRS_NID_BITS 16
109 static unsigned nrs_crrn_hop_hash(cfs_hash_t *hs, const void *key,
112 return cfs_hash_djb2_hash(key, sizeof(lnet_nid_t), mask);
115 static int nrs_crrn_hop_keycmp(const void *key, cfs_hlist_node_t *hnode)
117 lnet_nid_t *nid = (lnet_nid_t *)key;
118 struct nrs_crrn_client *cli = cfs_hlist_entry(hnode,
119 struct nrs_crrn_client,
121 return *nid == cli->cc_nid;
124 static void *nrs_crrn_hop_key(cfs_hlist_node_t *hnode)
126 struct nrs_crrn_client *cli = cfs_hlist_entry(hnode,
127 struct nrs_crrn_client,
132 static void *nrs_crrn_hop_object(cfs_hlist_node_t *hnode)
134 return cfs_hlist_entry(hnode, struct nrs_crrn_client, cc_hnode);
137 static void nrs_crrn_hop_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
139 struct nrs_crrn_client *cli = cfs_hlist_entry(hnode,
140 struct nrs_crrn_client,
142 atomic_inc(&cli->cc_ref);
145 static void nrs_crrn_hop_put(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
147 struct nrs_crrn_client *cli = cfs_hlist_entry(hnode,
148 struct nrs_crrn_client,
150 atomic_dec(&cli->cc_ref);
153 static void nrs_crrn_hop_exit(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
155 struct nrs_crrn_client *cli = cfs_hlist_entry(hnode,
156 struct nrs_crrn_client,
158 LASSERTF(atomic_read(&cli->cc_ref) == 0,
159 "Busy CRR-N object from client with NID %s, with %d refs\n",
160 libcfs_nid2str(cli->cc_nid), atomic_read(&cli->cc_ref));
165 static cfs_hash_ops_t nrs_crrn_hash_ops = {
166 .hs_hash = nrs_crrn_hop_hash,
167 .hs_keycmp = nrs_crrn_hop_keycmp,
168 .hs_key = nrs_crrn_hop_key,
169 .hs_object = nrs_crrn_hop_object,
170 .hs_get = nrs_crrn_hop_get,
171 .hs_put = nrs_crrn_hop_put,
172 .hs_put_locked = nrs_crrn_hop_put,
173 .hs_exit = nrs_crrn_hop_exit,
177 * Called when a CRR-N policy instance is started.
179 * \param[in] policy the policy
181 * \retval -ENOMEM OOM error
184 static int nrs_crrn_start(struct ptlrpc_nrs_policy *policy, char *arg)
186 struct nrs_crrn_net *net;
190 OBD_CPT_ALLOC_PTR(net, nrs_pol2cptab(policy), nrs_pol2cptid(policy));
194 net->cn_binheap = cfs_binheap_create(&nrs_crrn_heap_ops,
195 CBH_FLAG_ATOMIC_GROW, 4096, NULL,
196 nrs_pol2cptab(policy),
197 nrs_pol2cptid(policy));
198 if (net->cn_binheap == NULL)
199 GOTO(failed, rc = -ENOMEM);
201 net->cn_cli_hash = cfs_hash_create("nrs_crrn_nid_hash",
202 NRS_NID_BITS, NRS_NID_BITS,
207 CFS_HASH_RW_BKTLOCK);
208 if (net->cn_cli_hash == NULL)
209 GOTO(failed, rc = -ENOMEM);
212 * Set default quantum value to max_rpcs_in_flight for non-MDS OSCs;
213 * there may be more RPCs pending from each struct nrs_crrn_client even
214 * with the default max_rpcs_in_flight value, as we are scheduling over
215 * NIDs, and there may be more than one mount point per client.
217 net->cn_quantum = OBD_MAX_RIF_DEFAULT;
219 * Set to 1 so that the test inside nrs_crrn_req_add() can evaluate to
222 net->cn_sequence = 1;
224 policy->pol_private = net;
229 if (net->cn_binheap != NULL)
230 cfs_binheap_destroy(net->cn_binheap);
238 * Called when a CRR-N policy instance is stopped.
240 * Called when the policy has been instructed to transition to the
241 * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED state and has no more pending
244 * \param[in] policy the policy
246 static void nrs_crrn_stop(struct ptlrpc_nrs_policy *policy)
248 struct nrs_crrn_net *net = policy->pol_private;
251 LASSERT(net != NULL);
252 LASSERT(net->cn_binheap != NULL);
253 LASSERT(net->cn_cli_hash != NULL);
254 LASSERT(cfs_binheap_is_empty(net->cn_binheap));
256 cfs_binheap_destroy(net->cn_binheap);
257 cfs_hash_putref(net->cn_cli_hash);
263 * Performs a policy-specific ctl function on CRR-N policy instances; similar
266 * \param[in] policy the policy instance
267 * \param[in] opc the opcode
268 * \param[in,out] arg used for passing parameters and information
270 * \pre assert_spin_locked(&policy->pol_nrs->->nrs_lock)
271 * \post assert_spin_locked(&policy->pol_nrs->->nrs_lock)
273 * \retval 0 operation carried out successfully
276 int nrs_crrn_ctl(struct ptlrpc_nrs_policy *policy, enum ptlrpc_nrs_ctl opc,
279 assert_spin_locked(&policy->pol_nrs->nrs_lock);
281 switch((enum nrs_ctl_crr)opc) {
286 * Read Round Robin quantum size of a policy instance.
288 case NRS_CTL_CRRN_RD_QUANTUM: {
289 struct nrs_crrn_net *net = policy->pol_private;
291 *(__u16 *)arg = net->cn_quantum;
296 * Write Round Robin quantum size of a policy instance.
298 case NRS_CTL_CRRN_WR_QUANTUM: {
299 struct nrs_crrn_net *net = policy->pol_private;
301 net->cn_quantum = *(__u16 *)arg;
302 LASSERT(net->cn_quantum != 0);
311 * Obtains resources from CRR-N policy instances. The top-level resource lives
312 * inside \e nrs_crrn_net and the second-level resource inside
313 * \e nrs_crrn_client object instances.
315 * \param[in] policy the policy for which resources are being taken for
317 * \param[in] nrq the request for which resources are being taken
318 * \param[in] parent parent resource, embedded in nrs_crrn_net for the
320 * \param[out] resp resources references are placed in this array
321 * \param[in] moving_req signifies limited caller context; used to perform
322 * memory allocations in an atomic context in this
325 * \retval 0 we are returning a top-level, parent resource, one that is
326 * embedded in an nrs_crrn_net object
327 * \retval 1 we are returning a bottom-level resource, one that is embedded
328 * in an nrs_crrn_client object
330 * \see nrs_resource_get_safe()
332 int nrs_crrn_res_get(struct ptlrpc_nrs_policy *policy,
333 struct ptlrpc_nrs_request *nrq,
334 const struct ptlrpc_nrs_resource *parent,
335 struct ptlrpc_nrs_resource **resp, bool moving_req)
337 struct nrs_crrn_net *net;
338 struct nrs_crrn_client *cli;
339 struct nrs_crrn_client *tmp;
340 struct ptlrpc_request *req;
342 if (parent == NULL) {
343 *resp = &((struct nrs_crrn_net *)policy->pol_private)->cn_res;
347 net = container_of(parent, struct nrs_crrn_net, cn_res);
348 req = container_of(nrq, struct ptlrpc_request, rq_nrq);
350 cli = cfs_hash_lookup(net->cn_cli_hash, &req->rq_peer.nid);
354 OBD_CPT_ALLOC_GFP(cli, nrs_pol2cptab(policy), nrs_pol2cptid(policy),
355 sizeof(*cli), moving_req ? GFP_ATOMIC : GFP_NOFS);
359 cli->cc_nid = req->rq_peer.nid;
361 atomic_set(&cli->cc_ref, 1);
362 tmp = cfs_hash_findadd_unique(net->cn_cli_hash, &cli->cc_nid,
369 *resp = &cli->cc_res;
375 * Called when releasing references to the resource hierachy obtained for a
376 * request for scheduling using the CRR-N policy.
378 * \param[in] policy the policy the resource belongs to
379 * \param[in] res the resource to be released
381 static void nrs_crrn_res_put(struct ptlrpc_nrs_policy *policy,
382 const struct ptlrpc_nrs_resource *res)
384 struct nrs_crrn_net *net;
385 struct nrs_crrn_client *cli;
388 * Do nothing for freeing parent, nrs_crrn_net resources
390 if (res->res_parent == NULL)
393 cli = container_of(res, struct nrs_crrn_client, cc_res);
394 net = container_of(res->res_parent, struct nrs_crrn_net, cn_res);
396 cfs_hash_put(net->cn_cli_hash, &cli->cc_hnode);
400 * Called when getting a request from the CRR-N policy for handlingso that it can be served
402 * \param[in] policy the policy being polled
403 * \param[in] peek when set, signifies that we just want to examine the
404 * request, and not handle it, so the request is not removed
406 * \param[in] force force the policy to return a request; unused in this policy
408 * \retval the request to be handled
409 * \retval NULL no request available
411 * \see ptlrpc_nrs_req_get_nolock()
412 * \see nrs_request_get()
415 struct ptlrpc_nrs_request *nrs_crrn_req_get(struct ptlrpc_nrs_policy *policy,
416 bool peek, bool force)
418 struct nrs_crrn_net *net = policy->pol_private;
419 cfs_binheap_node_t *node = cfs_binheap_root(net->cn_binheap);
420 struct ptlrpc_nrs_request *nrq;
422 nrq = unlikely(node == NULL) ? NULL :
423 container_of(node, struct ptlrpc_nrs_request, nr_node);
425 if (likely(!peek && nrq != NULL)) {
426 struct nrs_crrn_client *cli;
427 struct ptlrpc_request *req = container_of(nrq,
428 struct ptlrpc_request,
431 cli = container_of(nrs_request_resource(nrq),
432 struct nrs_crrn_client, cc_res);
434 LASSERT(nrq->nr_u.crr.cr_round <= cli->cc_round);
436 cfs_binheap_remove(net->cn_binheap, &nrq->nr_node);
440 "NRS: starting to handle %s request from %s, with round "
441 LPU64"\n", NRS_POL_NAME_CRRN,
442 libcfs_id2str(req->rq_peer), nrq->nr_u.crr.cr_round);
444 /** Peek at the next request to be served */
445 node = cfs_binheap_root(net->cn_binheap);
447 /** No more requests */
448 if (unlikely(node == NULL)) {
451 struct ptlrpc_nrs_request *next;
453 next = container_of(node, struct ptlrpc_nrs_request,
456 if (net->cn_round < next->nr_u.crr.cr_round)
457 net->cn_round = next->nr_u.crr.cr_round;
465 * Adds request \a nrq to a CRR-N \a policy instance's set of queued requests
467 * A scheduling round is a stream of requests that have been sorted in batches
468 * according to the client that they originate from (as identified by its NID);
469 * there can be only one batch for each client in each round. The batches are of
470 * maximum size nrs_crrn_net:cn_quantum. When a new request arrives for
471 * scheduling from a client that has exhausted its quantum in its current round,
472 * it will start scheduling requests on the next scheduling round. Clients are
473 * allowed to schedule requests against a round until all requests for the round
474 * are serviced, so a client might miss a round if it is not generating requests
475 * for a long enough period of time. Clients that miss a round will continue
476 * with scheduling the next request that they generate, starting at the round
477 * that requests are being dispatched for, at the time of arrival of this new
480 * Requests are tagged with the round number and a sequence number; the sequence
481 * number indicates the relative ordering amongst the batches of requests in a
482 * round, and is identical for all requests in a batch, as is the round number.
483 * The round and sequence numbers are used by crrn_req_compare() in order to
484 * maintain an ordered set of rounds, with each round consisting of an ordered
485 * set of batches of requests.
487 * \param[in] policy the policy
488 * \param[in] nrq the request to add
490 * \retval 0 request successfully added
493 static int nrs_crrn_req_add(struct ptlrpc_nrs_policy *policy,
494 struct ptlrpc_nrs_request *nrq)
496 struct nrs_crrn_net *net;
497 struct nrs_crrn_client *cli;
500 cli = container_of(nrs_request_resource(nrq),
501 struct nrs_crrn_client, cc_res);
502 net = container_of(nrs_request_resource(nrq)->res_parent,
503 struct nrs_crrn_net, cn_res);
505 if (cli->cc_quantum == 0 || cli->cc_round < net->cn_round ||
506 (cli->cc_active == 0 && cli->cc_quantum > 0)) {
509 * If the client has no pending requests, and still some of its
510 * quantum remaining unused, which implies it has not had a
511 * chance to schedule up to its maximum allowed batch size of
512 * requests in the previous round it participated, schedule this
513 * next request on a new round; this avoids fragmentation of
514 * request batches caused by client inactivity, at the expense
515 * of potentially slightly increased service time for the
516 * request batch this request will be a part of.
518 if (cli->cc_active == 0 && cli->cc_quantum > 0)
521 /** A new scheduling round has commenced */
522 if (cli->cc_round < net->cn_round)
523 cli->cc_round = net->cn_round;
525 /** I was not the last client through here */
526 if (cli->cc_sequence < net->cn_sequence)
527 cli->cc_sequence = ++net->cn_sequence;
529 * Reset the quantum if we have reached the maximum quantum
530 * size for this batch, or even if we have not managed to
531 * complete a batch size up to its maximum allowed size.
532 * XXX: Accessed unlocked
534 cli->cc_quantum = net->cn_quantum;
537 nrq->nr_u.crr.cr_round = cli->cc_round;
538 nrq->nr_u.crr.cr_sequence = cli->cc_sequence;
540 rc = cfs_binheap_insert(net->cn_binheap, &nrq->nr_node);
543 if (--cli->cc_quantum == 0)
550 * Removes request \a nrq from a CRR-N \a policy instance's set of queued
553 * \param[in] policy the policy
554 * \param[in] nrq the request to remove
556 static void nrs_crrn_req_del(struct ptlrpc_nrs_policy *policy,
557 struct ptlrpc_nrs_request *nrq)
559 struct nrs_crrn_net *net;
560 struct nrs_crrn_client *cli;
563 cli = container_of(nrs_request_resource(nrq),
564 struct nrs_crrn_client, cc_res);
565 net = container_of(nrs_request_resource(nrq)->res_parent,
566 struct nrs_crrn_net, cn_res);
568 LASSERT(nrq->nr_u.crr.cr_round <= cli->cc_round);
570 is_root = &nrq->nr_node == cfs_binheap_root(net->cn_binheap);
572 cfs_binheap_remove(net->cn_binheap, &nrq->nr_node);
576 * If we just deleted the node at the root of the binheap, we may have
577 * to adjust round numbers.
579 if (unlikely(is_root)) {
580 /** Peek at the next request to be served */
581 cfs_binheap_node_t *node = cfs_binheap_root(net->cn_binheap);
583 /** No more requests */
584 if (unlikely(node == NULL)) {
587 nrq = container_of(node, struct ptlrpc_nrs_request,
590 if (net->cn_round < nrq->nr_u.crr.cr_round)
591 net->cn_round = nrq->nr_u.crr.cr_round;
597 * Called right after the request \a nrq finishes being handled by CRR-N policy
598 * instance \a policy.
600 * \param[in] policy the policy that handled the request
601 * \param[in] nrq the request that was handled
603 static void nrs_crrn_req_stop(struct ptlrpc_nrs_policy *policy,
604 struct ptlrpc_nrs_request *nrq)
606 struct ptlrpc_request *req = container_of(nrq, struct ptlrpc_request,
610 "NRS: finished handling %s request from %s, with round "LPU64
611 "\n", NRS_POL_NAME_CRRN,
612 libcfs_id2str(req->rq_peer), nrq->nr_u.crr.cr_round);
622 * Retrieves the value of the Round Robin quantum (i.e. the maximum batch size)
623 * for CRR-N policy instances on both the regular and high-priority NRS head
624 * of a service, as long as a policy instance is not in the
625 * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED state; policy instances in this
626 * state are skipped later by nrs_crrn_ctl().
628 * Quantum values are in # of RPCs, and output is in YAML format.
636 ptlrpc_lprocfs_nrs_crrn_quantum_seq_show(struct seq_file *m, void *data)
638 struct ptlrpc_service *svc = m->private;
643 * Perform two separate calls to this as only one of the NRS heads'
644 * policies may be in the ptlrpc_nrs_pol_state::NRS_POL_STATE_STARTED or
645 * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPING state.
647 rc = ptlrpc_nrs_policy_control(svc, PTLRPC_NRS_QUEUE_REG,
649 NRS_CTL_CRRN_RD_QUANTUM,
652 seq_printf(m, NRS_LPROCFS_QUANTUM_NAME_REG
655 * Ignore -ENODEV as the regular NRS head's policy may be in the
656 * ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED state.
658 } else if (rc != -ENODEV) {
662 if (!nrs_svc_has_hp(svc))
665 rc = ptlrpc_nrs_policy_control(svc, PTLRPC_NRS_QUEUE_HP,
667 NRS_CTL_CRRN_RD_QUANTUM,
670 seq_printf(m, NRS_LPROCFS_QUANTUM_NAME_HP"%-5d\n", quantum);
672 * Ignore -ENODEV as the high priority NRS head's policy may be
673 * in the ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED state.
675 } else if (rc != -ENODEV) {
684 * Sets the value of the Round Robin quantum (i.e. the maximum batch size)
685 * for CRR-N policy instances of a service. The user can set the quantum size
686 * for the regular or high priority NRS head individually by specifying each
687 * value, or both together in a single invocation.
691 * lctl set_param *.*.*.nrs_crrn_quantum=reg_quantum:32, to set the regular
692 * request quantum size on all PTLRPC services to 32
694 * lctl set_param *.*.*.nrs_crrn_quantum=hp_quantum:16, to set the high
695 * priority request quantum size on all PTLRPC services to 16, and
697 * lctl set_param *.*.ost_io.nrs_crrn_quantum=16, to set both the regular and
698 * high priority request quantum sizes of the ost_io service to 16.
700 * policy instances in the ptlrpc_nrs_pol_state::NRS_POL_STATE_STOPPED state
701 * are skipped later by nrs_crrn_ctl().
704 ptlrpc_lprocfs_nrs_crrn_quantum_seq_write(struct file *file,
705 const char *buffer, size_t count,
708 struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
709 enum ptlrpc_nrs_queue_type queue = 0;
710 char kernbuf[LPROCFS_NRS_WR_QUANTUM_MAX_CMD];
714 /** lprocfs_find_named_value() modifies its argument, so keep a copy */
719 if (count > (sizeof(kernbuf) - 1))
722 if (copy_from_user(kernbuf, buffer, count))
725 kernbuf[count] = '\0';
730 * Check if the regular quantum value has been specified
732 val = lprocfs_find_named_value(kernbuf, NRS_LPROCFS_QUANTUM_NAME_REG,
734 if (val != kernbuf) {
735 quantum_reg = simple_strtol(val, NULL, 10);
737 queue |= PTLRPC_NRS_QUEUE_REG;
743 * Check if the high priority quantum value has been specified
745 val = lprocfs_find_named_value(kernbuf, NRS_LPROCFS_QUANTUM_NAME_HP,
747 if (val != kernbuf) {
748 if (!nrs_svc_has_hp(svc))
751 quantum_hp = simple_strtol(val, NULL, 10);
753 queue |= PTLRPC_NRS_QUEUE_HP;
757 * If none of the queues has been specified, look for a valid numerical
761 if (!isdigit(kernbuf[0]))
764 quantum_reg = simple_strtol(kernbuf, NULL, 10);
766 queue = PTLRPC_NRS_QUEUE_REG;
768 if (nrs_svc_has_hp(svc)) {
769 queue |= PTLRPC_NRS_QUEUE_HP;
770 quantum_hp = quantum_reg;
774 if ((((queue & PTLRPC_NRS_QUEUE_REG) != 0) &&
775 ((quantum_reg > LPROCFS_NRS_QUANTUM_MAX || quantum_reg <= 0))) ||
776 (((queue & PTLRPC_NRS_QUEUE_HP) != 0) &&
777 ((quantum_hp > LPROCFS_NRS_QUANTUM_MAX || quantum_hp <= 0))))
781 * We change the values on regular and HP NRS heads separately, so that
782 * we do not exit early from ptlrpc_nrs_policy_control() with an error
783 * returned by nrs_policy_ctl_locked(), in cases where the user has not
784 * started the policy on either the regular or HP NRS head; i.e. we are
785 * ignoring -ENODEV within nrs_policy_ctl_locked(). -ENODEV is returned
786 * only if the operation fails with -ENODEV on all heads that have been
787 * specified by the command; if at least one operation succeeds,
788 * success is returned.
790 if ((queue & PTLRPC_NRS_QUEUE_REG) != 0) {
791 rc = ptlrpc_nrs_policy_control(svc, PTLRPC_NRS_QUEUE_REG,
793 NRS_CTL_CRRN_WR_QUANTUM, false,
795 if ((rc < 0 && rc != -ENODEV) ||
796 (rc == -ENODEV && queue == PTLRPC_NRS_QUEUE_REG))
800 if ((queue & PTLRPC_NRS_QUEUE_HP) != 0) {
801 rc2 = ptlrpc_nrs_policy_control(svc, PTLRPC_NRS_QUEUE_HP,
803 NRS_CTL_CRRN_WR_QUANTUM, false,
805 if ((rc2 < 0 && rc2 != -ENODEV) ||
806 (rc2 == -ENODEV && queue == PTLRPC_NRS_QUEUE_HP))
810 return rc == -ENODEV && rc2 == -ENODEV ? -ENODEV : count;
812 LPROC_SEQ_FOPS(ptlrpc_lprocfs_nrs_crrn_quantum);
815 * Initializes a CRR-N policy's lprocfs interface for service \a svc
817 * \param[in] svc the service
822 int nrs_crrn_lprocfs_init(struct ptlrpc_service *svc)
824 struct lprocfs_seq_vars nrs_crrn_lprocfs_vars[] = {
825 { .name = "nrs_crrn_quantum",
826 .fops = &ptlrpc_lprocfs_nrs_crrn_quantum_fops,
831 if (svc->srv_procroot == NULL)
834 return lprocfs_seq_add_vars(svc->srv_procroot, nrs_crrn_lprocfs_vars,
839 * Cleans up a CRR-N policy's lprocfs interface for service \a svc
841 * \param[in] svc the service
843 void nrs_crrn_lprocfs_fini(struct ptlrpc_service *svc)
845 if (svc->srv_procroot == NULL)
848 lprocfs_remove_proc_entry("nrs_crrn_quantum", svc->srv_procroot);
854 * CRR-N policy operations
856 static const struct ptlrpc_nrs_pol_ops nrs_crrn_ops = {
857 .op_policy_start = nrs_crrn_start,
858 .op_policy_stop = nrs_crrn_stop,
859 .op_policy_ctl = nrs_crrn_ctl,
860 .op_res_get = nrs_crrn_res_get,
861 .op_res_put = nrs_crrn_res_put,
862 .op_req_get = nrs_crrn_req_get,
863 .op_req_enqueue = nrs_crrn_req_add,
864 .op_req_dequeue = nrs_crrn_req_del,
865 .op_req_stop = nrs_crrn_req_stop,
867 .op_lprocfs_init = nrs_crrn_lprocfs_init,
868 .op_lprocfs_fini = nrs_crrn_lprocfs_fini,
873 * CRR-N policy configuration
875 struct ptlrpc_nrs_pol_conf nrs_conf_crrn = {
876 .nc_name = NRS_POL_NAME_CRRN,
877 .nc_ops = &nrs_crrn_ops,
878 .nc_compat = nrs_policy_compat_all,
881 /** @} CRR-N policy */
885 #endif /* HAVE_SERVER_SUPPORT */