struct nrs_tbf_head *head,
struct nrs_tbf_cmd *start)
{
- struct nrs_tbf_rule *rule, *tmp_rule;
- int rc;
+ struct nrs_tbf_rule *rule;
+ struct nrs_tbf_rule *tmp_rule;
+ struct nrs_tbf_rule *next_rule;
+ char *next_name = start->u.tc_start.ts_next_name;
+ int rc;
rule = nrs_tbf_rule_find(head, start->tc_name);
if (rule) {
nrs_tbf_rule_put(rule);
return -EEXIST;
}
- list_add(&rule->tr_linkage, &head->th_list);
+
+ if (next_name) {
+ next_rule = nrs_tbf_rule_find_nolock(head, next_name);
+ if (!next_rule) {
+ spin_unlock(&head->th_rule_lock);
+ nrs_tbf_rule_put(rule);
+ return -ENOENT;
+ }
+
+ list_add(&rule->tr_linkage, next_rule->tr_linkage.prev);
+ nrs_tbf_rule_put(next_rule);
+ } else {
+ /* Add on the top of the rule list */
+ list_add(&rule->tr_linkage, &head->th_list);
+ }
spin_unlock(&head->th_rule_lock);
atomic_inc(&head->th_rule_sequence);
if (start->u.tc_start.ts_rule_flags & NTRS_DEFAULT) {
return 0;
}
+/**
+ * Change the rank of a rule in the rule list
+ *
+ * The matched rule will be moved to the position right before another
+ * given rule.
+ *
+ * \param[in] policy the policy instance
+ * \param[in] head the TBF policy instance
+ * \param[in] name the rule name to be moved
+ * \param[in] next_name the rule name before which the matched rule will be
+ * moved
+ *
+ */
static int
-nrs_tbf_rule_change(struct ptlrpc_nrs_policy *policy,
- struct nrs_tbf_head *head,
- struct nrs_tbf_cmd *change)
+nrs_tbf_rule_change_rank(struct ptlrpc_nrs_policy *policy,
+ struct nrs_tbf_head *head,
+ char *name,
+ char *next_name)
+{
+ struct nrs_tbf_rule *rule = NULL;
+ struct nrs_tbf_rule *next_rule = NULL;
+ int rc = 0;
+
+ LASSERT(head != NULL);
+
+ spin_lock(&head->th_rule_lock);
+ rule = nrs_tbf_rule_find_nolock(head, name);
+ if (!rule)
+ GOTO(out, rc = -ENOENT);
+
+ if (strcmp(name, next_name) == 0)
+ GOTO(out_put, rc);
+
+ next_rule = nrs_tbf_rule_find_nolock(head, next_name);
+ if (!next_rule)
+ GOTO(out_put, rc = -ENOENT);
+
+ list_move(&rule->tr_linkage, next_rule->tr_linkage.prev);
+ nrs_tbf_rule_put(next_rule);
+out_put:
+ nrs_tbf_rule_put(rule);
+out:
+ spin_unlock(&head->th_rule_lock);
+ return rc;
+}
+
+static int
+nrs_tbf_rule_change_rate(struct ptlrpc_nrs_policy *policy,
+ struct nrs_tbf_head *head,
+ char *name,
+ __u64 rate)
{
struct nrs_tbf_rule *rule;
assert_spin_locked(&policy->pol_nrs->nrs_lock);
- rule = nrs_tbf_rule_find(head, change->tc_name);
+ rule = nrs_tbf_rule_find(head, name);
if (rule == NULL)
return -ENOENT;
- rule->tr_rpc_rate = change->u.tc_change.tc_rpc_rate;
+ rule->tr_rpc_rate = rate;
rule->tr_nsecs = NSEC_PER_SEC;
do_div(rule->tr_nsecs, rule->tr_rpc_rate);
rule->tr_generation++;
}
static int
+nrs_tbf_rule_change(struct ptlrpc_nrs_policy *policy,
+ struct nrs_tbf_head *head,
+ struct nrs_tbf_cmd *change)
+{
+ __u64 rate = change->u.tc_change.tc_rpc_rate;
+ char *next_name = change->u.tc_change.tc_next_name;
+ int rc;
+
+ if (rate != 0) {
+ rc = nrs_tbf_rule_change_rate(policy, head, change->tc_name,
+ rate);
+ if (rc)
+ return rc;
+ }
+
+ if (next_name) {
+ rc = nrs_tbf_rule_change_rank(policy, head, change->tc_name,
+ next_name);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
nrs_tbf_rule_stop(struct ptlrpc_nrs_policy *policy,
struct nrs_tbf_head *head,
struct nrs_tbf_cmd *stop)
}
CDEBUG(D_RPCTRACE,
"NRS start %s request from %s, "
- "seq: "LPU64"\n",
+ "seq: %llu\n",
policy->pol_desc->pd_name,
libcfs_id2str(req->rq_peer),
nrq->nr_u.tbf.tr_sequence);
assert_spin_locked(&policy->pol_nrs->nrs_svcpt->scp_req_lock);
- CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: "LPU64"\n",
+ CDEBUG(D_RPCTRACE, "NRS stop %s request from %s, seq: %llu\n",
policy->pol_desc->pd_name, libcfs_id2str(req->rq_peer),
nrq->nr_u.tbf.tr_sequence);
}
cmd->u.tc_change.tc_rpc_rate = rate;
else
return -EINVAL;
+ } else if (strcmp(key, "rank") == 0) {
+ if (!name_is_valid(val))
+ return -EINVAL;
+
+ if (cmd->tc_cmd == NRS_CTL_TBF_START_RULE)
+ cmd->u.tc_start.ts_next_name = val;
+ else if (cmd->tc_cmd == NRS_CTL_TBF_CHANGE_RULE)
+ cmd->u.tc_change.tc_next_name = val;
+ else
+ return -EINVAL;
} else {
return -EINVAL;
}
cmd->u.tc_start.ts_rpc_rate = tbf_rate;
break;
case NRS_CTL_TBF_CHANGE_RULE:
- if (cmd->u.tc_change.tc_rpc_rate == 0)
+ if (cmd->u.tc_change.tc_rpc_rate == 0 &&
+ cmd->u.tc_change.tc_next_name == NULL)
return -EINVAL;
break;
case NRS_CTL_TBF_STOP_RULE: