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 
48 static 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 },    /* 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 
139 static 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 
ll_opcode2str(__u32 opcode)159 const 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 
ll_eopcode2str(__u32 opcode)178 static 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)
ptlrpc_lprocfs_register(struct proc_dir_entry * root,char * dir,char * name,struct proc_dir_entry ** procroot_ret,struct lprocfs_stats ** stats_ret)185 static 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 
259 static int
ptlrpc_lprocfs_req_history_len_seq_show(struct seq_file * m,void * v)260 ptlrpc_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 }
273 LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_req_history_len);
274 
275 static int
ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file * m,void * n)276 ptlrpc_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 
290 static ssize_t
ptlrpc_lprocfs_req_history_max_seq_write(struct file * file,const char __user * buffer,size_t count,loff_t * off)291 ptlrpc_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 	/* This sanity check is more of an insanity check; we can still
308 	 * hose a kernel by allowing the request history to grow too
309 	 * far. */
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 }
325 LPROC_SEQ_FOPS(ptlrpc_lprocfs_req_history_max);
326 
327 static int
ptlrpc_lprocfs_threads_min_seq_show(struct seq_file * m,void * n)328 ptlrpc_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 
336 static ssize_t
ptlrpc_lprocfs_threads_min_seq_write(struct file * file,const char __user * buffer,size_t count,loff_t * off)337 ptlrpc_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 }
363 LPROC_SEQ_FOPS(ptlrpc_lprocfs_threads_min);
364 
365 static int
ptlrpc_lprocfs_threads_started_seq_show(struct seq_file * m,void * n)366 ptlrpc_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 }
379 LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_threads_started);
380 
381 static int
ptlrpc_lprocfs_threads_max_seq_show(struct seq_file * m,void * n)382 ptlrpc_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 
390 static ssize_t
ptlrpc_lprocfs_threads_max_seq_write(struct file * file,const char __user * buffer,size_t count,loff_t * off)391 ptlrpc_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 }
417 LPROC_SEQ_FOPS(ptlrpc_lprocfs_threads_max);
418 
419 /**
420  * \addtogoup nrs
421  * @{
422  */
423 extern struct nrs_core nrs_core;
424 
425 /**
426  * Translates \e ptlrpc_nrs_pol_state values to human-readable strings.
427  *
428  * \param[in] state The policy state
429  */
nrs_state2str(enum ptlrpc_nrs_pol_state state)430 static 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  * Obtains status information for \a policy.
450  *
451  * Information is copied in \a info.
452  *
453  * \param[in] policy The policy
454  * \param[out] info  Holds returned status information
455  */
nrs_policy_get_info_locked(struct ptlrpc_nrs_policy * policy,struct ptlrpc_nrs_pol_info * info)456 void 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 	 * XXX: These are accessed without holding
469 	 * ptlrpc_service_part::scp_req_lock.
470 	 */
471 	info->pi_req_queued  = policy->pol_req_queued;
472 	info->pi_req_started = policy->pol_req_started;
473 }
474 
475 /**
476  * Reads and prints policy status information for all policies of a PTLRPC
477  * service.
478  */
ptlrpc_lprocfs_nrs_seq_show(struct seq_file * m,void * n)479 static 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 	 * Serialize NRS core lprocfs operations with policy registration/
495 	 * unregistration.
496 	 */
497 	mutex_lock(&nrs_core.nrs_mutex);
498 
499 	/**
500 	 * Use the first service partition's regular NRS head in order to obtain
501 	 * the number of policies registered with NRS heads of this service. All
502 	 * service partitions will have the same number of policies.
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 	}
515 again:
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 			 * Copy values when handling the first service
530 			 * partition.
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 				 * For the rest of the service partitions
540 				 * sanity-check the values we get.
541 				 */
542 			} else {
543 				LASSERT(strncmp(infos[pol_idx].pi_name,
544 						tmp.pi_name,
545 						NRS_POL_NAME_MAX) == 0);
546 				/**
547 				 * Not asserting ptlrpc_nrs_pol_info::pi_state,
548 				 * because it may be different between
549 				 * instances of the same policy in different
550 				 * service partitions.
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 	 * Policy status information output is in YAML format.
566 	 * For example:
567 	 *
568 	 *	regular_requests:
569 	 *	  - name: fifo
570 	 *	    state: started
571 	 *	    fallback: yes
572 	 *	    queued: 0
573 	 *	    active: 0
574 	 *
575 	 *	  - name: crrn
576 	 *	    state: started
577 	 *	    fallback: no
578 	 *	    queued: 2015
579 	 *	    active: 384
580 	 *
581 	 *	high_priority_requests:
582 	 *	  - name: fifo
583 	 *	    state: started
584 	 *	    fallback: yes
585 	 *	    queued: 0
586 	 *	    active: 2
587 	 *
588 	 *	  - name: crrn
589 	 *	    state: stopped
590 	 *	    fallback: no
591 	 *	    queued: 0
592 	 *	    active: 0
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 		 * Redo the processing for the service's HP NRS heads' policies.
615 		 */
616 		hp = true;
617 		goto again;
618 	}
619 
620 out:
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  * The longest valid command string is the maximum policy name size, plus the
631  * length of the " reg" substring
632  */
633 #define LPROCFS_NRS_WR_MAX_CMD	(NRS_POL_NAME_MAX + sizeof(" reg") - 1)
634 
635 /**
636  * Starts and stops a given policy on a PTLRPC service.
637  *
638  * Commands consist of the policy name, followed by an optional [reg|hp] token;
639  * if the optional token is omitted, the operation is performed on both the
640  * regular and high-priority (if the service has one) NRS head.
641  */
ptlrpc_lprocfs_nrs_seq_write(struct file * file,const char __user * buffer,size_t count,loff_t * off)642 static 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 	 * strsep() modifies its argument, so keep a copy
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 	 * No [reg|hp] token has been specified
684 	 */
685 	if (cmd == NULL)
686 		goto default_queue;
687 
688 	/**
689 	 * The second token is either NULL, or an optional [reg|hp] string
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 
700 default_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 	 * Serialize NRS core lprocfs operations with policy registration/
710 	 * unregistration.
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);
718 out:
719 	if (cmd_copy)
720 		OBD_FREE(cmd_copy, LPROCFS_NRS_WR_MAX_CMD);
721 
722 	return rc < 0 ? rc : count;
723 }
724 LPROC_SEQ_FOPS(ptlrpc_lprocfs_nrs);
725 
726 /** @} nrs */
727 
728 struct ptlrpc_srh_iterator {
729 	int			srhi_idx;
730 	__u64			srhi_seq;
731 	struct ptlrpc_request	*srhi_req;
732 };
733 
734 static int
ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part * svcpt,struct ptlrpc_srh_iterator * srhi,__u64 seq)735 ptlrpc_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 		/* If srhi_req was set previously, hasn't been culled and
746 		 * we're searching for a seq on or after it (i.e. more
747 		 * recent), search from it onwards.
748 		 * Since the service history is LRU (i.e. culled reqs will
749 		 * be near the head), we shouldn't have to do long
750 		 * re-scans */
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 		/* search from start */
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  * ptlrpc history sequence is used as "position" of seq_file, in some case,
781  * seq_read() will increase "position" to indicate reading the next
782  * element, however, low bits of history sequence are reserved for CPT id
783  * (check the details from comments before ptlrpc_req_add_history), which
784  * means seq_read() might change CPT id of history sequence and never
785  * finish reading of requests on a CPT. To make it work, we have to shift
786  * CPT id to high bits and timestamp to low bits, so seq_read() will only
787  * increase timestamp which can correctly indicate the next position.
788  */
789 
790 /* convert seq_file pos to cpt */
791 #define PTLRPC_REQ_POS2CPT(svc, pos)			\
792 	((svc)->srv_cpt_bits == 0 ? 0 :			\
793 	 (__u64)(pos) >> (64 - (svc)->srv_cpt_bits))
794 
795 /* make up seq_file pos from cpt */
796 #define PTLRPC_REQ_CPT2POS(svc, cpt)			\
797 	((svc)->srv_cpt_bits == 0 ? 0 :			\
798 	 (cpt) << (64 - (svc)->srv_cpt_bits))
799 
800 /* convert sequence to position */
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 /* convert position to sequence */
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 
812 static void *
ptlrpc_lprocfs_svc_req_history_start(struct seq_file * s,loff_t * pos)813 ptlrpc_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)) { /* can't support */
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) /* skip */
839 			continue;
840 		if (i > cpt) /* make up the lowest position for this 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 
858 static void
ptlrpc_lprocfs_svc_req_history_stop(struct seq_file * s,void * iter)859 ptlrpc_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 
867 static void *
ptlrpc_lprocfs_svc_req_history_next(struct seq_file * s,void * iter,loff_t * pos)868 ptlrpc_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) { /* reset iterator for a new CPT */
882 			srhi->srhi_req = NULL;
883 			seq = srhi->srhi_seq = 0;
884 		} else { /* the next sequence */
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 /* common ost/mdt so_req_printer */
target_print_req(void * seq_file,struct ptlrpc_request * req)903 void target_print_req(void *seq_file, struct ptlrpc_request *req)
904 {
905 	/* Called holding srv_lock with irqs disabled.
906 	 * Print specific req contents and a newline.
907 	 * CAVEAT EMPTOR: check request message length before printing!!!
908 	 * You might have received any old crap so you must be just as
909 	 * careful here as the service's request parser!!! */
910 	struct seq_file *sf = seq_file;
911 
912 	switch (req->rq_phase) {
913 	case RQ_PHASE_NEW:
914 		/* still awaiting a service thread's attention, or rejected
915 		 * because the generic request message didn't unpack */
916 		seq_printf(sf, "<not swabbed>\n");
917 		break;
918 	case RQ_PHASE_INTERPRET:
919 		/* being handled, so basic msg swabbed, and opc is valid
920 		 * but racing with mds_handle() */
921 	case RQ_PHASE_COMPLETE:
922 		/* been handled by mds_handle() reply state possibly still
923 		 * volatile */
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 }
930 EXPORT_SYMBOL(target_print_req);
931 
ptlrpc_lprocfs_svc_req_history_show(struct seq_file * s,void * iter)932 static 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 		/* Print common req fields.
952 		 * CAVEAT EMPTOR: we're racing with the service handler
953 		 * here.  The request could contain any old crap, so you
954 		 * must be just as careful as the service's request
955 		 * parser. Currently I only print stuff here I know is OK
956 		 * to look at coz it was set up in request_in_callback()!!! */
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 
974 static int
ptlrpc_lprocfs_svc_req_history_open(struct inode * inode,struct file * file)975 ptlrpc_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 /* See also lprocfs_rd_timeouts */
ptlrpc_lprocfs_timeouts_seq_show(struct seq_file * m,void * n)996 static 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 }
1027 LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_timeouts);
1028 
ptlrpc_lprocfs_hp_ratio_seq_show(struct seq_file * m,void * v)1029 static 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 
ptlrpc_lprocfs_hp_ratio_seq_write(struct file * file,const char __user * buffer,size_t count,loff_t * off)1036 static 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 }
1058 LPROC_SEQ_FOPS(ptlrpc_lprocfs_hp_ratio);
1059 
ptlrpc_lprocfs_register_service(struct proc_dir_entry * entry,struct ptlrpc_service * svc)1060 void 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 
ptlrpc_lprocfs_register_obd(struct obd_device * obddev)1115 void 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 }
1121 EXPORT_SYMBOL(ptlrpc_lprocfs_register_obd);
1122 
ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request * req,long amount)1123 void 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 
ptlrpc_lprocfs_brw(struct ptlrpc_request * req,int bytes)1137 void 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 
1163 EXPORT_SYMBOL(ptlrpc_lprocfs_brw);
1164 
ptlrpc_lprocfs_unregister_service(struct ptlrpc_service * svc)1165 void 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 
ptlrpc_lprocfs_unregister_obd(struct obd_device * obd)1174 void 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 }
1182 EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd);
1183 
1184 
1185 #define BUFLEN (UUID_MAX + 5)
1186 
lprocfs_wr_evict_client(struct file * file,const char __user * buffer,size_t count,loff_t * off)1187 int 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 	 * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
1200 	 * bytes into kbuf, to ensure that the string is NUL-terminated.
1201 	 * UUID_MAX should include a trailing NUL already.
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 	/* Kludge code(deadlock situation): the lprocfs lock has been held
1210 	 * since the client is evicted by writing client's
1211 	 * uuid/nid to procfs "evict_client" entry. However,
1212 	 * obd_export_evict_by_uuid() will call lprocfs_remove() to destroy
1213 	 * the proc entries under the being destroyed export{}, so I have
1214 	 * to drop the lock at first here.
1215 	 * - jay, jxiong@clusterfs.com */
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 
1227 out:
1228 	OBD_FREE(kbuf, BUFLEN);
1229 	return count;
1230 }
1231 EXPORT_SYMBOL(lprocfs_wr_evict_client);
1232 
1233 #undef BUFLEN
1234 
lprocfs_wr_ping(struct file * file,const char __user * buffer,size_t count,loff_t * off)1235 int 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 }
1257 EXPORT_SYMBOL(lprocfs_wr_ping);
1258 
1259 /* Write the connection UUID to this file to attempt to connect to that node.
1260  * The connection UUID is a node's primary NID. For example,
1261  * "echo connection=192.168.0.1@tcp0::instance > .../import".
1262  */
lprocfs_wr_import(struct file * file,const char __user * buffer,size_t count,loff_t * off)1263 int 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 	/* only support connection=uuid::instance now */
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 
1321 out:
1322 	OBD_FREE(kbuf, count + 1);
1323 	return count;
1324 }
1325 EXPORT_SYMBOL(lprocfs_wr_import);
1326 
lprocfs_rd_pinger_recov(struct seq_file * m,void * n)1327 int 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 }
1338 EXPORT_SYMBOL(lprocfs_rd_pinger_recov);
1339 
lprocfs_wr_pinger_recov(struct file * file,const char __user * buffer,size_t count,loff_t * off)1340 int 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 }
1364 EXPORT_SYMBOL(lprocfs_wr_pinger_recov);
1365 
1366 #endif /* CONFIG_PROC_FS */
1367