1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#define DEBUG_SUBSYSTEM S_CLASS
34
35#include <obd_support.h>
36#include <obd.h>
37#include <lprocfs_status.h>
38#include <uapi/linux/lustre/lustre_idl.h>
39#include <lustre_net.h>
40#include <obd_class.h>
41#include "ptlrpc_internal.h"
42
43static struct ll_rpc_opcode {
44 __u32 opcode;
45 const char *opname;
46} ll_rpc_opcode_table[LUSTRE_MAX_OPCODES] = {
47 { OST_REPLY, "ost_reply" },
48 { OST_GETATTR, "ost_getattr" },
49 { OST_SETATTR, "ost_setattr" },
50 { OST_READ, "ost_read" },
51 { OST_WRITE, "ost_write" },
52 { OST_CREATE, "ost_create" },
53 { OST_DESTROY, "ost_destroy" },
54 { OST_GET_INFO, "ost_get_info" },
55 { OST_CONNECT, "ost_connect" },
56 { OST_DISCONNECT, "ost_disconnect" },
57 { OST_PUNCH, "ost_punch" },
58 { OST_OPEN, "ost_open" },
59 { OST_CLOSE, "ost_close" },
60 { OST_STATFS, "ost_statfs" },
61 { 14, NULL },
62 { 15, NULL },
63 { OST_SYNC, "ost_sync" },
64 { OST_SET_INFO, "ost_set_info" },
65 { OST_QUOTACHECK, "ost_quotacheck" },
66 { OST_QUOTACTL, "ost_quotactl" },
67 { OST_QUOTA_ADJUST_QUNIT, "ost_quota_adjust_qunit" },
68 { MDS_GETATTR, "mds_getattr" },
69 { MDS_GETATTR_NAME, "mds_getattr_lock" },
70 { MDS_CLOSE, "mds_close" },
71 { MDS_REINT, "mds_reint" },
72 { MDS_READPAGE, "mds_readpage" },
73 { MDS_CONNECT, "mds_connect" },
74 { MDS_DISCONNECT, "mds_disconnect" },
75 { MDS_GETSTATUS, "mds_getstatus" },
76 { MDS_STATFS, "mds_statfs" },
77 { MDS_PIN, "mds_pin" },
78 { MDS_UNPIN, "mds_unpin" },
79 { MDS_SYNC, "mds_sync" },
80 { MDS_DONE_WRITING, "mds_done_writing" },
81 { MDS_SET_INFO, "mds_set_info" },
82 { MDS_QUOTACHECK, "mds_quotacheck" },
83 { MDS_QUOTACTL, "mds_quotactl" },
84 { MDS_GETXATTR, "mds_getxattr" },
85 { MDS_SETXATTR, "mds_setxattr" },
86 { MDS_WRITEPAGE, "mds_writepage" },
87 { MDS_IS_SUBDIR, "mds_is_subdir" },
88 { MDS_GET_INFO, "mds_get_info" },
89 { MDS_HSM_STATE_GET, "mds_hsm_state_get" },
90 { MDS_HSM_STATE_SET, "mds_hsm_state_set" },
91 { MDS_HSM_ACTION, "mds_hsm_action" },
92 { MDS_HSM_PROGRESS, "mds_hsm_progress" },
93 { MDS_HSM_REQUEST, "mds_hsm_request" },
94 { MDS_HSM_CT_REGISTER, "mds_hsm_ct_register" },
95 { MDS_HSM_CT_UNREGISTER, "mds_hsm_ct_unregister" },
96 { MDS_SWAP_LAYOUTS, "mds_swap_layouts" },
97 { LDLM_ENQUEUE, "ldlm_enqueue" },
98 { LDLM_CONVERT, "ldlm_convert" },
99 { LDLM_CANCEL, "ldlm_cancel" },
100 { LDLM_BL_CALLBACK, "ldlm_bl_callback" },
101 { LDLM_CP_CALLBACK, "ldlm_cp_callback" },
102 { LDLM_GL_CALLBACK, "ldlm_gl_callback" },
103 { LDLM_SET_INFO, "ldlm_set_info" },
104 { MGS_CONNECT, "mgs_connect" },
105 { MGS_DISCONNECT, "mgs_disconnect" },
106 { MGS_EXCEPTION, "mgs_exception" },
107 { MGS_TARGET_REG, "mgs_target_reg" },
108 { MGS_TARGET_DEL, "mgs_target_del" },
109 { MGS_SET_INFO, "mgs_set_info" },
110 { MGS_CONFIG_READ, "mgs_config_read" },
111 { OBD_PING, "obd_ping" },
112 { OBD_LOG_CANCEL, "llog_cancel" },
113 { OBD_QC_CALLBACK, "obd_quota_callback" },
114 { OBD_IDX_READ, "dt_index_read" },
115 { LLOG_ORIGIN_HANDLE_CREATE, "llog_origin_handle_open" },
116 { LLOG_ORIGIN_HANDLE_NEXT_BLOCK, "llog_origin_handle_next_block" },
117 { LLOG_ORIGIN_HANDLE_READ_HEADER, "llog_origin_handle_read_header" },
118 { LLOG_ORIGIN_HANDLE_WRITE_REC, "llog_origin_handle_write_rec" },
119 { LLOG_ORIGIN_HANDLE_CLOSE, "llog_origin_handle_close" },
120 { LLOG_ORIGIN_CONNECT, "llog_origin_connect" },
121 { LLOG_CATINFO, "llog_catinfo" },
122 { LLOG_ORIGIN_HANDLE_PREV_BLOCK, "llog_origin_handle_prev_block" },
123 { LLOG_ORIGIN_HANDLE_DESTROY, "llog_origin_handle_destroy" },
124 { QUOTA_DQACQ, "quota_acquire" },
125 { QUOTA_DQREL, "quota_release" },
126 { SEQ_QUERY, "seq_query" },
127 { SEC_CTX_INIT, "sec_ctx_init" },
128 { SEC_CTX_INIT_CONT, "sec_ctx_init_cont" },
129 { SEC_CTX_FINI, "sec_ctx_fini" },
130 { FLD_QUERY, "fld_query" },
131 { FLD_READ, "fld_read" },
132};
133
134static struct ll_eopcode {
135 __u32 opcode;
136 const char *opname;
137} ll_eopcode_table[EXTRA_LAST_OPC] = {
138 { LDLM_GLIMPSE_ENQUEUE, "ldlm_glimpse_enqueue" },
139 { LDLM_PLAIN_ENQUEUE, "ldlm_plain_enqueue" },
140 { LDLM_EXTENT_ENQUEUE, "ldlm_extent_enqueue" },
141 { LDLM_FLOCK_ENQUEUE, "ldlm_flock_enqueue" },
142 { LDLM_IBITS_ENQUEUE, "ldlm_ibits_enqueue" },
143 { MDS_REINT_SETATTR, "mds_reint_setattr" },
144 { MDS_REINT_CREATE, "mds_reint_create" },
145 { MDS_REINT_LINK, "mds_reint_link" },
146 { MDS_REINT_UNLINK, "mds_reint_unlink" },
147 { MDS_REINT_RENAME, "mds_reint_rename" },
148 { MDS_REINT_OPEN, "mds_reint_open" },
149 { MDS_REINT_SETXATTR, "mds_reint_setxattr" },
150 { BRW_READ_BYTES, "read_bytes" },
151 { BRW_WRITE_BYTES, "write_bytes" },
152};
153
154const char *ll_opcode2str(__u32 opcode)
155{
156
157
158
159
160
161
162
163 __u32 offset = opcode_offset(opcode);
164
165 LASSERTF(offset < LUSTRE_MAX_OPCODES,
166 "offset %u >= LUSTRE_MAX_OPCODES %u\n",
167 offset, LUSTRE_MAX_OPCODES);
168 LASSERTF(ll_rpc_opcode_table[offset].opcode == opcode,
169 "ll_rpc_opcode_table[%u].opcode %u != opcode %u\n",
170 offset, ll_rpc_opcode_table[offset].opcode, opcode);
171 return ll_rpc_opcode_table[offset].opname;
172}
173
174static const char *ll_eopcode2str(__u32 opcode)
175{
176 LASSERT(ll_eopcode_table[opcode].opcode == opcode);
177 return ll_eopcode_table[opcode].opname;
178}
179
180static void
181ptlrpc_ldebugfs_register(struct dentry *root, char *dir,
182 char *name,
183 struct dentry **debugfs_root_ret,
184 struct lprocfs_stats **stats_ret)
185{
186 struct dentry *svc_debugfs_entry;
187 struct lprocfs_stats *svc_stats;
188 int i, rc;
189 unsigned int svc_counter_config = LPROCFS_CNTR_AVGMINMAX |
190 LPROCFS_CNTR_STDDEV;
191
192 LASSERT(!*debugfs_root_ret);
193 LASSERT(!*stats_ret);
194
195 svc_stats = lprocfs_alloc_stats(EXTRA_MAX_OPCODES + LUSTRE_MAX_OPCODES,
196 0);
197 if (!svc_stats)
198 return;
199
200 if (dir) {
201 svc_debugfs_entry = ldebugfs_register(dir, root, NULL, NULL);
202 if (IS_ERR(svc_debugfs_entry)) {
203 lprocfs_free_stats(&svc_stats);
204 return;
205 }
206 } else {
207 svc_debugfs_entry = root;
208 }
209
210 lprocfs_counter_init(svc_stats, PTLRPC_REQWAIT_CNTR,
211 svc_counter_config, "req_waittime", "usec");
212 lprocfs_counter_init(svc_stats, PTLRPC_REQQDEPTH_CNTR,
213 svc_counter_config, "req_qdepth", "reqs");
214 lprocfs_counter_init(svc_stats, PTLRPC_REQACTIVE_CNTR,
215 svc_counter_config, "req_active", "reqs");
216 lprocfs_counter_init(svc_stats, PTLRPC_TIMEOUT,
217 svc_counter_config, "req_timeout", "sec");
218 lprocfs_counter_init(svc_stats, PTLRPC_REQBUF_AVAIL_CNTR,
219 svc_counter_config, "reqbuf_avail", "bufs");
220 for (i = 0; i < EXTRA_LAST_OPC; i++) {
221 char *units;
222
223 switch (i) {
224 case BRW_WRITE_BYTES:
225 case BRW_READ_BYTES:
226 units = "bytes";
227 break;
228 default:
229 units = "reqs";
230 break;
231 }
232 lprocfs_counter_init(svc_stats, PTLRPC_LAST_CNTR + i,
233 svc_counter_config,
234 ll_eopcode2str(i), units);
235 }
236 for (i = 0; i < LUSTRE_MAX_OPCODES; i++) {
237 __u32 opcode = ll_rpc_opcode_table[i].opcode;
238
239 lprocfs_counter_init(svc_stats,
240 EXTRA_MAX_OPCODES + i, svc_counter_config,
241 ll_opcode2str(opcode), "usec");
242 }
243
244 rc = ldebugfs_register_stats(svc_debugfs_entry, name, svc_stats);
245 if (rc < 0) {
246 if (dir)
247 ldebugfs_remove(&svc_debugfs_entry);
248 lprocfs_free_stats(&svc_stats);
249 } else {
250 if (dir)
251 *debugfs_root_ret = svc_debugfs_entry;
252 *stats_ret = svc_stats;
253 }
254}
255
256static int
257ptlrpc_lprocfs_req_history_len_seq_show(struct seq_file *m, void *v)
258{
259 struct ptlrpc_service *svc = m->private;
260 struct ptlrpc_service_part *svcpt;
261 int total = 0;
262 int i;
263
264 ptlrpc_service_for_each_part(svcpt, i, svc)
265 total += svcpt->scp_hist_nrqbds;
266
267 seq_printf(m, "%d\n", total);
268 return 0;
269}
270
271LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_req_history_len);
272
273static int
274ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file *m, void *n)
275{
276 struct ptlrpc_service *svc = m->private;
277 struct ptlrpc_service_part *svcpt;
278 int total = 0;
279 int i;
280
281 ptlrpc_service_for_each_part(svcpt, i, svc)
282 total += svc->srv_hist_nrqbds_cpt_max;
283
284 seq_printf(m, "%d\n", total);
285 return 0;
286}
287
288static ssize_t
289ptlrpc_lprocfs_req_history_max_seq_write(struct file *file,
290 const char __user *buffer,
291 size_t count, loff_t *off)
292{
293 struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
294 int bufpages;
295 int val;
296 int rc;
297
298 rc = lprocfs_write_helper(buffer, count, &val);
299 if (rc < 0)
300 return rc;
301
302 if (val < 0)
303 return -ERANGE;
304
305
306
307
308
309 bufpages = (svc->srv_buf_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
310 if (val > totalram_pages / (2 * bufpages))
311 return -ERANGE;
312
313 spin_lock(&svc->srv_lock);
314
315 if (val == 0)
316 svc->srv_hist_nrqbds_cpt_max = 0;
317 else
318 svc->srv_hist_nrqbds_cpt_max = max(1, (val / svc->srv_ncpts));
319
320 spin_unlock(&svc->srv_lock);
321
322 return count;
323}
324
325LPROC_SEQ_FOPS(ptlrpc_lprocfs_req_history_max);
326
327static ssize_t threads_min_show(struct kobject *kobj, struct attribute *attr,
328 char *buf)
329{
330 struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
331 srv_kobj);
332
333 return sprintf(buf, "%d\n", svc->srv_nthrs_cpt_init * svc->srv_ncpts);
334}
335
336static ssize_t threads_min_store(struct kobject *kobj, struct attribute *attr,
337 const char *buffer, size_t count)
338{
339 struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
340 srv_kobj);
341 unsigned long val;
342 int rc = kstrtoul(buffer, 10, &val);
343
344 if (rc < 0)
345 return rc;
346
347 if (val / svc->srv_ncpts < PTLRPC_NTHRS_INIT)
348 return -ERANGE;
349
350 spin_lock(&svc->srv_lock);
351 if (val > svc->srv_nthrs_cpt_limit * svc->srv_ncpts) {
352 spin_unlock(&svc->srv_lock);
353 return -ERANGE;
354 }
355
356 svc->srv_nthrs_cpt_init = val / svc->srv_ncpts;
357
358 spin_unlock(&svc->srv_lock);
359
360 return count;
361}
362LUSTRE_RW_ATTR(threads_min);
363
364static ssize_t threads_started_show(struct kobject *kobj,
365 struct attribute *attr,
366 char *buf)
367{
368 struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
369 srv_kobj);
370 struct ptlrpc_service_part *svcpt;
371 int total = 0;
372 int i;
373
374 ptlrpc_service_for_each_part(svcpt, i, svc)
375 total += svcpt->scp_nthrs_running;
376
377 return sprintf(buf, "%d\n", total);
378}
379LUSTRE_RO_ATTR(threads_started);
380
381static ssize_t threads_max_show(struct kobject *kobj, struct attribute *attr,
382 char *buf)
383{
384 struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
385 srv_kobj);
386
387 return sprintf(buf, "%d\n", svc->srv_nthrs_cpt_limit * svc->srv_ncpts);
388}
389
390static ssize_t threads_max_store(struct kobject *kobj, struct attribute *attr,
391 const char *buffer, size_t count)
392{
393 struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
394 srv_kobj);
395 unsigned long val;
396 int rc = kstrtoul(buffer, 10, &val);
397
398 if (rc < 0)
399 return rc;
400
401 if (val / svc->srv_ncpts < PTLRPC_NTHRS_INIT)
402 return -ERANGE;
403
404 spin_lock(&svc->srv_lock);
405 if (val < svc->srv_nthrs_cpt_init * svc->srv_ncpts) {
406 spin_unlock(&svc->srv_lock);
407 return -ERANGE;
408 }
409
410 svc->srv_nthrs_cpt_limit = val / svc->srv_ncpts;
411
412 spin_unlock(&svc->srv_lock);
413
414 return count;
415}
416LUSTRE_RW_ATTR(threads_max);
417
418
419
420
421
422
423
424
425
426
427
428static const char *nrs_state2str(enum ptlrpc_nrs_pol_state state)
429{
430 switch (state) {
431 default:
432 LBUG();
433 case NRS_POL_STATE_INVALID:
434 return "invalid";
435 case NRS_POL_STATE_STOPPED:
436 return "stopped";
437 case NRS_POL_STATE_STOPPING:
438 return "stopping";
439 case NRS_POL_STATE_STARTING:
440 return "starting";
441 case NRS_POL_STATE_STARTED:
442 return "started";
443 }
444}
445
446
447
448
449
450
451
452
453
454static void nrs_policy_get_info_locked(struct ptlrpc_nrs_policy *policy,
455 struct ptlrpc_nrs_pol_info *info)
456{
457 assert_spin_locked(&policy->pol_nrs->nrs_lock);
458
459 memcpy(info->pi_name, policy->pol_desc->pd_name, NRS_POL_NAME_MAX);
460
461 info->pi_fallback = !!(policy->pol_flags & PTLRPC_NRS_FL_FALLBACK);
462 info->pi_state = policy->pol_state;
463
464
465
466
467 info->pi_req_queued = policy->pol_req_queued;
468 info->pi_req_started = policy->pol_req_started;
469}
470
471
472
473
474
475static int ptlrpc_lprocfs_nrs_seq_show(struct seq_file *m, void *n)
476{
477 struct ptlrpc_service *svc = m->private;
478 struct ptlrpc_service_part *svcpt;
479 struct ptlrpc_nrs *nrs;
480 struct ptlrpc_nrs_policy *policy;
481 struct ptlrpc_nrs_pol_info *infos;
482 struct ptlrpc_nrs_pol_info tmp;
483 unsigned int num_pols;
484 unsigned int pol_idx = 0;
485 bool hp = false;
486 int i;
487 int rc = 0;
488
489
490
491
492
493 mutex_lock(&nrs_core.nrs_mutex);
494
495
496
497
498
499
500 nrs = nrs_svcpt2nrs(svc->srv_parts[0], false);
501
502 spin_lock(&nrs->nrs_lock);
503 num_pols = svc->srv_parts[0]->scp_nrs_reg.nrs_num_pols;
504 spin_unlock(&nrs->nrs_lock);
505
506 infos = kcalloc(num_pols, sizeof(*infos), GFP_NOFS);
507 if (!infos) {
508 rc = -ENOMEM;
509 goto unlock;
510 }
511again:
512
513 ptlrpc_service_for_each_part(svcpt, i, svc) {
514 nrs = nrs_svcpt2nrs(svcpt, hp);
515 spin_lock(&nrs->nrs_lock);
516
517 pol_idx = 0;
518
519 list_for_each_entry(policy, &nrs->nrs_policy_list, pol_list) {
520 LASSERT(pol_idx < num_pols);
521
522 nrs_policy_get_info_locked(policy, &tmp);
523
524
525
526
527 if (i == 0) {
528 memcpy(infos[pol_idx].pi_name, tmp.pi_name,
529 NRS_POL_NAME_MAX);
530 memcpy(&infos[pol_idx].pi_state, &tmp.pi_state,
531 sizeof(tmp.pi_state));
532 infos[pol_idx].pi_fallback = tmp.pi_fallback;
533
534
535
536
537 } else {
538 LASSERT(strncmp(infos[pol_idx].pi_name,
539 tmp.pi_name,
540 NRS_POL_NAME_MAX) == 0);
541
542
543
544
545
546
547 LASSERT(infos[pol_idx].pi_fallback ==
548 tmp.pi_fallback);
549 }
550
551 infos[pol_idx].pi_req_queued += tmp.pi_req_queued;
552 infos[pol_idx].pi_req_started += tmp.pi_req_started;
553
554 pol_idx++;
555 }
556 spin_unlock(&nrs->nrs_lock);
557 }
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589 seq_printf(m, "%s\n",
590 !hp ? "\nregular_requests:" : "high_priority_requests:");
591
592 for (pol_idx = 0; pol_idx < num_pols; pol_idx++) {
593 seq_printf(m, " - name: %s\n"
594 " state: %s\n"
595 " fallback: %s\n"
596 " queued: %-20d\n"
597 " active: %-20d\n\n",
598 infos[pol_idx].pi_name,
599 nrs_state2str(infos[pol_idx].pi_state),
600 infos[pol_idx].pi_fallback ? "yes" : "no",
601 (int)infos[pol_idx].pi_req_queued,
602 (int)infos[pol_idx].pi_req_started);
603 }
604
605 if (!hp && nrs_svc_has_hp(svc)) {
606 memset(infos, 0, num_pols * sizeof(*infos));
607
608
609
610
611 hp = true;
612 goto again;
613 }
614
615 kfree(infos);
616unlock:
617 mutex_unlock(&nrs_core.nrs_mutex);
618
619 return rc;
620}
621
622
623
624
625
626#define LPROCFS_NRS_WR_MAX_CMD (NRS_POL_NAME_MAX + sizeof(" reg") - 1)
627
628
629
630
631
632
633
634
635static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file,
636 const char __user *buffer,
637 size_t count, loff_t *off)
638{
639 struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
640 enum ptlrpc_nrs_queue_type queue = PTLRPC_NRS_QUEUE_BOTH;
641 char *cmd;
642 char *cmd_copy = NULL;
643 char *token;
644 int rc = 0;
645
646 if (count >= LPROCFS_NRS_WR_MAX_CMD)
647 return -EINVAL;
648
649 cmd = kzalloc(LPROCFS_NRS_WR_MAX_CMD, GFP_NOFS);
650 if (!cmd)
651 return -ENOMEM;
652
653
654
655 cmd_copy = cmd;
656
657 if (copy_from_user(cmd, buffer, count)) {
658 rc = -EFAULT;
659 goto out;
660 }
661
662 cmd[count] = '\0';
663
664 token = strsep(&cmd, " ");
665
666 if (strlen(token) > NRS_POL_NAME_MAX - 1) {
667 rc = -EINVAL;
668 goto out;
669 }
670
671
672
673
674 if (!cmd)
675 goto default_queue;
676
677
678
679
680 if (strcmp(cmd, "reg") == 0) {
681 queue = PTLRPC_NRS_QUEUE_REG;
682 } else if (strcmp(cmd, "hp") == 0) {
683 queue = PTLRPC_NRS_QUEUE_HP;
684 } else {
685 rc = -EINVAL;
686 goto out;
687 }
688
689default_queue:
690
691 if (queue == PTLRPC_NRS_QUEUE_HP && !nrs_svc_has_hp(svc)) {
692 rc = -ENODEV;
693 goto out;
694 } else if (queue == PTLRPC_NRS_QUEUE_BOTH && !nrs_svc_has_hp(svc)) {
695 queue = PTLRPC_NRS_QUEUE_REG;
696 }
697
698
699
700
701
702 mutex_lock(&nrs_core.nrs_mutex);
703
704 rc = ptlrpc_nrs_policy_control(svc, queue, token, PTLRPC_NRS_CTL_START,
705 false, NULL);
706
707 mutex_unlock(&nrs_core.nrs_mutex);
708out:
709 kfree(cmd_copy);
710
711 return rc < 0 ? rc : count;
712}
713
714LPROC_SEQ_FOPS(ptlrpc_lprocfs_nrs);
715
716
717
718struct ptlrpc_srh_iterator {
719 int srhi_idx;
720 __u64 srhi_seq;
721 struct ptlrpc_request *srhi_req;
722};
723
724static int
725ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt,
726 struct ptlrpc_srh_iterator *srhi,
727 __u64 seq)
728{
729 struct list_head *e;
730 struct ptlrpc_request *req;
731
732 if (srhi->srhi_req && srhi->srhi_seq > svcpt->scp_hist_seq_culled &&
733 srhi->srhi_seq <= seq) {
734
735
736
737
738
739
740
741 LASSERTF(srhi->srhi_seq == srhi->srhi_req->rq_history_seq,
742 "%s:%d: seek seq %llu, request seq %llu\n",
743 svcpt->scp_service->srv_name, svcpt->scp_cpt,
744 srhi->srhi_seq, srhi->srhi_req->rq_history_seq);
745 LASSERTF(!list_empty(&svcpt->scp_hist_reqs),
746 "%s:%d: seek offset %llu, request seq %llu, last culled %llu\n",
747 svcpt->scp_service->srv_name, svcpt->scp_cpt,
748 seq, srhi->srhi_seq, svcpt->scp_hist_seq_culled);
749 e = &srhi->srhi_req->rq_history_list;
750 } else {
751
752 e = svcpt->scp_hist_reqs.next;
753 }
754
755 while (e != &svcpt->scp_hist_reqs) {
756 req = list_entry(e, struct ptlrpc_request, rq_history_list);
757
758 if (req->rq_history_seq >= seq) {
759 srhi->srhi_seq = req->rq_history_seq;
760 srhi->srhi_req = req;
761 return 0;
762 }
763 e = e->next;
764 }
765
766 return -ENOENT;
767}
768
769
770
771
772
773
774
775
776
777
778
779
780
781#define PTLRPC_REQ_POS2CPT(svc, pos) \
782 ((svc)->srv_cpt_bits == 0 ? 0 : \
783 (__u64)(pos) >> (64 - (svc)->srv_cpt_bits))
784
785
786#define PTLRPC_REQ_CPT2POS(svc, cpt) \
787 ((svc)->srv_cpt_bits == 0 ? 0 : \
788 (cpt) << (64 - (svc)->srv_cpt_bits))
789
790
791#define PTLRPC_REQ_SEQ2POS(svc, seq) \
792 ((svc)->srv_cpt_bits == 0 ? (seq) : \
793 ((seq) >> (svc)->srv_cpt_bits) | \
794 ((seq) << (64 - (svc)->srv_cpt_bits)))
795
796
797#define PTLRPC_REQ_POS2SEQ(svc, pos) \
798 ((svc)->srv_cpt_bits == 0 ? (pos) : \
799 ((__u64)(pos) << (svc)->srv_cpt_bits) | \
800 ((__u64)(pos) >> (64 - (svc)->srv_cpt_bits)))
801
802static void *
803ptlrpc_lprocfs_svc_req_history_start(struct seq_file *s, loff_t *pos)
804{
805 struct ptlrpc_service *svc = s->private;
806 struct ptlrpc_service_part *svcpt;
807 struct ptlrpc_srh_iterator *srhi;
808 unsigned int cpt;
809 int rc;
810 int i;
811
812 if (sizeof(loff_t) != sizeof(__u64)) {
813 CWARN("Failed to read request history because size of loff_t %d can't match size of u64\n",
814 (int)sizeof(loff_t));
815 return NULL;
816 }
817
818 srhi = kzalloc(sizeof(*srhi), GFP_NOFS);
819 if (!srhi)
820 return NULL;
821
822 srhi->srhi_seq = 0;
823 srhi->srhi_req = NULL;
824
825 cpt = PTLRPC_REQ_POS2CPT(svc, *pos);
826
827 ptlrpc_service_for_each_part(svcpt, i, svc) {
828 if (i < cpt)
829 continue;
830 if (i > cpt)
831 *pos = PTLRPC_REQ_CPT2POS(svc, i);
832
833 spin_lock(&svcpt->scp_lock);
834 rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi,
835 PTLRPC_REQ_POS2SEQ(svc, *pos));
836 spin_unlock(&svcpt->scp_lock);
837 if (rc == 0) {
838 *pos = PTLRPC_REQ_SEQ2POS(svc, srhi->srhi_seq);
839 srhi->srhi_idx = i;
840 return srhi;
841 }
842 }
843
844 kfree(srhi);
845 return NULL;
846}
847
848static void
849ptlrpc_lprocfs_svc_req_history_stop(struct seq_file *s, void *iter)
850{
851 struct ptlrpc_srh_iterator *srhi = iter;
852
853 kfree(srhi);
854}
855
856static void *
857ptlrpc_lprocfs_svc_req_history_next(struct seq_file *s,
858 void *iter, loff_t *pos)
859{
860 struct ptlrpc_service *svc = s->private;
861 struct ptlrpc_srh_iterator *srhi = iter;
862 struct ptlrpc_service_part *svcpt;
863 __u64 seq;
864 int rc;
865 int i;
866
867 for (i = srhi->srhi_idx; i < svc->srv_ncpts; i++) {
868 svcpt = svc->srv_parts[i];
869
870 if (i > srhi->srhi_idx) {
871 srhi->srhi_req = NULL;
872 seq = 0;
873 srhi->srhi_seq = 0;
874 } else {
875 seq = srhi->srhi_seq + (1 << svc->srv_cpt_bits);
876 }
877
878 spin_lock(&svcpt->scp_lock);
879 rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, seq);
880 spin_unlock(&svcpt->scp_lock);
881 if (rc == 0) {
882 *pos = PTLRPC_REQ_SEQ2POS(svc, srhi->srhi_seq);
883 srhi->srhi_idx = i;
884 return srhi;
885 }
886 }
887
888 kfree(srhi);
889 return NULL;
890}
891
892static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
893{
894 struct ptlrpc_service *svc = s->private;
895 struct ptlrpc_srh_iterator *srhi = iter;
896 struct ptlrpc_service_part *svcpt;
897 struct ptlrpc_request *req;
898 int rc;
899
900 LASSERT(srhi->srhi_idx < svc->srv_ncpts);
901
902 svcpt = svc->srv_parts[srhi->srhi_idx];
903
904 spin_lock(&svcpt->scp_lock);
905
906 rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, srhi->srhi_seq);
907
908 if (rc == 0) {
909 struct timespec64 arrival, sent, arrivaldiff;
910 char nidstr[LNET_NIDSTR_SIZE];
911
912 req = srhi->srhi_req;
913
914 libcfs_nid2str_r(req->rq_self, nidstr, sizeof(nidstr));
915 arrival.tv_sec = req->rq_arrival_time.tv_sec;
916 arrival.tv_nsec = req->rq_arrival_time.tv_nsec;
917 sent.tv_sec = req->rq_sent;
918 sent.tv_nsec = 0;
919 arrivaldiff = timespec64_sub(sent, arrival);
920
921
922
923
924
925
926
927
928 seq_printf(s, "%lld:%s:%s:x%llu:%d:%s:%lld.%06lld:%lld.%06llds(%+lld.0s) ",
929 req->rq_history_seq, nidstr,
930 libcfs_id2str(req->rq_peer), req->rq_xid,
931 req->rq_reqlen, ptlrpc_rqphase2str(req),
932 (s64)req->rq_arrival_time.tv_sec,
933 (s64)req->rq_arrival_time.tv_nsec / NSEC_PER_USEC,
934 (s64)arrivaldiff.tv_sec,
935 (s64)(arrivaldiff.tv_nsec / NSEC_PER_USEC),
936 (s64)(req->rq_sent - req->rq_deadline));
937 if (!svc->srv_ops.so_req_printer)
938 seq_putc(s, '\n');
939 else
940 svc->srv_ops.so_req_printer(s, srhi->srhi_req);
941 }
942
943 spin_unlock(&svcpt->scp_lock);
944 return rc;
945}
946
947static int
948ptlrpc_lprocfs_svc_req_history_open(struct inode *inode, struct file *file)
949{
950 static const struct seq_operations sops = {
951 .start = ptlrpc_lprocfs_svc_req_history_start,
952 .stop = ptlrpc_lprocfs_svc_req_history_stop,
953 .next = ptlrpc_lprocfs_svc_req_history_next,
954 .show = ptlrpc_lprocfs_svc_req_history_show,
955 };
956 struct seq_file *seqf;
957 int rc;
958
959 rc = seq_open(file, &sops);
960 if (rc)
961 return rc;
962
963 seqf = file->private_data;
964 seqf->private = inode->i_private;
965 return 0;
966}
967
968
969static int ptlrpc_lprocfs_timeouts_seq_show(struct seq_file *m, void *n)
970{
971 struct ptlrpc_service *svc = m->private;
972 struct ptlrpc_service_part *svcpt;
973 struct dhms ts;
974 time64_t worstt;
975 unsigned int cur;
976 unsigned int worst;
977 int i;
978
979 if (AT_OFF) {
980 seq_printf(m, "adaptive timeouts off, using obd_timeout %u\n",
981 obd_timeout);
982 return 0;
983 }
984
985 ptlrpc_service_for_each_part(svcpt, i, svc) {
986 cur = at_get(&svcpt->scp_at_estimate);
987 worst = svcpt->scp_at_estimate.at_worst_ever;
988 worstt = svcpt->scp_at_estimate.at_worst_time;
989 s2dhms(&ts, ktime_get_real_seconds() - worstt);
990
991 seq_printf(m, "%10s : cur %3u worst %3u (at %lld, "
992 DHMS_FMT " ago) ", "service",
993 cur, worst, (s64)worstt, DHMS_VARS(&ts));
994
995 lprocfs_at_hist_helper(m, &svcpt->scp_at_estimate);
996 }
997
998 return 0;
999}
1000
1001LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_timeouts);
1002
1003static ssize_t high_priority_ratio_show(struct kobject *kobj,
1004 struct attribute *attr,
1005 char *buf)
1006{
1007 struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
1008 srv_kobj);
1009 return sprintf(buf, "%d\n", svc->srv_hpreq_ratio);
1010}
1011
1012static ssize_t high_priority_ratio_store(struct kobject *kobj,
1013 struct attribute *attr,
1014 const char *buffer,
1015 size_t count)
1016{
1017 struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
1018 srv_kobj);
1019 int rc;
1020 int val;
1021
1022 rc = kstrtoint(buffer, 10, &val);
1023 if (rc < 0)
1024 return rc;
1025
1026 if (val < 0)
1027 return -ERANGE;
1028
1029 spin_lock(&svc->srv_lock);
1030 svc->srv_hpreq_ratio = val;
1031 spin_unlock(&svc->srv_lock);
1032
1033 return count;
1034}
1035LUSTRE_RW_ATTR(high_priority_ratio);
1036
1037static struct attribute *ptlrpc_svc_attrs[] = {
1038 &lustre_attr_threads_min.attr,
1039 &lustre_attr_threads_started.attr,
1040 &lustre_attr_threads_max.attr,
1041 &lustre_attr_high_priority_ratio.attr,
1042 NULL,
1043};
1044
1045static void ptlrpc_sysfs_svc_release(struct kobject *kobj)
1046{
1047 struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
1048 srv_kobj);
1049
1050 complete(&svc->srv_kobj_unregister);
1051}
1052
1053static struct kobj_type ptlrpc_svc_ktype = {
1054 .default_attrs = ptlrpc_svc_attrs,
1055 .sysfs_ops = &lustre_sysfs_ops,
1056 .release = ptlrpc_sysfs_svc_release,
1057};
1058
1059void ptlrpc_sysfs_unregister_service(struct ptlrpc_service *svc)
1060{
1061
1062 if (svc->srv_kobj.kset) {
1063 kobject_put(&svc->srv_kobj);
1064 wait_for_completion(&svc->srv_kobj_unregister);
1065 }
1066}
1067
1068int ptlrpc_sysfs_register_service(struct kset *parent,
1069 struct ptlrpc_service *svc)
1070{
1071 int rc;
1072
1073 svc->srv_kobj.kset = parent;
1074 init_completion(&svc->srv_kobj_unregister);
1075 rc = kobject_init_and_add(&svc->srv_kobj, &ptlrpc_svc_ktype, NULL,
1076 "%s", svc->srv_name);
1077
1078 return rc;
1079}
1080
1081void ptlrpc_ldebugfs_register_service(struct dentry *entry,
1082 struct ptlrpc_service *svc)
1083{
1084 struct lprocfs_vars lproc_vars[] = {
1085 {.name = "req_buffer_history_len",
1086 .fops = &ptlrpc_lprocfs_req_history_len_fops,
1087 .data = svc},
1088 {.name = "req_buffer_history_max",
1089 .fops = &ptlrpc_lprocfs_req_history_max_fops,
1090 .data = svc},
1091 {.name = "timeouts",
1092 .fops = &ptlrpc_lprocfs_timeouts_fops,
1093 .data = svc},
1094 {.name = "nrs_policies",
1095 .fops = &ptlrpc_lprocfs_nrs_fops,
1096 .data = svc},
1097 {NULL}
1098 };
1099 static const struct file_operations req_history_fops = {
1100 .owner = THIS_MODULE,
1101 .open = ptlrpc_lprocfs_svc_req_history_open,
1102 .read = seq_read,
1103 .llseek = seq_lseek,
1104 .release = lprocfs_seq_release,
1105 };
1106
1107 int rc;
1108
1109 ptlrpc_ldebugfs_register(entry, svc->srv_name,
1110 "stats", &svc->srv_debugfs_entry,
1111 &svc->srv_stats);
1112
1113 if (IS_ERR_OR_NULL(svc->srv_debugfs_entry))
1114 return;
1115
1116 ldebugfs_add_vars(svc->srv_debugfs_entry, lproc_vars, NULL);
1117
1118 rc = ldebugfs_seq_create(svc->srv_debugfs_entry, "req_history",
1119 0400, &req_history_fops, svc);
1120 if (rc)
1121 CWARN("Error adding the req_history file\n");
1122}
1123
1124void ptlrpc_lprocfs_register_obd(struct obd_device *obddev)
1125{
1126 ptlrpc_ldebugfs_register(obddev->obd_debugfs_entry, NULL, "stats",
1127 &obddev->obd_svc_debugfs_entry,
1128 &obddev->obd_svc_stats);
1129}
1130EXPORT_SYMBOL(ptlrpc_lprocfs_register_obd);
1131
1132void ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request *req, long amount)
1133{
1134 struct lprocfs_stats *svc_stats;
1135 __u32 op = lustre_msg_get_opc(req->rq_reqmsg);
1136 int opc = opcode_offset(op);
1137
1138 svc_stats = req->rq_import->imp_obd->obd_svc_stats;
1139 if (!svc_stats || opc <= 0)
1140 return;
1141 LASSERT(opc < LUSTRE_MAX_OPCODES);
1142 if (!(op == LDLM_ENQUEUE || op == MDS_REINT))
1143 lprocfs_counter_add(svc_stats, opc + EXTRA_MAX_OPCODES, amount);
1144}
1145
1146void ptlrpc_lprocfs_brw(struct ptlrpc_request *req, int bytes)
1147{
1148 struct lprocfs_stats *svc_stats;
1149 int idx;
1150
1151 if (!req->rq_import)
1152 return;
1153 svc_stats = req->rq_import->imp_obd->obd_svc_stats;
1154 if (!svc_stats)
1155 return;
1156 idx = lustre_msg_get_opc(req->rq_reqmsg);
1157 switch (idx) {
1158 case OST_READ:
1159 idx = BRW_READ_BYTES + PTLRPC_LAST_CNTR;
1160 break;
1161 case OST_WRITE:
1162 idx = BRW_WRITE_BYTES + PTLRPC_LAST_CNTR;
1163 break;
1164 default:
1165 LASSERTF(0, "unsupported opcode %u\n", idx);
1166 break;
1167 }
1168
1169 lprocfs_counter_add(svc_stats, idx, bytes);
1170}
1171EXPORT_SYMBOL(ptlrpc_lprocfs_brw);
1172
1173void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc)
1174{
1175 if (!IS_ERR_OR_NULL(svc->srv_debugfs_entry))
1176 ldebugfs_remove(&svc->srv_debugfs_entry);
1177
1178 if (svc->srv_stats)
1179 lprocfs_free_stats(&svc->srv_stats);
1180}
1181
1182void ptlrpc_lprocfs_unregister_obd(struct obd_device *obd)
1183{
1184 if (!IS_ERR_OR_NULL(obd->obd_svc_debugfs_entry))
1185 ldebugfs_remove(&obd->obd_svc_debugfs_entry);
1186
1187 if (obd->obd_svc_stats)
1188 lprocfs_free_stats(&obd->obd_svc_stats);
1189}
1190EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd);
1191
1192#undef BUFLEN
1193
1194int lprocfs_wr_ping(struct file *file, const char __user *buffer,
1195 size_t count, loff_t *off)
1196{
1197 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
1198 struct ptlrpc_request *req;
1199 int rc;
1200
1201 rc = lprocfs_climp_check(obd);
1202 if (rc)
1203 return rc;
1204
1205 req = ptlrpc_prep_ping(obd->u.cli.cl_import);
1206 up_read(&obd->u.cli.cl_sem);
1207 if (!req)
1208 return -ENOMEM;
1209
1210 req->rq_send_state = LUSTRE_IMP_FULL;
1211
1212 rc = ptlrpc_queue_wait(req);
1213
1214 ptlrpc_req_finished(req);
1215 if (rc >= 0)
1216 return count;
1217 return rc;
1218}
1219EXPORT_SYMBOL(lprocfs_wr_ping);
1220
1221
1222
1223
1224
1225int lprocfs_wr_import(struct file *file, const char __user *buffer,
1226 size_t count, loff_t *off)
1227{
1228 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
1229 struct obd_import *imp = obd->u.cli.cl_import;
1230 char *kbuf = NULL;
1231 char *uuid;
1232 char *ptr;
1233 int do_reconn = 1;
1234 const char prefix[] = "connection=";
1235 const int prefix_len = sizeof(prefix) - 1;
1236
1237 if (count > PAGE_SIZE - 1 || count <= prefix_len)
1238 return -EINVAL;
1239
1240 kbuf = kzalloc(count + 1, GFP_NOFS);
1241 if (!kbuf)
1242 return -ENOMEM;
1243
1244 if (copy_from_user(kbuf, buffer, count)) {
1245 count = -EFAULT;
1246 goto out;
1247 }
1248
1249 kbuf[count] = 0;
1250
1251
1252 if (strncmp(prefix, kbuf, prefix_len) != 0) {
1253 count = -EINVAL;
1254 goto out;
1255 }
1256
1257 uuid = kbuf + prefix_len;
1258 ptr = strstr(uuid, "::");
1259 if (ptr) {
1260 __u32 inst;
1261 char *endptr;
1262
1263 *ptr = 0;
1264 do_reconn = 0;
1265 ptr += strlen("::");
1266 inst = simple_strtoul(ptr, &endptr, 10);
1267 if (*endptr) {
1268 CERROR("config: wrong instance # %s\n", ptr);
1269 } else if (inst != imp->imp_connect_data.ocd_instance) {
1270 CDEBUG(D_INFO, "IR: %s is connecting to an obsoleted target(%u/%u), reconnecting...\n",
1271 imp->imp_obd->obd_name,
1272 imp->imp_connect_data.ocd_instance, inst);
1273 do_reconn = 1;
1274 } else {
1275 CDEBUG(D_INFO, "IR: %s has already been connecting to new target(%u)\n",
1276 imp->imp_obd->obd_name, inst);
1277 }
1278 }
1279
1280 if (do_reconn)
1281 ptlrpc_recover_import(imp, uuid, 1);
1282
1283out:
1284 kfree(kbuf);
1285 return count;
1286}
1287EXPORT_SYMBOL(lprocfs_wr_import);
1288
1289int lprocfs_rd_pinger_recov(struct seq_file *m, void *n)
1290{
1291 struct obd_device *obd = m->private;
1292 struct obd_import *imp = obd->u.cli.cl_import;
1293 int rc;
1294
1295 rc = lprocfs_climp_check(obd);
1296 if (rc)
1297 return rc;
1298
1299 seq_printf(m, "%d\n", !imp->imp_no_pinger_recover);
1300 up_read(&obd->u.cli.cl_sem);
1301
1302 return 0;
1303}
1304EXPORT_SYMBOL(lprocfs_rd_pinger_recov);
1305
1306int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer,
1307 size_t count, loff_t *off)
1308{
1309 struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
1310 struct client_obd *cli = &obd->u.cli;
1311 struct obd_import *imp = cli->cl_import;
1312 int rc, val;
1313
1314 rc = lprocfs_write_helper(buffer, count, &val);
1315 if (rc < 0)
1316 return rc;
1317
1318 if (val != 0 && val != 1)
1319 return -ERANGE;
1320
1321 rc = lprocfs_climp_check(obd);
1322 if (rc)
1323 return rc;
1324
1325 spin_lock(&imp->imp_lock);
1326 imp->imp_no_pinger_recover = !val;
1327 spin_unlock(&imp->imp_lock);
1328 up_read(&obd->u.cli.cl_sem);
1329
1330 return count;
1331}
1332EXPORT_SYMBOL(lprocfs_wr_pinger_recov);
1333