Whamcloud - gitweb
LU-10656 ldlm: fix export reference
[fs/lustre-release.git] / lustre / ptlrpc / nrs_tbf.c
index 95fa32b..ccab4c6 100644 (file)
@@ -300,6 +300,7 @@ nrs_tbf_rule_start(struct ptlrpc_nrs_policy *policy,
 
        memcpy(rule->tr_name, start->tc_name, strlen(start->tc_name));
        rule->tr_rpc_rate = start->u.tc_start.ts_rpc_rate;
+       rule->tr_flags = start->u.tc_start.ts_rule_flags;
        rule->tr_nsecs = NSEC_PER_SEC;
        do_div(rule->tr_nsecs, rule->tr_rpc_rate);
        rule->tr_depth = tbf_depth;
@@ -348,6 +349,9 @@ nrs_tbf_rule_start(struct ptlrpc_nrs_policy *policy,
                head->th_rule = rule;
        }
 
+       CDEBUG(D_RPCTRACE, "TBF starts rule@%p rate %llu gen %llu\n",
+              rule, rule->tr_rpc_rate, rule->tr_generation);
+
        return 0;
 }
 
@@ -518,11 +522,9 @@ tbf_cli_compare(struct cfs_binheap_node *e1, struct cfs_binheap_node *e2)
        cli1 = container_of(e1, struct nrs_tbf_client, tc_node);
        cli2 = container_of(e2, struct nrs_tbf_client, tc_node);
 
-       if (cli1->tc_check_time + cli1->tc_nsecs <
-           cli2->tc_check_time + cli2->tc_nsecs)
+       if (cli1->tc_deadline < cli2->tc_deadline)
                return 1;
-       else if (cli1->tc_check_time + cli1->tc_nsecs >
-                cli2->tc_check_time + cli2->tc_nsecs)
+       else if (cli1->tc_deadline > cli2->tc_deadline)
                return 0;
 
        if (cli1->tc_check_time < cli2->tc_check_time)
@@ -2366,6 +2368,13 @@ static int nrs_tbf_res_get(struct ptlrpc_nrs_policy *policy,
                    cli->tc_rule->tr_flags & NTRS_STOPPING) {
                        struct nrs_tbf_rule *rule;
 
+                       CDEBUG(D_RPCTRACE,
+                              "TBF class@%p rate %llu sequence %d, "
+                              "rule flags %d, head sequence %d\n",
+                              cli, cli->tc_rpc_rate,
+                              cli->tc_rule_sequence,
+                              cli->tc_rule->tr_flags,
+                              atomic_read(&head->th_rule_sequence));
                        rule = nrs_tbf_rule_match(head, cli);
                        if (rule != cli->tc_rule) {
                                nrs_tbf_cli_reset(head, rule, cli);
@@ -2467,10 +2476,12 @@ struct ptlrpc_nrs_request *nrs_tbf_req_get(struct ptlrpc_nrs_policy *policy,
                                     struct ptlrpc_nrs_request,
                                     nr_u.tbf.tr_list);
        } else {
+               struct nrs_tbf_rule *rule = cli->tc_rule;
                __u64 now = ktime_to_ns(ktime_get());
                __u64 passed;
                __u64 ntoken;
                __u64 deadline;
+               __u64 old_resid = 0;
 
                deadline = cli->tc_check_time +
                          cli->tc_nsecs;
@@ -2478,9 +2489,19 @@ struct ptlrpc_nrs_request *nrs_tbf_req_get(struct ptlrpc_nrs_policy *policy,
                passed = now - cli->tc_check_time;
                ntoken = passed * cli->tc_rpc_rate;
                do_div(ntoken, NSEC_PER_SEC);
+
                ntoken += cli->tc_ntoken;
-               if (ntoken > cli->tc_depth)
+               if (rule->tr_flags & NTRS_REALTIME) {
+                       LASSERT(cli->tc_nsecs_resid < cli->tc_nsecs);
+                       old_resid = cli->tc_nsecs_resid;
+                       cli->tc_nsecs_resid += passed % cli->tc_nsecs;
+                       if (cli->tc_nsecs_resid > cli->tc_nsecs) {
+                               ntoken++;
+                               cli->tc_nsecs_resid -= cli->tc_nsecs;
+                       }
+               } else if (ntoken > cli->tc_depth)
                        ntoken = cli->tc_depth;
+
                if (ntoken > 0) {
                        struct ptlrpc_request *req;
                        nrq = list_entry(cli->tc_list.next,
@@ -2498,18 +2519,30 @@ struct ptlrpc_nrs_request *nrs_tbf_req_get(struct ptlrpc_nrs_policy *policy,
                                                   &cli->tc_node);
                                cli->tc_in_heap = false;
                        } else {
+                               if (!(rule->tr_flags & NTRS_REALTIME))
+                                       cli->tc_deadline = now + cli->tc_nsecs;
                                cfs_binheap_relocate(head->th_binheap,
                                                     &cli->tc_node);
                        }
                        CDEBUG(D_RPCTRACE,
-                              "NRS start %s request from %s, "
-                              "seq: %llu\n",
-                              policy->pol_desc->pd_name,
-                              libcfs_id2str(req->rq_peer),
-                              nrq->nr_u.tbf.tr_sequence);
+                              "TBF dequeues: class@%p rate %llu gen %llu "
+                              "token %llu, rule@%p rate %llu gen %llu\n",
+                              cli, cli->tc_rpc_rate,
+                              cli->tc_rule_generation, cli->tc_ntoken,
+                              cli->tc_rule, cli->tc_rule->tr_rpc_rate,
+                              cli->tc_rule->tr_generation);
                } else {
                        ktime_t time;
 
+                       if (rule->tr_flags & NTRS_REALTIME) {
+                               cli->tc_deadline = deadline;
+                               cli->tc_nsecs_resid = old_resid;
+                               cfs_binheap_relocate(head->th_binheap,
+                                                    &cli->tc_node);
+                               if (node != cfs_binheap_root(head->th_binheap))
+                                       return nrs_tbf_req_get(policy,
+                                                              peek, force);
+                       }
                        policy->pol_nrs->nrs_throttling = 1;
                        head->th_deadline = deadline;
                        time = ktime_set(0, 0);
@@ -2545,6 +2578,7 @@ static int nrs_tbf_req_add(struct ptlrpc_nrs_policy *policy,
                            struct nrs_tbf_head, th_res);
        if (list_empty(&cli->tc_list)) {
                LASSERT(!cli->tc_in_heap);
+               cli->tc_deadline = cli->tc_check_time + cli->tc_nsecs;
                rc = cfs_binheap_insert(head->th_binheap, &cli->tc_node);
                if (rc == 0) {
                        cli->tc_in_heap = true;
@@ -2552,8 +2586,7 @@ static int nrs_tbf_req_add(struct ptlrpc_nrs_policy *policy,
                        list_add_tail(&nrq->nr_u.tbf.tr_list,
                                          &cli->tc_list);
                        if (policy->pol_nrs->nrs_throttling) {
-                               __u64 deadline = cli->tc_check_time +
-                                                cli->tc_nsecs;
+                               __u64 deadline = cli->tc_deadline;
                                if ((head->th_deadline > deadline) &&
                                    (hrtimer_try_to_cancel(&head->th_timer)
                                     >= 0)) {
@@ -2572,6 +2605,16 @@ static int nrs_tbf_req_add(struct ptlrpc_nrs_policy *policy,
                list_add_tail(&nrq->nr_u.tbf.tr_list,
                                  &cli->tc_list);
        }
+
+       if (rc == 0)
+               CDEBUG(D_RPCTRACE,
+                      "TBF enqueues: class@%p rate %llu gen %llu "
+                      "token %llu, rule@%p rate %llu gen %llu\n",
+                      cli, cli->tc_rpc_rate,
+                      cli->tc_rule_generation, cli->tc_ntoken,
+                      cli->tc_rule, cli->tc_rule->tr_rpc_rate,
+                      cli->tc_rule->tr_generation);
+
        return rc;
 }
 
@@ -2784,6 +2827,15 @@ nrs_tbf_parse_value_pair(struct nrs_tbf_cmd *cmd, char *buffer)
                        cmd->u.tc_change.tc_next_name = val;
                else
                        return -EINVAL;
+       } else if (strcmp(key, "realtime") == 0) {
+               unsigned long realtime;
+
+               rc = kstrtoul(val, 10, &realtime);
+               if (rc)
+                       return rc;
+
+               if (realtime > 0)
+                       cmd->u.tc_start.ts_rule_flags |= NTRS_REALTIME;
        } else {
                return -EINVAL;
        }