1/*
2 * GPL HEADER START
3 *
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
22 * have any questions.
23 *
24 * GPL HEADER END
25 */
26/*
27 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
29 *
30 * Copyright (c) 2011, 2012, Intel Corporation.
31 */
32/*
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
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
48struct 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 },    /* formerly OST_SAN_READ */
67	{ 15,		NULL },    /* formerly OST_SAN_WRITE */
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
139struct 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	/* When one of the assertions below fail, chances are that:
162	 *     1) A new opcode was added in include/lustre/lustre_idl.h,
163	 *	but is missing from the table above.
164	 * or  2) The opcode space was renumbered or rearranged,
165	 *	and the opcode_offset() function in
166	 *	ptlrpc_internal.h needs to be modified.
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
178const char* ll_eopcode2str(__u32 opcode)
179{
180	LASSERT(ll_eopcode_table[opcode].opcode == opcode);
181	return ll_eopcode_table[opcode].opname;
182}
183#if defined (CONFIG_PROC_FS)
184void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir,
185			     char *name, struct proc_dir_entry **procroot_ret,
186			     struct lprocfs_stats **stats_ret)
187{
188	struct proc_dir_entry *svc_procroot;
189	struct lprocfs_stats *svc_stats;
190	int i, rc;
191	unsigned int svc_counter_config = LPROCFS_CNTR_AVGMINMAX |
192					  LPROCFS_CNTR_STDDEV;
193
194	LASSERT(*procroot_ret == NULL);
195	LASSERT(*stats_ret == NULL);
196
197	svc_stats = lprocfs_alloc_stats(EXTRA_MAX_OPCODES+LUSTRE_MAX_OPCODES,
198					0);
199	if (svc_stats == NULL)
200		return;
201
202	if (dir) {
203		svc_procroot = lprocfs_register(dir, root, NULL, NULL);
204		if (IS_ERR(svc_procroot)) {
205			lprocfs_free_stats(&svc_stats);
206			return;
207		}
208	} else {
209		svc_procroot = root;
210	}
211
212	lprocfs_counter_init(svc_stats, PTLRPC_REQWAIT_CNTR,
213			     svc_counter_config, "req_waittime", "usec");
214	lprocfs_counter_init(svc_stats, PTLRPC_REQQDEPTH_CNTR,
215			     svc_counter_config, "req_qdepth", "reqs");
216	lprocfs_counter_init(svc_stats, PTLRPC_REQACTIVE_CNTR,
217			     svc_counter_config, "req_active", "reqs");
218	lprocfs_counter_init(svc_stats, PTLRPC_TIMEOUT,
219			     svc_counter_config, "req_timeout", "sec");
220	lprocfs_counter_init(svc_stats, PTLRPC_REQBUF_AVAIL_CNTR,
221			     svc_counter_config, "reqbuf_avail", "bufs");
222	for (i = 0; i < EXTRA_LAST_OPC; i++) {
223		char *units;
224
225		switch (i) {
226		case BRW_WRITE_BYTES:
227		case BRW_READ_BYTES:
228			units = "bytes";
229			break;
230		default:
231			units = "reqs";
232			break;
233		}
234		lprocfs_counter_init(svc_stats, PTLRPC_LAST_CNTR + i,
235				     svc_counter_config,
236				     ll_eopcode2str(i), units);
237	}
238	for (i = 0; i < LUSTRE_MAX_OPCODES; i++) {
239		__u32 opcode = ll_rpc_opcode_table[i].opcode;
240		lprocfs_counter_init(svc_stats,
241				     EXTRA_MAX_OPCODES + i, svc_counter_config,
242				     ll_opcode2str(opcode), "usec");
243	}
244
245	rc = lprocfs_register_stats(svc_procroot, name, svc_stats);
246	if (rc < 0) {
247		if (dir)
248			lprocfs_remove(&svc_procroot);
249		lprocfs_free_stats(&svc_stats);
250	} else {
251		if (dir)
252			*procroot_ret = svc_procroot;
253		*stats_ret = svc_stats;
254	}
255}
256
257static int
258ptlrpc_lprocfs_req_history_len_seq_show(struct seq_file *m, void *v)
259{
260	struct ptlrpc_service *svc = m->private;
261	struct ptlrpc_service_part *svcpt;
262	int	total = 0;
263	int	i;
264
265	ptlrpc_service_for_each_part(svcpt, i, svc)
266		total += svcpt->scp_hist_nrqbds;
267
268	return seq_printf(m, "%d\n", total);
269}
270LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_req_history_len);
271
272static int
273ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file *m, void *n)
274{
275	struct ptlrpc_service *svc = m->private;
276	struct ptlrpc_service_part *svcpt;
277	int	total = 0;
278	int	i;
279
280	ptlrpc_service_for_each_part(svcpt, i, svc)
281		total += svc->srv_hist_nrqbds_cpt_max;
282
283	return seq_printf(m, "%d\n", total);
284}
285
286static ssize_t
287ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, const char *buffer,
288					 size_t count, loff_t *off)
289{
290	struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
291	int			    bufpages;
292	int			    val;
293	int			    rc;
294
295	rc = lprocfs_write_helper(buffer, count, &val);
296	if (rc < 0)
297		return rc;
298
299	if (val < 0)
300		return -ERANGE;
301
302	/* This sanity check is more of an insanity check; we can still
303	 * hose a kernel by allowing the request history to grow too
304	 * far. */
305	bufpages = (svc->srv_buf_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
306	if (val > totalram_pages / (2 * bufpages))
307		return -ERANGE;
308
309	spin_lock(&svc->srv_lock);
310
311	if (val == 0)
312		svc->srv_hist_nrqbds_cpt_max = 0;
313	else
314		svc->srv_hist_nrqbds_cpt_max = max(1, (val / svc->srv_ncpts));
315
316	spin_unlock(&svc->srv_lock);
317
318	return count;
319}
320LPROC_SEQ_FOPS(ptlrpc_lprocfs_req_history_max);
321
322static int
323ptlrpc_lprocfs_threads_min_seq_show(struct seq_file *m, void *n)
324{
325	struct ptlrpc_service *svc = m->private;
326
327	return seq_printf(m, "%d\n",
328			svc->srv_nthrs_cpt_init * svc->srv_ncpts);
329}
330
331static ssize_t
332ptlrpc_lprocfs_threads_min_seq_write(struct file *file, const char *buffer,
333				     size_t count, loff_t *off)
334{
335	struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
336	int	val;
337	int	rc = lprocfs_write_helper(buffer, count, &val);
338
339	if (rc < 0)
340		return rc;
341
342	if (val / svc->srv_ncpts < PTLRPC_NTHRS_INIT)
343		return -ERANGE;
344
345	spin_lock(&svc->srv_lock);
346	if (val > svc->srv_nthrs_cpt_limit * svc->srv_ncpts) {
347		spin_unlock(&svc->srv_lock);
348		return -ERANGE;
349	}
350
351	svc->srv_nthrs_cpt_init = val / svc->srv_ncpts;
352
353	spin_unlock(&svc->srv_lock);
354
355	return count;
356}
357LPROC_SEQ_FOPS(ptlrpc_lprocfs_threads_min);
358
359static int
360ptlrpc_lprocfs_threads_started_seq_show(struct seq_file *m, void *n)
361{
362	struct ptlrpc_service *svc = m->private;
363	struct ptlrpc_service_part *svcpt;
364	int	total = 0;
365	int	i;
366
367	ptlrpc_service_for_each_part(svcpt, i, svc)
368		total += svcpt->scp_nthrs_running;
369
370	return seq_printf(m, "%d\n", total);
371}
372LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_threads_started);
373
374static int
375ptlrpc_lprocfs_threads_max_seq_show(struct seq_file *m, void *n)
376{
377	struct ptlrpc_service *svc = m->private;
378
379	return seq_printf(m, "%d\n",
380			svc->srv_nthrs_cpt_limit * svc->srv_ncpts);
381}
382
383static ssize_t
384ptlrpc_lprocfs_threads_max_seq_write(struct file *file, const char *buffer,
385				     size_t count, loff_t *off)
386{
387	struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
388	int	val;
389	int	rc = lprocfs_write_helper(buffer, count, &val);
390
391	if (rc < 0)
392		return rc;
393
394	if (val / svc->srv_ncpts < PTLRPC_NTHRS_INIT)
395		return -ERANGE;
396
397	spin_lock(&svc->srv_lock);
398	if (val < svc->srv_nthrs_cpt_init * svc->srv_ncpts) {
399		spin_unlock(&svc->srv_lock);
400		return -ERANGE;
401	}
402
403	svc->srv_nthrs_cpt_limit = val / svc->srv_ncpts;
404
405	spin_unlock(&svc->srv_lock);
406
407	return count;
408}
409LPROC_SEQ_FOPS(ptlrpc_lprocfs_threads_max);
410
411/**
412 * \addtogoup nrs
413 * @{
414 */
415extern struct nrs_core nrs_core;
416
417/**
418 * Translates \e ptlrpc_nrs_pol_state values to human-readable strings.
419 *
420 * \param[in] state The policy state
421 */
422static const char *nrs_state2str(enum ptlrpc_nrs_pol_state state)
423{
424	switch (state) {
425	default:
426		LBUG();
427	case NRS_POL_STATE_INVALID:
428		return "invalid";
429	case NRS_POL_STATE_STOPPED:
430		return "stopped";
431	case NRS_POL_STATE_STOPPING:
432		return "stopping";
433	case NRS_POL_STATE_STARTING:
434		return "starting";
435	case NRS_POL_STATE_STARTED:
436		return "started";
437	}
438}
439
440/**
441 * Obtains status information for \a policy.
442 *
443 * Information is copied in \a info.
444 *
445 * \param[in] policy The policy
446 * \param[out] info  Holds returned status information
447 */
448void nrs_policy_get_info_locked(struct ptlrpc_nrs_policy *policy,
449				struct ptlrpc_nrs_pol_info *info)
450{
451	LASSERT(policy != NULL);
452	LASSERT(info != NULL);
453	assert_spin_locked(&policy->pol_nrs->nrs_lock);
454
455	memcpy(info->pi_name, policy->pol_desc->pd_name, NRS_POL_NAME_MAX);
456
457	info->pi_fallback    = !!(policy->pol_flags & PTLRPC_NRS_FL_FALLBACK);
458	info->pi_state	     = policy->pol_state;
459	/**
460	 * XXX: These are accessed without holding
461	 * ptlrpc_service_part::scp_req_lock.
462	 */
463	info->pi_req_queued  = policy->pol_req_queued;
464	info->pi_req_started = policy->pol_req_started;
465}
466
467/**
468 * Reads and prints policy status information for all policies of a PTLRPC
469 * service.
470 */
471static int ptlrpc_lprocfs_nrs_seq_show(struct seq_file *m, void *n)
472{
473	struct ptlrpc_service	       *svc = m->private;
474	struct ptlrpc_service_part     *svcpt;
475	struct ptlrpc_nrs	       *nrs;
476	struct ptlrpc_nrs_policy       *policy;
477	struct ptlrpc_nrs_pol_info     *infos;
478	struct ptlrpc_nrs_pol_info	tmp;
479	unsigned			num_pols;
480	unsigned			pol_idx = 0;
481	bool				hp = false;
482	int				i;
483	int				rc = 0;
484
485	/**
486	 * Serialize NRS core lprocfs operations with policy registration/
487	 * unregistration.
488	 */
489	mutex_lock(&nrs_core.nrs_mutex);
490
491	/**
492	 * Use the first service partition's regular NRS head in order to obtain
493	 * the number of policies registered with NRS heads of this service. All
494	 * service partitions will have the same number of policies.
495	 */
496	nrs = nrs_svcpt2nrs(svc->srv_parts[0], false);
497
498	spin_lock(&nrs->nrs_lock);
499	num_pols = svc->srv_parts[0]->scp_nrs_reg.nrs_num_pols;
500	spin_unlock(&nrs->nrs_lock);
501
502	OBD_ALLOC(infos, num_pols * sizeof(*infos));
503	if (infos == NULL) {
504		rc = -ENOMEM;
505		goto out;
506	}
507again:
508
509	ptlrpc_service_for_each_part(svcpt, i, svc) {
510		nrs = nrs_svcpt2nrs(svcpt, hp);
511		spin_lock(&nrs->nrs_lock);
512
513		pol_idx = 0;
514
515		list_for_each_entry(policy, &nrs->nrs_policy_list,
516					pol_list) {
517			LASSERT(pol_idx < num_pols);
518
519			nrs_policy_get_info_locked(policy, &tmp);
520			/**
521			 * Copy values when handling the first service
522			 * partition.
523			 */
524			if (i == 0) {
525				memcpy(infos[pol_idx].pi_name, tmp.pi_name,
526				       NRS_POL_NAME_MAX);
527				memcpy(&infos[pol_idx].pi_state, &tmp.pi_state,
528				       sizeof(tmp.pi_state));
529				infos[pol_idx].pi_fallback = tmp.pi_fallback;
530				/**
531				 * For the rest of the service partitions
532				 * sanity-check the values we get.
533				 */
534			} else {
535				LASSERT(strncmp(infos[pol_idx].pi_name,
536						tmp.pi_name,
537						NRS_POL_NAME_MAX) == 0);
538				/**
539				 * Not asserting ptlrpc_nrs_pol_info::pi_state,
540				 * because it may be different between
541				 * instances of the same policy in different
542				 * service partitions.
543				 */
544				LASSERT(infos[pol_idx].pi_fallback ==
545					tmp.pi_fallback);
546			}
547
548			infos[pol_idx].pi_req_queued += tmp.pi_req_queued;
549			infos[pol_idx].pi_req_started += tmp.pi_req_started;
550
551			pol_idx++;
552		}
553		spin_unlock(&nrs->nrs_lock);
554	}
555
556	/**
557	 * Policy status information output is in YAML format.
558	 * For example:
559	 *
560	 *	regular_requests:
561	 *	  - name: fifo
562	 *	    state: started
563	 *	    fallback: yes
564	 *	    queued: 0
565	 *	    active: 0
566	 *
567	 *	  - name: crrn
568	 *	    state: started
569	 *	    fallback: no
570	 *	    queued: 2015
571	 *	    active: 384
572	 *
573	 *	high_priority_requests:
574	 *	  - name: fifo
575	 *	    state: started
576	 *	    fallback: yes
577	 *	    queued: 0
578	 *	    active: 2
579	 *
580	 *	  - name: crrn
581	 *	    state: stopped
582	 *	    fallback: no
583	 *	    queued: 0
584	 *	    active: 0
585	 */
586	seq_printf(m, "%s\n",
587		      !hp ?  "\nregular_requests:" : "high_priority_requests:");
588
589	for (pol_idx = 0; pol_idx < num_pols; pol_idx++) {
590		seq_printf(m,  "  - name: %s\n"
591			       "    state: %s\n"
592			       "    fallback: %s\n"
593			       "    queued: %-20d\n"
594			       "    active: %-20d\n\n",
595			       infos[pol_idx].pi_name,
596			       nrs_state2str(infos[pol_idx].pi_state),
597			       infos[pol_idx].pi_fallback ? "yes" : "no",
598			       (int)infos[pol_idx].pi_req_queued,
599			       (int)infos[pol_idx].pi_req_started);
600	}
601
602	if (!hp && nrs_svc_has_hp(svc)) {
603		memset(infos, 0, num_pols * sizeof(*infos));
604
605		/**
606		 * Redo the processing for the service's HP NRS heads' policies.
607		 */
608		hp = true;
609		goto again;
610	}
611
612out:
613	if (infos)
614		OBD_FREE(infos, num_pols * sizeof(*infos));
615
616	mutex_unlock(&nrs_core.nrs_mutex);
617
618	return rc;
619}
620
621/**
622 * The longest valid command string is the maximum policy name size, plus the
623 * length of the " reg" substring
624 */
625#define LPROCFS_NRS_WR_MAX_CMD	(NRS_POL_NAME_MAX + sizeof(" reg") - 1)
626
627/**
628 * Starts and stops a given policy on a PTLRPC service.
629 *
630 * Commands consist of the policy name, followed by an optional [reg|hp] token;
631 * if the optional token is omitted, the operation is performed on both the
632 * regular and high-priority (if the service has one) NRS head.
633 */
634static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file,
635					const char __user *buffer,
636					size_t count, loff_t *off)
637{
638	struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
639	enum ptlrpc_nrs_queue_type	queue = PTLRPC_NRS_QUEUE_BOTH;
640	char			       *cmd;
641	char			       *cmd_copy = NULL;
642	char			       *token;
643	int				rc = 0;
644
645	if (count >= LPROCFS_NRS_WR_MAX_CMD) {
646		rc = -EINVAL;
647		goto out;
648	}
649
650	OBD_ALLOC(cmd, LPROCFS_NRS_WR_MAX_CMD);
651	if (cmd == NULL) {
652		rc = -ENOMEM;
653		goto out;
654	}
655	/**
656	 * strsep() modifies its argument, so keep a copy
657	 */
658	cmd_copy = cmd;
659
660	if (copy_from_user(cmd, buffer, count)) {
661		rc = -EFAULT;
662		goto out;
663	}
664
665	cmd[count] = '\0';
666
667	token = strsep(&cmd, " ");
668
669	if (strlen(token) > NRS_POL_NAME_MAX - 1) {
670		rc = -EINVAL;
671		goto out;
672	}
673
674	/**
675	 * No [reg|hp] token has been specified
676	 */
677	if (cmd == NULL)
678		goto default_queue;
679
680	/**
681	 * The second token is either NULL, or an optional [reg|hp] string
682	 */
683	if (strcmp(cmd, "reg") == 0)
684		queue = PTLRPC_NRS_QUEUE_REG;
685	else if (strcmp(cmd, "hp") == 0)
686		queue = PTLRPC_NRS_QUEUE_HP;
687	else {
688		rc = -EINVAL;
689		goto out;
690	}
691
692default_queue:
693
694	if (queue == PTLRPC_NRS_QUEUE_HP && !nrs_svc_has_hp(svc)) {
695		rc = -ENODEV;
696		goto out;
697	}
698	else if (queue == PTLRPC_NRS_QUEUE_BOTH && !nrs_svc_has_hp(svc))
699		queue = PTLRPC_NRS_QUEUE_REG;
700
701	/**
702	 * Serialize NRS core lprocfs operations with policy registration/
703	 * unregistration.
704	 */
705	mutex_lock(&nrs_core.nrs_mutex);
706
707	rc = ptlrpc_nrs_policy_control(svc, queue, token, PTLRPC_NRS_CTL_START,
708				       false, NULL);
709
710	mutex_unlock(&nrs_core.nrs_mutex);
711out:
712	if (cmd_copy)
713		OBD_FREE(cmd_copy, LPROCFS_NRS_WR_MAX_CMD);
714
715	return rc < 0 ? rc : count;
716}
717LPROC_SEQ_FOPS(ptlrpc_lprocfs_nrs);
718
719/** @} nrs */
720
721struct ptlrpc_srh_iterator {
722	int			srhi_idx;
723	__u64			srhi_seq;
724	struct ptlrpc_request	*srhi_req;
725};
726
727int
728ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt,
729				    struct ptlrpc_srh_iterator *srhi,
730				    __u64 seq)
731{
732	struct list_head		*e;
733	struct ptlrpc_request	*req;
734
735	if (srhi->srhi_req != NULL &&
736	    srhi->srhi_seq > svcpt->scp_hist_seq_culled &&
737	    srhi->srhi_seq <= seq) {
738		/* If srhi_req was set previously, hasn't been culled and
739		 * we're searching for a seq on or after it (i.e. more
740		 * recent), search from it onwards.
741		 * Since the service history is LRU (i.e. culled reqs will
742		 * be near the head), we shouldn't have to do long
743		 * re-scans */
744		LASSERTF(srhi->srhi_seq == srhi->srhi_req->rq_history_seq,
745			 "%s:%d: seek seq %llu, request seq %llu\n",
746			 svcpt->scp_service->srv_name, svcpt->scp_cpt,
747			 srhi->srhi_seq, srhi->srhi_req->rq_history_seq);
748		LASSERTF(!list_empty(&svcpt->scp_hist_reqs),
749			 "%s:%d: seek offset %llu, request seq %llu, "
750			 "last culled %llu\n",
751			 svcpt->scp_service->srv_name, svcpt->scp_cpt,
752			 seq, srhi->srhi_seq, svcpt->scp_hist_seq_culled);
753		e = &srhi->srhi_req->rq_history_list;
754	} else {
755		/* search from start */
756		e = svcpt->scp_hist_reqs.next;
757	}
758
759	while (e != &svcpt->scp_hist_reqs) {
760		req = list_entry(e, struct ptlrpc_request, rq_history_list);
761
762		if (req->rq_history_seq >= seq) {
763			srhi->srhi_seq = req->rq_history_seq;
764			srhi->srhi_req = req;
765			return 0;
766		}
767		e = e->next;
768	}
769
770	return -ENOENT;
771}
772
773/*
774 * ptlrpc history sequence is used as "position" of seq_file, in some case,
775 * seq_read() will increase "position" to indicate reading the next
776 * element, however, low bits of history sequence are reserved for CPT id
777 * (check the details from comments before ptlrpc_req_add_history), which
778 * means seq_read() might change CPT id of history sequence and never
779 * finish reading of requests on a CPT. To make it work, we have to shift
780 * CPT id to high bits and timestamp to low bits, so seq_read() will only
781 * increase timestamp which can correctly indicate the next position.
782 */
783
784/* convert seq_file pos to cpt */
785#define PTLRPC_REQ_POS2CPT(svc, pos)			\
786	((svc)->srv_cpt_bits == 0 ? 0 :			\
787	 (__u64)(pos) >> (64 - (svc)->srv_cpt_bits))
788
789/* make up seq_file pos from cpt */
790#define PTLRPC_REQ_CPT2POS(svc, cpt)			\
791	((svc)->srv_cpt_bits == 0 ? 0 :			\
792	 (cpt) << (64 - (svc)->srv_cpt_bits))
793
794/* convert sequence to position */
795#define PTLRPC_REQ_SEQ2POS(svc, seq)			\
796	((svc)->srv_cpt_bits == 0 ? (seq) :		\
797	 ((seq) >> (svc)->srv_cpt_bits) |		\
798	 ((seq) << (64 - (svc)->srv_cpt_bits)))
799
800/* convert position to sequence */
801#define PTLRPC_REQ_POS2SEQ(svc, pos)			\
802	((svc)->srv_cpt_bits == 0 ? (pos) :		\
803	 ((__u64)(pos) << (svc)->srv_cpt_bits) |	\
804	 ((__u64)(pos) >> (64 - (svc)->srv_cpt_bits)))
805
806static void *
807ptlrpc_lprocfs_svc_req_history_start(struct seq_file *s, loff_t *pos)
808{
809	struct ptlrpc_service		*svc = s->private;
810	struct ptlrpc_service_part	*svcpt;
811	struct ptlrpc_srh_iterator	*srhi;
812	unsigned int			cpt;
813	int				rc;
814	int				i;
815
816	if (sizeof(loff_t) != sizeof(__u64)) { /* can't support */
817		CWARN("Failed to read request history because size of loff_t "
818		      "%d can't match size of u64\n", (int)sizeof(loff_t));
819		return NULL;
820	}
821
822	OBD_ALLOC(srhi, sizeof(*srhi));
823	if (srhi == NULL)
824		return NULL;
825
826	srhi->srhi_seq = 0;
827	srhi->srhi_req = NULL;
828
829	cpt = PTLRPC_REQ_POS2CPT(svc, *pos);
830
831	ptlrpc_service_for_each_part(svcpt, i, svc) {
832		if (i < cpt) /* skip */
833			continue;
834		if (i > cpt) /* make up the lowest position for this CPT */
835			*pos = PTLRPC_REQ_CPT2POS(svc, i);
836
837		spin_lock(&svcpt->scp_lock);
838		rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi,
839				PTLRPC_REQ_POS2SEQ(svc, *pos));
840		spin_unlock(&svcpt->scp_lock);
841		if (rc == 0) {
842			*pos = PTLRPC_REQ_SEQ2POS(svc, srhi->srhi_seq);
843			srhi->srhi_idx = i;
844			return srhi;
845		}
846	}
847
848	OBD_FREE(srhi, sizeof(*srhi));
849	return NULL;
850}
851
852static void
853ptlrpc_lprocfs_svc_req_history_stop(struct seq_file *s, void *iter)
854{
855	struct ptlrpc_srh_iterator *srhi = iter;
856
857	if (srhi != NULL)
858		OBD_FREE(srhi, sizeof(*srhi));
859}
860
861static void *
862ptlrpc_lprocfs_svc_req_history_next(struct seq_file *s,
863				    void *iter, loff_t *pos)
864{
865	struct ptlrpc_service		*svc = s->private;
866	struct ptlrpc_srh_iterator	*srhi = iter;
867	struct ptlrpc_service_part	*svcpt;
868	__u64				seq;
869	int				rc;
870	int				i;
871
872	for (i = srhi->srhi_idx; i < svc->srv_ncpts; i++) {
873		svcpt = svc->srv_parts[i];
874
875		if (i > srhi->srhi_idx) { /* reset iterator for a new CPT */
876			srhi->srhi_req = NULL;
877			seq = srhi->srhi_seq = 0;
878		} else { /* the next sequence */
879			seq = srhi->srhi_seq + (1 << svc->srv_cpt_bits);
880		}
881
882		spin_lock(&svcpt->scp_lock);
883		rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, seq);
884		spin_unlock(&svcpt->scp_lock);
885		if (rc == 0) {
886			*pos = PTLRPC_REQ_SEQ2POS(svc, srhi->srhi_seq);
887			srhi->srhi_idx = i;
888			return srhi;
889		}
890	}
891
892	OBD_FREE(srhi, sizeof(*srhi));
893	return NULL;
894}
895
896/* common ost/mdt so_req_printer */
897void target_print_req(void *seq_file, struct ptlrpc_request *req)
898{
899	/* Called holding srv_lock with irqs disabled.
900	 * Print specific req contents and a newline.
901	 * CAVEAT EMPTOR: check request message length before printing!!!
902	 * You might have received any old crap so you must be just as
903	 * careful here as the service's request parser!!! */
904	struct seq_file *sf = seq_file;
905
906	switch (req->rq_phase) {
907	case RQ_PHASE_NEW:
908		/* still awaiting a service thread's attention, or rejected
909		 * because the generic request message didn't unpack */
910		seq_printf(sf, "<not swabbed>\n");
911		break;
912	case RQ_PHASE_INTERPRET:
913		/* being handled, so basic msg swabbed, and opc is valid
914		 * but racing with mds_handle() */
915	case RQ_PHASE_COMPLETE:
916		/* been handled by mds_handle() reply state possibly still
917		 * volatile */
918		seq_printf(sf, "opc %d\n", lustre_msg_get_opc(req->rq_reqmsg));
919		break;
920	default:
921		DEBUG_REQ(D_ERROR, req, "bad phase %d", req->rq_phase);
922	}
923}
924EXPORT_SYMBOL(target_print_req);
925
926static int ptlrpc_lprocfs_svc_req_history_show(struct seq_file *s, void *iter)
927{
928	struct ptlrpc_service		*svc = s->private;
929	struct ptlrpc_srh_iterator	*srhi = iter;
930	struct ptlrpc_service_part	*svcpt;
931	struct ptlrpc_request		*req;
932	int				rc;
933
934	LASSERT(srhi->srhi_idx < svc->srv_ncpts);
935
936	svcpt = svc->srv_parts[srhi->srhi_idx];
937
938	spin_lock(&svcpt->scp_lock);
939
940	rc = ptlrpc_lprocfs_svc_req_history_seek(svcpt, srhi, srhi->srhi_seq);
941
942	if (rc == 0) {
943		req = srhi->srhi_req;
944
945		/* Print common req fields.
946		 * CAVEAT EMPTOR: we're racing with the service handler
947		 * here.  The request could contain any old crap, so you
948		 * must be just as careful as the service's request
949		 * parser. Currently I only print stuff here I know is OK
950		 * to look at coz it was set up in request_in_callback()!!! */
951		seq_printf(s, "%lld:%s:%s:x%llu:%d:%s:%ld:%lds(%+lds) ",
952			   req->rq_history_seq, libcfs_nid2str(req->rq_self),
953			   libcfs_id2str(req->rq_peer), req->rq_xid,
954			   req->rq_reqlen, ptlrpc_rqphase2str(req),
955			   req->rq_arrival_time.tv_sec,
956			   req->rq_sent - req->rq_arrival_time.tv_sec,
957			   req->rq_sent - req->rq_deadline);
958		if (svc->srv_ops.so_req_printer == NULL)
959			seq_printf(s, "\n");
960		else
961			svc->srv_ops.so_req_printer(s, srhi->srhi_req);
962	}
963
964	spin_unlock(&svcpt->scp_lock);
965	return rc;
966}
967
968static int
969ptlrpc_lprocfs_svc_req_history_open(struct inode *inode, struct file *file)
970{
971	static struct seq_operations sops = {
972		.start = ptlrpc_lprocfs_svc_req_history_start,
973		.stop  = ptlrpc_lprocfs_svc_req_history_stop,
974		.next  = ptlrpc_lprocfs_svc_req_history_next,
975		.show  = ptlrpc_lprocfs_svc_req_history_show,
976	};
977	struct seq_file       *seqf;
978	int		    rc;
979
980	rc = seq_open(file, &sops);
981	if (rc)
982		return rc;
983
984	seqf = file->private_data;
985	seqf->private = PDE_DATA(inode);
986	return 0;
987}
988
989/* See also lprocfs_rd_timeouts */
990static int ptlrpc_lprocfs_timeouts_seq_show(struct seq_file *m, void *n)
991{
992	struct ptlrpc_service		*svc = m->private;
993	struct ptlrpc_service_part	*svcpt;
994	struct dhms			ts;
995	time_t				worstt;
996	unsigned int			cur;
997	unsigned int			worst;
998	int				i;
999
1000	if (AT_OFF) {
1001		seq_printf(m, "adaptive timeouts off, using obd_timeout %u\n",
1002			       obd_timeout);
1003		return 0;
1004	}
1005
1006	ptlrpc_service_for_each_part(svcpt, i, svc) {
1007		cur	= at_get(&svcpt->scp_at_estimate);
1008		worst	= svcpt->scp_at_estimate.at_worst_ever;
1009		worstt	= svcpt->scp_at_estimate.at_worst_time;
1010		s2dhms(&ts, get_seconds() - worstt);
1011
1012		seq_printf(m, "%10s : cur %3u  worst %3u (at %ld, "
1013			      DHMS_FMT" ago) ", "service",
1014			      cur, worst, worstt, DHMS_VARS(&ts));
1015
1016		lprocfs_at_hist_helper(m, &svcpt->scp_at_estimate);
1017	}
1018
1019	return 0;
1020}
1021LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_timeouts);
1022
1023static int ptlrpc_lprocfs_hp_ratio_seq_show(struct seq_file *m, void *v)
1024{
1025	struct ptlrpc_service *svc = m->private;
1026	return seq_printf(m, "%d", svc->srv_hpreq_ratio);
1027}
1028
1029static ssize_t ptlrpc_lprocfs_hp_ratio_seq_write(struct file *file,
1030					     const char *buffer,
1031					     size_t count,
1032					     loff_t *off)
1033{
1034	struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private;
1035	int	rc;
1036	int	val;
1037
1038	rc = lprocfs_write_helper(buffer, count, &val);
1039	if (rc < 0)
1040		return rc;
1041
1042	if (val < 0)
1043		return -ERANGE;
1044
1045	spin_lock(&svc->srv_lock);
1046	svc->srv_hpreq_ratio = val;
1047	spin_unlock(&svc->srv_lock);
1048
1049	return count;
1050}
1051LPROC_SEQ_FOPS(ptlrpc_lprocfs_hp_ratio);
1052
1053void ptlrpc_lprocfs_register_service(struct proc_dir_entry *entry,
1054				     struct ptlrpc_service *svc)
1055{
1056	struct lprocfs_vars lproc_vars[] = {
1057		{.name       = "high_priority_ratio",
1058		 .fops	     = &ptlrpc_lprocfs_hp_ratio_fops,
1059		 .data       = svc},
1060		{.name       = "req_buffer_history_len",
1061		 .fops	     = &ptlrpc_lprocfs_req_history_len_fops,
1062		 .data       = svc},
1063		{.name       = "req_buffer_history_max",
1064		 .fops	     = &ptlrpc_lprocfs_req_history_max_fops,
1065		 .data       = svc},
1066		{.name       = "threads_min",
1067		 .fops	     = &ptlrpc_lprocfs_threads_min_fops,
1068		 .data       = svc},
1069		{.name       = "threads_max",
1070		 .fops	     = &ptlrpc_lprocfs_threads_max_fops,
1071		 .data       = svc},
1072		{.name       = "threads_started",
1073		 .fops	     = &ptlrpc_lprocfs_threads_started_fops,
1074		 .data       = svc},
1075		{.name       = "timeouts",
1076		 .fops	     = &ptlrpc_lprocfs_timeouts_fops,
1077		 .data       = svc},
1078		{.name       = "nrs_policies",
1079		 .fops	     = &ptlrpc_lprocfs_nrs_fops,
1080		 .data	     = svc},
1081		{NULL}
1082	};
1083	static struct file_operations req_history_fops = {
1084		.owner       = THIS_MODULE,
1085		.open	= ptlrpc_lprocfs_svc_req_history_open,
1086		.read	= seq_read,
1087		.llseek      = seq_lseek,
1088		.release     = lprocfs_seq_release,
1089	};
1090
1091	int rc;
1092
1093	ptlrpc_lprocfs_register(entry, svc->srv_name,
1094				"stats", &svc->srv_procroot,
1095				&svc->srv_stats);
1096
1097	if (svc->srv_procroot == NULL)
1098		return;
1099
1100	lprocfs_add_vars(svc->srv_procroot, lproc_vars, NULL);
1101
1102	rc = lprocfs_seq_create(svc->srv_procroot, "req_history",
1103				0400, &req_history_fops, svc);
1104	if (rc)
1105		CWARN("Error adding the req_history file\n");
1106}
1107
1108void ptlrpc_lprocfs_register_obd(struct obd_device *obddev)
1109{
1110	ptlrpc_lprocfs_register(obddev->obd_proc_entry, NULL, "stats",
1111				&obddev->obd_svc_procroot,
1112				&obddev->obd_svc_stats);
1113}
1114EXPORT_SYMBOL(ptlrpc_lprocfs_register_obd);
1115
1116void ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request *req, long amount)
1117{
1118	struct lprocfs_stats *svc_stats;
1119	__u32 op = lustre_msg_get_opc(req->rq_reqmsg);
1120	int opc = opcode_offset(op);
1121
1122	svc_stats = req->rq_import->imp_obd->obd_svc_stats;
1123	if (svc_stats == NULL || opc <= 0)
1124		return;
1125	LASSERT(opc < LUSTRE_MAX_OPCODES);
1126	if (!(op == LDLM_ENQUEUE || op == MDS_REINT))
1127		lprocfs_counter_add(svc_stats, opc + EXTRA_MAX_OPCODES, amount);
1128}
1129
1130void ptlrpc_lprocfs_brw(struct ptlrpc_request *req, int bytes)
1131{
1132	struct lprocfs_stats *svc_stats;
1133	int idx;
1134
1135	if (!req->rq_import)
1136		return;
1137	svc_stats = req->rq_import->imp_obd->obd_svc_stats;
1138	if (!svc_stats)
1139		return;
1140	idx = lustre_msg_get_opc(req->rq_reqmsg);
1141	switch (idx) {
1142	case OST_READ:
1143		idx = BRW_READ_BYTES + PTLRPC_LAST_CNTR;
1144		break;
1145	case OST_WRITE:
1146		idx = BRW_WRITE_BYTES + PTLRPC_LAST_CNTR;
1147		break;
1148	default:
1149		LASSERTF(0, "unsupported opcode %u\n", idx);
1150		break;
1151	}
1152
1153	lprocfs_counter_add(svc_stats, idx, bytes);
1154}
1155
1156EXPORT_SYMBOL(ptlrpc_lprocfs_brw);
1157
1158void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc)
1159{
1160	if (svc->srv_procroot != NULL)
1161		lprocfs_remove(&svc->srv_procroot);
1162
1163	if (svc->srv_stats)
1164		lprocfs_free_stats(&svc->srv_stats);
1165}
1166
1167void ptlrpc_lprocfs_unregister_obd(struct obd_device *obd)
1168{
1169	if (obd->obd_svc_procroot)
1170		lprocfs_remove(&obd->obd_svc_procroot);
1171
1172	if (obd->obd_svc_stats)
1173		lprocfs_free_stats(&obd->obd_svc_stats);
1174}
1175EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd);
1176
1177
1178#define BUFLEN (UUID_MAX + 5)
1179
1180int lprocfs_wr_evict_client(struct file *file, const char *buffer,
1181			    size_t count, loff_t *off)
1182{
1183	struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
1184	char	      *kbuf;
1185	char	      *tmpbuf;
1186
1187	OBD_ALLOC(kbuf, BUFLEN);
1188	if (kbuf == NULL)
1189		return -ENOMEM;
1190
1191	/*
1192	 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
1193	 * bytes into kbuf, to ensure that the string is NUL-terminated.
1194	 * UUID_MAX should include a trailing NUL already.
1195	 */
1196	if (copy_from_user(kbuf, buffer,
1197			       min_t(unsigned long, BUFLEN - 1, count))) {
1198		count = -EFAULT;
1199		goto out;
1200	}
1201	tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
1202	/* Kludge code(deadlock situation): the lprocfs lock has been held
1203	 * since the client is evicted by writing client's
1204	 * uuid/nid to procfs "evict_client" entry. However,
1205	 * obd_export_evict_by_uuid() will call lprocfs_remove() to destroy
1206	 * the proc entries under the being destroyed export{}, so I have
1207	 * to drop the lock at first here.
1208	 * - jay, jxiong@clusterfs.com */
1209	class_incref(obd, __func__, current);
1210
1211	if (strncmp(tmpbuf, "nid:", 4) == 0)
1212		obd_export_evict_by_nid(obd, tmpbuf + 4);
1213	else if (strncmp(tmpbuf, "uuid:", 5) == 0)
1214		obd_export_evict_by_uuid(obd, tmpbuf + 5);
1215	else
1216		obd_export_evict_by_uuid(obd, tmpbuf);
1217
1218	class_decref(obd, __func__, current);
1219
1220out:
1221	OBD_FREE(kbuf, BUFLEN);
1222	return count;
1223}
1224EXPORT_SYMBOL(lprocfs_wr_evict_client);
1225
1226#undef BUFLEN
1227
1228int lprocfs_wr_ping(struct file *file, const char *buffer,
1229		    size_t count, loff_t *off)
1230{
1231	struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
1232	struct ptlrpc_request *req;
1233	int		    rc;
1234
1235	LPROCFS_CLIMP_CHECK(obd);
1236	req = ptlrpc_prep_ping(obd->u.cli.cl_import);
1237	LPROCFS_CLIMP_EXIT(obd);
1238	if (req == NULL)
1239		return -ENOMEM;
1240
1241	req->rq_send_state = LUSTRE_IMP_FULL;
1242
1243	rc = ptlrpc_queue_wait(req);
1244
1245	ptlrpc_req_finished(req);
1246	if (rc >= 0)
1247		return count;
1248	return rc;
1249}
1250EXPORT_SYMBOL(lprocfs_wr_ping);
1251
1252/* Write the connection UUID to this file to attempt to connect to that node.
1253 * The connection UUID is a node's primary NID. For example,
1254 * "echo connection=192.168.0.1@tcp0::instance > .../import".
1255 */
1256int lprocfs_wr_import(struct file *file, const char *buffer,
1257		      size_t count, loff_t *off)
1258{
1259	struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
1260	struct obd_import *imp = obd->u.cli.cl_import;
1261	char *kbuf = NULL;
1262	char *uuid;
1263	char *ptr;
1264	int do_reconn = 1;
1265	const char prefix[] = "connection=";
1266	const int prefix_len = sizeof(prefix) - 1;
1267
1268	if (count > PAGE_CACHE_SIZE - 1 || count <= prefix_len)
1269		return -EINVAL;
1270
1271	OBD_ALLOC(kbuf, count + 1);
1272	if (kbuf == NULL)
1273		return -ENOMEM;
1274
1275	if (copy_from_user(kbuf, buffer, count)) {
1276		count = -EFAULT;
1277		goto out;
1278	}
1279
1280	kbuf[count] = 0;
1281
1282	/* only support connection=uuid::instance now */
1283	if (strncmp(prefix, kbuf, prefix_len) != 0) {
1284		count = -EINVAL;
1285		goto out;
1286	}
1287
1288	uuid = kbuf + prefix_len;
1289	ptr = strstr(uuid, "::");
1290	if (ptr) {
1291		__u32 inst;
1292		char *endptr;
1293
1294		*ptr = 0;
1295		do_reconn = 0;
1296		ptr += strlen("::");
1297		inst = simple_strtol(ptr, &endptr, 10);
1298		if (*endptr) {
1299			CERROR("config: wrong instance # %s\n", ptr);
1300		} else if (inst != imp->imp_connect_data.ocd_instance) {
1301			CDEBUG(D_INFO, "IR: %s is connecting to an obsoleted "
1302			       "target(%u/%u), reconnecting...\n",
1303			       imp->imp_obd->obd_name,
1304			       imp->imp_connect_data.ocd_instance, inst);
1305			do_reconn = 1;
1306		} else {
1307			CDEBUG(D_INFO, "IR: %s has already been connecting to "
1308			       "new target(%u)\n",
1309			       imp->imp_obd->obd_name, inst);
1310		}
1311	}
1312
1313	if (do_reconn)
1314		ptlrpc_recover_import(imp, uuid, 1);
1315
1316out:
1317	OBD_FREE(kbuf, count + 1);
1318	return count;
1319}
1320EXPORT_SYMBOL(lprocfs_wr_import);
1321
1322int lprocfs_rd_pinger_recov(struct seq_file *m, void *n)
1323{
1324	struct obd_device *obd = m->private;
1325	struct obd_import *imp = obd->u.cli.cl_import;
1326	int rc;
1327
1328	LPROCFS_CLIMP_CHECK(obd);
1329	rc = seq_printf(m, "%d\n", !imp->imp_no_pinger_recover);
1330	LPROCFS_CLIMP_EXIT(obd);
1331
1332	return rc;
1333}
1334EXPORT_SYMBOL(lprocfs_rd_pinger_recov);
1335
1336int lprocfs_wr_pinger_recov(struct file *file, const char *buffer,
1337		      size_t count, loff_t *off)
1338{
1339	struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
1340	struct client_obd *cli = &obd->u.cli;
1341	struct obd_import *imp = cli->cl_import;
1342	int rc, val;
1343
1344	rc = lprocfs_write_helper(buffer, count, &val);
1345	if (rc < 0)
1346		return rc;
1347
1348	if (val != 0 && val != 1)
1349		return -ERANGE;
1350
1351	LPROCFS_CLIMP_CHECK(obd);
1352	spin_lock(&imp->imp_lock);
1353	imp->imp_no_pinger_recover = !val;
1354	spin_unlock(&imp->imp_lock);
1355	LPROCFS_CLIMP_EXIT(obd);
1356
1357	return count;
1358
1359}
1360EXPORT_SYMBOL(lprocfs_wr_pinger_recov);
1361
1362#endif /* CONFIG_PROC_FS */
1363