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