* GPL HEADER END
*/
/*
- * Copyright (c) 2011 Intel Corporation
+ * Copyright (c) 2011, 2014, Intel Corporation.
*
* Copyright 2012 Xyratex Technology Limited
*/
*/
#define DEBUG_SUBSYSTEM S_RPC
-#ifndef __KERNEL__
-#include <liblustre.h>
-#endif
#include <obd_support.h>
#include <obd_class.h>
#include <lustre_net.h>
#include <libcfs/libcfs.h>
#include "ptlrpc_internal.h"
-/* XXX: This is just for liblustre. Remove the #if defined directive when the
- * "cfs_" prefix is dropped from cfs_list_head. */
-#if defined (__linux__) && defined(__KERNEL__)
-extern struct list_head ptlrpc_all_services;
-#else
-extern struct cfs_list_head ptlrpc_all_services;
-#endif
-
/**
* NRS core object.
*/
static void nrs_policy_stop0(struct ptlrpc_nrs_policy *policy)
{
- struct ptlrpc_nrs *nrs = policy->pol_nrs;
ENTRY;
- if (policy->pol_desc->pd_ops->op_policy_stop != NULL) {
- spin_unlock(&nrs->nrs_lock);
-
+ if (policy->pol_desc->pd_ops->op_policy_stop != NULL)
policy->pol_desc->pd_ops->op_policy_stop(policy);
- spin_lock(&nrs->nrs_lock);
- }
-
- LASSERT(cfs_list_empty(&policy->pol_list_queued));
+ LASSERT(list_empty(&policy->pol_list_queued));
LASSERT(policy->pol_req_queued == 0 &&
policy->pol_req_started == 0);
policy->pol_state = NRS_POL_STATE_STOPPED;
- if (cfs_atomic_dec_and_test(&policy->pol_desc->pd_refs))
- cfs_module_put(policy->pol_desc->pd_owner);
+ if (atomic_dec_and_test(&policy->pol_desc->pd_refs))
+ module_put(policy->pol_desc->pd_owner);
EXIT;
}
* references on the policy to ptlrpc_nrs_pol_stae::NRS_POL_STATE_STOPPED. In
* this case, the fallback policy is only left active in the NRS head.
*/
-static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy)
+static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy, char *arg)
{
struct ptlrpc_nrs *nrs = policy->pol_nrs;
int rc = 0;
if (nrs->nrs_policy_fallback == NULL)
RETURN(-EPERM);
- if (policy->pol_state == NRS_POL_STATE_STARTED)
- RETURN(0);
+ if (policy->pol_state == NRS_POL_STATE_STARTED) {
+ /**
+ * If the policy argument now is different from the last time,
+ * stop the policy first and start it again with the new
+ * argument.
+ */
+ if ((arg != NULL) && (strlen(arg) >= NRS_POL_ARG_MAX))
+ return -EINVAL;
+
+ if ((arg == NULL && strlen(policy->pol_arg) == 0) ||
+ (arg != NULL && strcmp(policy->pol_arg, arg) == 0))
+ RETURN(0);
+
+ rc = nrs_policy_stop_locked(policy);
+ if (rc)
+ RETURN(-EAGAIN);
+ }
}
/**
* Increase the module usage count for policies registering from other
* modules.
*/
- if (cfs_atomic_inc_return(&policy->pol_desc->pd_refs) == 1 &&
- !cfs_try_module_get(policy->pol_desc->pd_owner)) {
- cfs_atomic_dec(&policy->pol_desc->pd_refs);
+ if (atomic_inc_return(&policy->pol_desc->pd_refs) == 1 &&
+ !try_module_get(policy->pol_desc->pd_owner)) {
+ atomic_dec(&policy->pol_desc->pd_refs);
CERROR("NRS: cannot get module for policy %s; is it alive?\n",
policy->pol_desc->pd_name);
RETURN(-ENODEV);
if (policy->pol_desc->pd_ops->op_policy_start) {
spin_unlock(&nrs->nrs_lock);
- rc = policy->pol_desc->pd_ops->op_policy_start(policy);
+ rc = policy->pol_desc->pd_ops->op_policy_start(policy, arg);
spin_lock(&nrs->nrs_lock);
if (rc != 0) {
- if (cfs_atomic_dec_and_test(&policy->pol_desc->pd_refs))
- cfs_module_put(policy->pol_desc->pd_owner);
+ if (atomic_dec_and_test(&policy->pol_desc->pd_refs))
+ module_put(policy->pol_desc->pd_owner);
policy->pol_state = NRS_POL_STATE_STOPPED;
GOTO(out, rc);
}
}
+ if (arg != NULL) {
+ if (strlcpy(policy->pol_arg, arg, sizeof(policy->pol_arg)) >=
+ sizeof(policy->pol_arg)) {
+ CERROR("NRS: arg '%s' is too long\n", arg);
+ GOTO(out, rc = -E2BIG);
+ }
+ }
+
policy->pol_state = NRS_POL_STATE_STARTED;
if (policy->pol_flags & PTLRPC_NRS_FL_FALLBACK) {
{
struct ptlrpc_nrs_policy *tmp;
- cfs_list_for_each_entry(tmp, &nrs->nrs_policy_list, pol_list) {
+ list_for_each_entry(tmp, &nrs->nrs_policy_list, pol_list) {
if (strncmp(tmp->pol_desc->pd_name, name,
NRS_POL_NAME_MAX) == 0) {
nrs_policy_get_locked(tmp);
if (policy == NULL)
GOTO(out, rc = -ENOENT);
+ if (policy->pol_state != NRS_POL_STATE_STARTED &&
+ policy->pol_state != NRS_POL_STATE_STOPPED)
+ GOTO(out, rc = -EAGAIN);
+
switch (opc) {
/**
* Unknown opcode, pass it down to the policy-specific control
* Start \e policy
*/
case PTLRPC_NRS_CTL_START:
- rc = nrs_policy_start_locked(policy);
+ rc = nrs_policy_start_locked(policy, arg);
break;
}
out:
LASSERT(policy->pol_state == NRS_POL_STATE_STOPPED);
}
- cfs_list_del(&policy->pol_list);
+ list_del(&policy->pol_list);
nrs->nrs_num_pols--;
nrs_policy_put_locked(policy);
LASSERT(desc->pd_compat != NULL);
OBD_CPT_ALLOC_GFP(policy, svcpt->scp_service->srv_cptable,
- svcpt->scp_cpt, sizeof(*policy), CFS_ALLOC_IO);
+ svcpt->scp_cpt, sizeof(*policy), GFP_NOFS);
if (policy == NULL)
RETURN(-ENOMEM);
policy->pol_state = NRS_POL_STATE_STOPPED;
policy->pol_flags = desc->pd_flags;
- CFS_INIT_LIST_HEAD(&policy->pol_list);
- CFS_INIT_LIST_HEAD(&policy->pol_list_queued);
+ INIT_LIST_HEAD(&policy->pol_list);
+ INIT_LIST_HEAD(&policy->pol_list_queued);
rc = nrs_policy_init(policy);
if (rc != 0) {
RETURN(-EEXIST);
}
- cfs_list_add_tail(&policy->pol_list, &nrs->nrs_policy_list);
+ list_add_tail(&policy->pol_list, &nrs->nrs_policy_list);
nrs->nrs_num_pols++;
if (policy->pol_flags & PTLRPC_NRS_FL_REG_START)
- rc = nrs_policy_start_locked(policy);
+ rc = nrs_policy_start_locked(policy, NULL);
spin_unlock(&nrs->nrs_lock);
* Add the policy to the NRS head's list of policies with enqueued
* requests, if it has not been added there.
*/
- if (unlikely(cfs_list_empty(&policy->pol_list_queued)))
- cfs_list_add_tail(&policy->pol_list_queued,
+ if (unlikely(list_empty(&policy->pol_list_queued)))
+ list_add_tail(&policy->pol_list_queued,
&policy->pol_nrs->nrs_policy_queued);
}
LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
- cfs_list_for_each_entry(desc, &nrs_core.nrs_policies, pd_list) {
+ list_for_each_entry(desc, &nrs_core.nrs_policies, pd_list) {
if (nrs_policy_compatible(svc, desc)) {
rc = nrs_policy_register(nrs, desc);
if (rc != 0) {
nrs->nrs_svcpt = svcpt;
nrs->nrs_queue_type = queue;
spin_lock_init(&nrs->nrs_lock);
- CFS_INIT_LIST_HEAD(&nrs->nrs_policy_list);
- CFS_INIT_LIST_HEAD(&nrs->nrs_policy_queued);
+ INIT_LIST_HEAD(&nrs->nrs_policy_list);
+ INIT_LIST_HEAD(&nrs->nrs_policy_queued);
+ nrs->nrs_throttling = 0;
rc = nrs_register_policies_locked(nrs);
LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
again:
- nrs = nrs_svcpt2nrs(svcpt, hp);
+ /* scp_nrs_hp could be NULL due to short of memory. */
+ nrs = hp ? svcpt->scp_nrs_hp : &svcpt->scp_nrs_reg;
+ /* check the nrs_svcpt to see if nrs is initialized. */
+ if (!nrs || !nrs->nrs_svcpt) {
+ EXIT;
+ return;
+ }
nrs->nrs_stopping = 1;
- cfs_list_for_each_entry_safe(policy, tmp, &nrs->nrs_policy_list,
+ list_for_each_entry_safe(policy, tmp, &nrs->nrs_policy_list,
pol_list) {
rc = nrs_policy_unregister(nrs, policy->pol_desc->pd_name);
LASSERT(rc == 0);
struct ptlrpc_nrs_pol_desc *tmp;
ENTRY;
- cfs_list_for_each_entry(tmp, &nrs_core.nrs_policies, pd_list) {
+ list_for_each_entry(tmp, &nrs_core.nrs_policies, pd_list) {
if (strncmp(tmp->pd_name, name, NRS_POL_NAME_MAX) == 0)
RETURN(tmp);
}
LASSERT(mutex_is_locked(&nrs_core.nrs_mutex));
LASSERT(mutex_is_locked(&ptlrpc_all_services_mutex));
- cfs_list_for_each_entry(svc, &ptlrpc_all_services, srv_list) {
+ list_for_each_entry(svc, &ptlrpc_all_services, srv_list) {
if (!nrs_policy_compatible(svc, desc) ||
unlikely(svc->srv_is_stopping))
if (desc == NULL)
GOTO(fail, rc = -ENOMEM);
- strncpy(desc->pd_name, conf->nc_name, NRS_POL_NAME_MAX);
+ if (strlcpy(desc->pd_name, conf->nc_name, sizeof(desc->pd_name)) >=
+ sizeof(desc->pd_name)) {
+ OBD_FREE_PTR(desc);
+ GOTO(fail, rc = -E2BIG);
+ }
desc->pd_ops = conf->nc_ops;
desc->pd_compat = conf->nc_compat;
desc->pd_compat_svc_name = conf->nc_compat_svc_name;
if ((conf->nc_flags & PTLRPC_NRS_FL_REG_EXTERN) != 0)
desc->pd_owner = conf->nc_owner;
desc->pd_flags = conf->nc_flags;
- cfs_atomic_set(&desc->pd_refs, 0);
+ atomic_set(&desc->pd_refs, 0);
/**
* For policies that are held in the same module as NRS (currently
*/
mutex_lock(&ptlrpc_all_services_mutex);
- cfs_list_for_each_entry(svc, &ptlrpc_all_services, srv_list) {
+ list_for_each_entry(svc, &ptlrpc_all_services, srv_list) {
struct ptlrpc_service_part *svcpt;
int i;
int rc2;
mutex_unlock(&ptlrpc_all_services_mutex);
internal:
- cfs_list_add_tail(&desc->pd_list, &nrs_core.nrs_policies);
+ list_add_tail(&desc->pd_list, &nrs_core.nrs_policies);
fail:
mutex_unlock(&nrs_core.nrs_mutex);
CDEBUG(D_INFO, "Unregistering policy %s from NRS core.\n",
conf->nc_name);
- cfs_list_del(&desc->pd_list);
+ list_del(&desc->pd_list);
OBD_FREE_PTR(desc);
fail:
* Set up lprocfs interfaces for all supported policies for the
* service.
*/
- cfs_list_for_each_entry(desc, &nrs_core.nrs_policies, pd_list) {
+ list_for_each_entry(desc, &nrs_core.nrs_policies, pd_list) {
if (!nrs_policy_compatible(svc, desc))
continue;
* Clean up lprocfs interfaces for all supported policies for the
* service.
*/
- cfs_list_for_each_entry(desc, &nrs_core.nrs_policies, pd_list) {
+ list_for_each_entry(desc, &nrs_core.nrs_policies, pd_list) {
if (!nrs_policy_compatible(svc, desc))
continue;
* ptlrpc_nrs::nrs_policy_queued.
*/
if (unlikely(policy->pol_req_queued == 0)) {
- cfs_list_del_init(&policy->pol_list_queued);
+ list_del_init(&policy->pol_list_queued);
/**
* If there are other policies with queued requests, move the
LASSERT(policy->pol_req_queued <
policy->pol_nrs->nrs_req_queued);
- cfs_list_move_tail(&policy->pol_list_queued,
+ list_move_tail(&policy->pol_list_queued,
&policy->pol_nrs->nrs_policy_queued);
}
}
* Always try to drain requests from all NRS polices even if they are
* inactive, because the user can change policy status at runtime.
*/
- cfs_list_for_each_entry(policy, &nrs->nrs_policy_queued,
+ list_for_each_entry(policy, &nrs->nrs_policy_queued,
pol_list_queued) {
nrq = nrs_request_get(policy, peek, force);
if (nrq != NULL) {
};
/**
+ * Returns whether NRS policy is throttling reqeust
+ *
+ * \param[in] svcpt the service partition to enquire.
+ * \param[in] hp whether the regular or high-priority NRS head is to be
+ * enquired.
+ *
+ * \retval false the indicated NRS head has no enqueued requests.
+ * \retval true the indicated NRS head has some enqueued requests.
+ */
+bool ptlrpc_nrs_req_throttling_nolock(struct ptlrpc_service_part *svcpt,
+ bool hp)
+{
+ struct ptlrpc_nrs *nrs = nrs_svcpt2nrs(svcpt, hp);
+
+ return !!nrs->nrs_throttling;
+};
+
+/**
* Moves request \a req from the regular to the high-priority NRS head.
*
* \param[in] req the request to move
RETURN(rc);
}
-
-/* ptlrpc/nrs_fifo.c */
-extern struct ptlrpc_nrs_pol_conf nrs_conf_fifo;
-
/**
* Adds all policies that ship with the ptlrpc module, to NRS core's list of
* policies \e nrs_core.nrs_policies.
ENTRY;
mutex_init(&nrs_core.nrs_mutex);
- CFS_INIT_LIST_HEAD(&nrs_core.nrs_policies);
+ INIT_LIST_HEAD(&nrs_core.nrs_policies);
rc = ptlrpc_nrs_policy_register(&nrs_conf_fifo);
if (rc != 0)
GOTO(fail, rc);
+#ifdef HAVE_SERVER_SUPPORT
+ rc = ptlrpc_nrs_policy_register(&nrs_conf_crrn);
+ if (rc != 0)
+ GOTO(fail, rc);
+
+ rc = ptlrpc_nrs_policy_register(&nrs_conf_orr);
+ if (rc != 0)
+ GOTO(fail, rc);
+
+ rc = ptlrpc_nrs_policy_register(&nrs_conf_trr);
+ if (rc != 0)
+ GOTO(fail, rc);
+ rc = ptlrpc_nrs_policy_register(&nrs_conf_tbf);
+ if (rc != 0)
+ GOTO(fail, rc);
+#endif /* HAVE_SERVER_SUPPORT */
+
RETURN(rc);
fail:
/**
}
/**
- * Removes all policy desciptors from nrs_core::nrs_policies, and frees the
+ * Removes all policy descriptors from nrs_core::nrs_policies, and frees the
* policy descriptors.
*
* Since all PTLRPC services are stopped at this point, there are no more
struct ptlrpc_nrs_pol_desc *desc;
struct ptlrpc_nrs_pol_desc *tmp;
- cfs_list_for_each_entry_safe(desc, tmp, &nrs_core.nrs_policies,
+ list_for_each_entry_safe(desc, tmp, &nrs_core.nrs_policies,
pd_list) {
- cfs_list_del_init(&desc->pd_list);
+ list_del_init(&desc->pd_list);
OBD_FREE_PTR(desc);
}
}