• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * lustre/obdclass/lprocfs_status.c
37  *
38  * Author: Hariharan Thantry <thantry@users.sourceforge.net>
39  */
40 
41 #define DEBUG_SUBSYSTEM S_CLASS
42 
43 #include "../include/obd_class.h"
44 #include "../include/lprocfs_status.h"
45 #include "../include/lustre/lustre_idl.h"
46 #include <linux/seq_file.h>
47 #include <linux/ctype.h>
48 
49 static const char * const obd_connect_names[] = {
50 	"read_only",
51 	"lov_index",
52 	"unused",
53 	"write_grant",
54 	"server_lock",
55 	"version",
56 	"request_portal",
57 	"acl",
58 	"xattr",
59 	"create_on_write",
60 	"truncate_lock",
61 	"initial_transno",
62 	"inode_bit_locks",
63 	"join_file(obsolete)",
64 	"getattr_by_fid",
65 	"no_oh_for_devices",
66 	"remote_client",
67 	"remote_client_by_force",
68 	"max_byte_per_rpc",
69 	"64bit_qdata",
70 	"mds_capability",
71 	"oss_capability",
72 	"early_lock_cancel",
73 	"som",
74 	"adaptive_timeouts",
75 	"lru_resize",
76 	"mds_mds_connection",
77 	"real_conn",
78 	"change_qunit_size",
79 	"alt_checksum_algorithm",
80 	"fid_is_enabled",
81 	"version_recovery",
82 	"pools",
83 	"grant_shrink",
84 	"skip_orphan",
85 	"large_ea",
86 	"full20",
87 	"layout_lock",
88 	"64bithash",
89 	"object_max_bytes",
90 	"imp_recov",
91 	"jobstats",
92 	"umask",
93 	"einprogress",
94 	"grant_param",
95 	"flock_owner",
96 	"lvb_type",
97 	"nanoseconds_times",
98 	"lightweight_conn",
99 	"short_io",
100 	"pingless",
101 	"flock_deadlock",
102 	"disp_stripe",
103 	"unknown",
104 	NULL
105 };
106 
obd_connect_flags2str(char * page,int count,__u64 flags,char * sep)107 int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
108 {
109 	__u64 mask = 1;
110 	int i, ret = 0;
111 
112 	for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
113 		if (flags & mask)
114 			ret += snprintf(page + ret, count - ret, "%s%s",
115 					ret ? sep : "", obd_connect_names[i]);
116 	}
117 	if (flags & ~(mask - 1))
118 		ret += snprintf(page + ret, count - ret,
119 				"%sunknown flags %#llx",
120 				ret ? sep : "", flags & ~(mask - 1));
121 	return ret;
122 }
123 EXPORT_SYMBOL(obd_connect_flags2str);
124 
lprocfs_read_frac_helper(char * buffer,unsigned long count,long val,int mult)125 int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val,
126 			     int mult)
127 {
128 	long decimal_val, frac_val;
129 	int prtn;
130 
131 	if (count < 10)
132 		return -EINVAL;
133 
134 	decimal_val = val / mult;
135 	prtn = snprintf(buffer, count, "%ld", decimal_val);
136 	frac_val = val % mult;
137 
138 	if (prtn < (count - 4) && frac_val > 0) {
139 		long temp_frac;
140 		int i, temp_mult = 1, frac_bits = 0;
141 
142 		temp_frac = frac_val * 10;
143 		buffer[prtn++] = '.';
144 		while (frac_bits < 2 && (temp_frac / mult) < 1) {
145 			/* only reserved 2 bits fraction */
146 			buffer[prtn++] = '0';
147 			temp_frac *= 10;
148 			frac_bits++;
149 		}
150 		/*
151 		 * Need to think these cases :
152 		 *      1. #echo x.00 > /proc/xxx       output result : x
153 		 *      2. #echo x.0x > /proc/xxx       output result : x.0x
154 		 *      3. #echo x.x0 > /proc/xxx       output result : x.x
155 		 *      4. #echo x.xx > /proc/xxx       output result : x.xx
156 		 *      Only reserved 2 bits fraction.
157 		 */
158 		for (i = 0; i < (5 - prtn); i++)
159 			temp_mult *= 10;
160 
161 		frac_bits = min((int)count - prtn, 3 - frac_bits);
162 		prtn += snprintf(buffer + prtn, frac_bits, "%ld",
163 				 frac_val * temp_mult / mult);
164 
165 		prtn--;
166 		while (buffer[prtn] < '1' || buffer[prtn] > '9') {
167 			prtn--;
168 			if (buffer[prtn] == '.') {
169 				prtn--;
170 				break;
171 			}
172 		}
173 		prtn++;
174 	}
175 	buffer[prtn++] = '\n';
176 	return prtn;
177 }
178 EXPORT_SYMBOL(lprocfs_read_frac_helper);
179 
lprocfs_write_frac_helper(const char __user * buffer,unsigned long count,int * val,int mult)180 int lprocfs_write_frac_helper(const char __user *buffer, unsigned long count,
181 			      int *val, int mult)
182 {
183 	char kernbuf[20], *end, *pbuf;
184 
185 	if (count > (sizeof(kernbuf) - 1))
186 		return -EINVAL;
187 
188 	if (copy_from_user(kernbuf, buffer, count))
189 		return -EFAULT;
190 
191 	kernbuf[count] = '\0';
192 	pbuf = kernbuf;
193 	if (*pbuf == '-') {
194 		mult = -mult;
195 		pbuf++;
196 	}
197 
198 	*val = (int)simple_strtoul(pbuf, &end, 10) * mult;
199 	if (pbuf == end)
200 		return -EINVAL;
201 
202 	if (end != NULL && *end == '.') {
203 		int temp_val, pow = 1;
204 		int i;
205 
206 		pbuf = end + 1;
207 		if (strlen(pbuf) > 5)
208 			pbuf[5] = '\0'; /*only allow 5bits fractional*/
209 
210 		temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult;
211 
212 		if (pbuf < end) {
213 			for (i = 0; i < (end - pbuf); i++)
214 				pow *= 10;
215 
216 			*val += temp_val / pow;
217 		}
218 	}
219 	return 0;
220 }
221 EXPORT_SYMBOL(lprocfs_write_frac_helper);
222 
223 static int lprocfs_no_percpu_stats;
224 module_param(lprocfs_no_percpu_stats, int, 0644);
225 MODULE_PARM_DESC(lprocfs_no_percpu_stats, "Do not alloc percpu data for lprocfs stats");
226 
227 #define MAX_STRING_SIZE 128
228 
lprocfs_single_release(struct inode * inode,struct file * file)229 int lprocfs_single_release(struct inode *inode, struct file *file)
230 {
231 	return single_release(inode, file);
232 }
233 EXPORT_SYMBOL(lprocfs_single_release);
234 
lprocfs_seq_release(struct inode * inode,struct file * file)235 int lprocfs_seq_release(struct inode *inode, struct file *file)
236 {
237 	return seq_release(inode, file);
238 }
239 EXPORT_SYMBOL(lprocfs_seq_release);
240 
241 /* lprocfs API calls */
242 
ldebugfs_add_simple(struct dentry * root,char * name,void * data,struct file_operations * fops)243 struct dentry *ldebugfs_add_simple(struct dentry *root,
244 				   char *name, void *data,
245 				   struct file_operations *fops)
246 {
247 	struct dentry *entry;
248 	umode_t mode = 0;
249 
250 	if (root == NULL || name == NULL || fops == NULL)
251 		return ERR_PTR(-EINVAL);
252 
253 	if (fops->read)
254 		mode = 0444;
255 	if (fops->write)
256 		mode |= 0200;
257 	entry = debugfs_create_file(name, mode, root, data, fops);
258 	if (IS_ERR_OR_NULL(entry)) {
259 		CERROR("LprocFS: No memory to create <debugfs> entry %s", name);
260 		return entry ?: ERR_PTR(-ENOMEM);
261 	}
262 	return entry;
263 }
264 EXPORT_SYMBOL(ldebugfs_add_simple);
265 
266 static struct file_operations lprocfs_generic_fops = { };
267 
ldebugfs_add_vars(struct dentry * parent,struct lprocfs_vars * list,void * data)268 int ldebugfs_add_vars(struct dentry *parent,
269 		      struct lprocfs_vars *list,
270 		      void *data)
271 {
272 	if (IS_ERR_OR_NULL(parent) || IS_ERR_OR_NULL(list))
273 		return -EINVAL;
274 
275 	while (list->name != NULL) {
276 		struct dentry *entry;
277 		umode_t mode = 0;
278 
279 		if (list->proc_mode != 0000) {
280 			mode = list->proc_mode;
281 		} else if (list->fops) {
282 			if (list->fops->read)
283 				mode = 0444;
284 			if (list->fops->write)
285 				mode |= 0200;
286 		}
287 		entry = debugfs_create_file(list->name, mode, parent,
288 					    list->data ?: data,
289 					    list->fops ?: &lprocfs_generic_fops
290 					   );
291 		if (IS_ERR_OR_NULL(entry))
292 			return entry ? PTR_ERR(entry) : -ENOMEM;
293 		list++;
294 	}
295 	return 0;
296 }
297 EXPORT_SYMBOL(ldebugfs_add_vars);
298 
ldebugfs_remove(struct dentry ** entryp)299 void ldebugfs_remove(struct dentry **entryp)
300 {
301 	debugfs_remove_recursive(*entryp);
302 	*entryp = NULL;
303 }
304 EXPORT_SYMBOL(ldebugfs_remove);
305 
ldebugfs_register(const char * name,struct dentry * parent,struct lprocfs_vars * list,void * data)306 struct dentry *ldebugfs_register(const char *name,
307 				 struct dentry *parent,
308 				 struct lprocfs_vars *list, void *data)
309 {
310 	struct dentry *entry;
311 
312 	entry = debugfs_create_dir(name, parent);
313 	if (IS_ERR_OR_NULL(entry)) {
314 		entry = entry ?: ERR_PTR(-ENOMEM);
315 		goto out;
316 	}
317 
318 	if (!IS_ERR_OR_NULL(list)) {
319 		int rc;
320 
321 		rc = ldebugfs_add_vars(entry, list, data);
322 		if (rc != 0) {
323 			debugfs_remove(entry);
324 			entry = ERR_PTR(rc);
325 		}
326 	}
327 out:
328 	return entry;
329 }
330 EXPORT_SYMBOL(ldebugfs_register);
331 
332 /* Generic callbacks */
lprocfs_rd_uint(struct seq_file * m,void * data)333 int lprocfs_rd_uint(struct seq_file *m, void *data)
334 {
335 	seq_printf(m, "%u\n", *(unsigned int *)data);
336 	return 0;
337 }
338 EXPORT_SYMBOL(lprocfs_rd_uint);
339 
lprocfs_wr_uint(struct file * file,const char __user * buffer,unsigned long count,void * data)340 int lprocfs_wr_uint(struct file *file, const char __user *buffer,
341 		    unsigned long count, void *data)
342 {
343 	unsigned *p = data;
344 	char dummy[MAX_STRING_SIZE + 1], *end;
345 	unsigned long tmp;
346 
347 	dummy[MAX_STRING_SIZE] = '\0';
348 	if (copy_from_user(dummy, buffer, MAX_STRING_SIZE))
349 		return -EFAULT;
350 
351 	tmp = simple_strtoul(dummy, &end, 0);
352 	if (dummy == end)
353 		return -EINVAL;
354 
355 	*p = (unsigned int)tmp;
356 	return count;
357 }
358 EXPORT_SYMBOL(lprocfs_wr_uint);
359 
uuid_show(struct kobject * kobj,struct attribute * attr,char * buf)360 static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
361 			 char *buf)
362 {
363 	struct obd_device *obd = container_of(kobj, struct obd_device,
364 					      obd_kobj);
365 
366 	return sprintf(buf, "%s\n", obd->obd_uuid.uuid);
367 }
368 LUSTRE_RO_ATTR(uuid);
369 
blocksize_show(struct kobject * kobj,struct attribute * attr,char * buf)370 static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
371 			      char *buf)
372 {
373 	struct obd_device *obd = container_of(kobj, struct obd_device,
374 					      obd_kobj);
375 	struct obd_statfs  osfs;
376 	int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
377 			    cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
378 			    OBD_STATFS_NODELAY);
379 	if (!rc)
380 		return sprintf(buf, "%u\n", osfs.os_bsize);
381 
382 	return rc;
383 }
384 LUSTRE_RO_ATTR(blocksize);
385 
kbytestotal_show(struct kobject * kobj,struct attribute * attr,char * buf)386 static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
387 				char *buf)
388 {
389 	struct obd_device *obd = container_of(kobj, struct obd_device,
390 					      obd_kobj);
391 	struct obd_statfs  osfs;
392 	int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
393 			    cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
394 			    OBD_STATFS_NODELAY);
395 	if (!rc) {
396 		__u32 blk_size = osfs.os_bsize >> 10;
397 		__u64 result = osfs.os_blocks;
398 
399 		while (blk_size >>= 1)
400 			result <<= 1;
401 
402 		return sprintf(buf, "%llu\n", result);
403 	}
404 
405 	return rc;
406 }
407 LUSTRE_RO_ATTR(kbytestotal);
408 
kbytesfree_show(struct kobject * kobj,struct attribute * attr,char * buf)409 static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
410 			       char *buf)
411 {
412 	struct obd_device *obd = container_of(kobj, struct obd_device,
413 					      obd_kobj);
414 	struct obd_statfs  osfs;
415 	int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
416 			    cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
417 			    OBD_STATFS_NODELAY);
418 	if (!rc) {
419 		__u32 blk_size = osfs.os_bsize >> 10;
420 		__u64 result = osfs.os_bfree;
421 
422 		while (blk_size >>= 1)
423 			result <<= 1;
424 
425 		return sprintf(buf, "%llu\n", result);
426 	}
427 
428 	return rc;
429 }
430 LUSTRE_RO_ATTR(kbytesfree);
431 
kbytesavail_show(struct kobject * kobj,struct attribute * attr,char * buf)432 static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
433 				char *buf)
434 {
435 	struct obd_device *obd = container_of(kobj, struct obd_device,
436 					      obd_kobj);
437 	struct obd_statfs  osfs;
438 	int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
439 			    cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
440 			    OBD_STATFS_NODELAY);
441 	if (!rc) {
442 		__u32 blk_size = osfs.os_bsize >> 10;
443 		__u64 result = osfs.os_bavail;
444 
445 		while (blk_size >>= 1)
446 			result <<= 1;
447 
448 		return sprintf(buf, "%llu\n", result);
449 	}
450 
451 	return rc;
452 }
453 LUSTRE_RO_ATTR(kbytesavail);
454 
filestotal_show(struct kobject * kobj,struct attribute * attr,char * buf)455 static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
456 			       char *buf)
457 {
458 	struct obd_device *obd = container_of(kobj, struct obd_device,
459 					      obd_kobj);
460 	struct obd_statfs  osfs;
461 	int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
462 			    cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
463 			    OBD_STATFS_NODELAY);
464 	if (!rc)
465 		return sprintf(buf, "%llu\n", osfs.os_files);
466 
467 	return rc;
468 }
469 LUSTRE_RO_ATTR(filestotal);
470 
filesfree_show(struct kobject * kobj,struct attribute * attr,char * buf)471 static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
472 			      char *buf)
473 {
474 	struct obd_device *obd = container_of(kobj, struct obd_device,
475 					      obd_kobj);
476 	struct obd_statfs  osfs;
477 	int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
478 			    cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
479 			    OBD_STATFS_NODELAY);
480 	if (!rc)
481 		return sprintf(buf, "%llu\n", osfs.os_ffree);
482 
483 	return rc;
484 }
485 LUSTRE_RO_ATTR(filesfree);
486 
lprocfs_rd_server_uuid(struct seq_file * m,void * data)487 int lprocfs_rd_server_uuid(struct seq_file *m, void *data)
488 {
489 	struct obd_device *obd = data;
490 	struct obd_import *imp;
491 	char *imp_state_name = NULL;
492 	int rc;
493 
494 	LASSERT(obd != NULL);
495 	rc = lprocfs_climp_check(obd);
496 	if (rc)
497 		return rc;
498 
499 	imp = obd->u.cli.cl_import;
500 	imp_state_name = ptlrpc_import_state_name(imp->imp_state);
501 	seq_printf(m, "%s\t%s%s\n",
502 		   obd2cli_tgt(obd), imp_state_name,
503 		   imp->imp_deactive ? "\tDEACTIVATED" : "");
504 
505 	LPROCFS_CLIMP_EXIT(obd);
506 
507 	return 0;
508 }
509 EXPORT_SYMBOL(lprocfs_rd_server_uuid);
510 
lprocfs_rd_conn_uuid(struct seq_file * m,void * data)511 int lprocfs_rd_conn_uuid(struct seq_file *m, void *data)
512 {
513 	struct obd_device *obd = data;
514 	struct ptlrpc_connection *conn;
515 	int rc;
516 
517 	LASSERT(obd != NULL);
518 
519 	rc = lprocfs_climp_check(obd);
520 	if (rc)
521 		return rc;
522 
523 	conn = obd->u.cli.cl_import->imp_connection;
524 	if (conn && obd->u.cli.cl_import)
525 		seq_printf(m, "%s\n", conn->c_remote_uuid.uuid);
526 	else
527 		seq_puts(m, "<none>\n");
528 
529 	LPROCFS_CLIMP_EXIT(obd);
530 
531 	return 0;
532 }
533 EXPORT_SYMBOL(lprocfs_rd_conn_uuid);
534 
535 /** add up per-cpu counters */
lprocfs_stats_collect(struct lprocfs_stats * stats,int idx,struct lprocfs_counter * cnt)536 void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
537 			   struct lprocfs_counter *cnt)
538 {
539 	unsigned int			num_entry;
540 	struct lprocfs_counter		*percpu_cntr;
541 	int				i;
542 	unsigned long			flags = 0;
543 
544 	memset(cnt, 0, sizeof(*cnt));
545 
546 	if (stats == NULL) {
547 		/* set count to 1 to avoid divide-by-zero errs in callers */
548 		cnt->lc_count = 1;
549 		return;
550 	}
551 
552 	cnt->lc_min = LC_MIN_INIT;
553 
554 	num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
555 
556 	for (i = 0; i < num_entry; i++) {
557 		if (stats->ls_percpu[i] == NULL)
558 			continue;
559 		percpu_cntr = lprocfs_stats_counter_get(stats, i, idx);
560 
561 		cnt->lc_count += percpu_cntr->lc_count;
562 		cnt->lc_sum += percpu_cntr->lc_sum;
563 		if (percpu_cntr->lc_min < cnt->lc_min)
564 			cnt->lc_min = percpu_cntr->lc_min;
565 		if (percpu_cntr->lc_max > cnt->lc_max)
566 			cnt->lc_max = percpu_cntr->lc_max;
567 		cnt->lc_sumsquare += percpu_cntr->lc_sumsquare;
568 	}
569 
570 	lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
571 }
572 EXPORT_SYMBOL(lprocfs_stats_collect);
573 
574 /**
575  * Append a space separated list of current set flags to str.
576  */
577 #define flag2str(flag, first)						\
578 	do {								\
579 		if (imp->imp_##flag)					\
580 		     seq_printf(m, "%s" #flag, first ? "" : ", ");	\
581 	} while (0)
obd_import_flags2str(struct obd_import * imp,struct seq_file * m)582 static int obd_import_flags2str(struct obd_import *imp, struct seq_file *m)
583 {
584 	bool first = true;
585 
586 	if (imp->imp_obd->obd_no_recov) {
587 		seq_printf(m, "no_recov");
588 		first = false;
589 	}
590 
591 	flag2str(invalid, first);
592 	first = false;
593 	flag2str(deactive, first);
594 	flag2str(replayable, first);
595 	flag2str(pingable, first);
596 	return 0;
597 }
598 
599 #undef flags2str
600 
obd_connect_seq_flags2str(struct seq_file * m,__u64 flags,char * sep)601 static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, char *sep)
602 {
603 	__u64 mask = 1;
604 	int i;
605 	bool first = true;
606 
607 	for (i = 0; obd_connect_names[i] != NULL; i++, mask <<= 1) {
608 		if (flags & mask) {
609 			seq_printf(m, "%s%s",
610 					first ? sep : "", obd_connect_names[i]);
611 			first = false;
612 		}
613 	}
614 	if (flags & ~(mask - 1))
615 		seq_printf(m, "%sunknown flags %#llx",
616 				first ? sep : "", flags & ~(mask - 1));
617 }
618 
lprocfs_rd_import(struct seq_file * m,void * data)619 int lprocfs_rd_import(struct seq_file *m, void *data)
620 {
621 	char				nidstr[LNET_NIDSTR_SIZE];
622 	struct lprocfs_counter		ret;
623 	struct lprocfs_counter_header	*header;
624 	struct obd_device		*obd	= data;
625 	struct obd_import		*imp;
626 	struct obd_import_conn		*conn;
627 	int				j;
628 	int				k;
629 	int				rw	= 0;
630 	int				rc;
631 
632 	LASSERT(obd != NULL);
633 	rc = lprocfs_climp_check(obd);
634 	if (rc)
635 		return rc;
636 
637 	imp = obd->u.cli.cl_import;
638 
639 	seq_printf(m,
640 		     "import:\n"
641 		     "    name: %s\n"
642 		     "    target: %s\n"
643 		     "    state: %s\n"
644 		     "    instance: %u\n"
645 		     "    connect_flags: [",
646 		     obd->obd_name,
647 		     obd2cli_tgt(obd),
648 		     ptlrpc_import_state_name(imp->imp_state),
649 		     imp->imp_connect_data.ocd_instance);
650 	obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags, ", ");
651 	seq_printf(m,
652 		      "]\n"
653 		      "    import_flags: [");
654 	obd_import_flags2str(imp, m);
655 
656 	seq_printf(m,
657 		      "]\n"
658 		      "    connection:\n"
659 		      "       failover_nids: [");
660 	spin_lock(&imp->imp_lock);
661 	j = 0;
662 	list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
663 		libcfs_nid2str_r(conn->oic_conn->c_peer.nid,
664 				 nidstr, sizeof(nidstr));
665 		seq_printf(m, "%s%s", j ? ", " : "", nidstr);
666 		j++;
667 	}
668 	libcfs_nid2str_r(imp->imp_connection->c_peer.nid,
669 			 nidstr, sizeof(nidstr));
670 	seq_printf(m,
671 		      "]\n"
672 		      "       current_connection: %s\n"
673 		      "       connection_attempts: %u\n"
674 		      "       generation: %u\n"
675 		      "       in-progress_invalidations: %u\n",
676 		      imp->imp_connection == NULL ? "<none>" : nidstr,
677 		      imp->imp_conn_cnt,
678 		      imp->imp_generation,
679 		      atomic_read(&imp->imp_inval_count));
680 	spin_unlock(&imp->imp_lock);
681 
682 	if (obd->obd_svc_stats == NULL)
683 		goto out_climp;
684 
685 	header = &obd->obd_svc_stats->ls_cnt_header[PTLRPC_REQWAIT_CNTR];
686 	lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret);
687 	if (ret.lc_count != 0) {
688 		/* first argument to do_div MUST be __u64 */
689 		__u64 sum = ret.lc_sum;
690 
691 		do_div(sum, ret.lc_count);
692 		ret.lc_sum = sum;
693 	} else
694 		ret.lc_sum = 0;
695 	seq_printf(m,
696 		      "    rpcs:\n"
697 		      "       inflight: %u\n"
698 		      "       unregistering: %u\n"
699 		      "       timeouts: %u\n"
700 		      "       avg_waittime: %llu %s\n",
701 		      atomic_read(&imp->imp_inflight),
702 		      atomic_read(&imp->imp_unregistering),
703 		      atomic_read(&imp->imp_timeouts),
704 		      ret.lc_sum, header->lc_units);
705 
706 	k = 0;
707 	for (j = 0; j < IMP_AT_MAX_PORTALS; j++) {
708 		if (imp->imp_at.iat_portal[j] == 0)
709 			break;
710 		k = max_t(unsigned int, k,
711 			  at_get(&imp->imp_at.iat_service_estimate[j]));
712 	}
713 	seq_printf(m,
714 		      "    service_estimates:\n"
715 		      "       services: %u sec\n"
716 		      "       network: %u sec\n",
717 		      k,
718 		      at_get(&imp->imp_at.iat_net_latency));
719 
720 	seq_printf(m,
721 		      "    transactions:\n"
722 		      "       last_replay: %llu\n"
723 		      "       peer_committed: %llu\n"
724 		      "       last_checked: %llu\n",
725 		      imp->imp_last_replay_transno,
726 		      imp->imp_peer_committed_transno,
727 		      imp->imp_last_transno_checked);
728 
729 	/* avg data rates */
730 	for (rw = 0; rw <= 1; rw++) {
731 		lprocfs_stats_collect(obd->obd_svc_stats,
732 				      PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw,
733 				      &ret);
734 		if (ret.lc_sum > 0 && ret.lc_count > 0) {
735 			/* first argument to do_div MUST be __u64 */
736 			__u64 sum = ret.lc_sum;
737 
738 			do_div(sum, ret.lc_count);
739 			ret.lc_sum = sum;
740 			seq_printf(m,
741 				      "    %s_data_averages:\n"
742 				      "       bytes_per_rpc: %llu\n",
743 				      rw ? "write" : "read",
744 				      ret.lc_sum);
745 		}
746 		k = (int)ret.lc_sum;
747 		j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES;
748 		header = &obd->obd_svc_stats->ls_cnt_header[j];
749 		lprocfs_stats_collect(obd->obd_svc_stats, j, &ret);
750 		if (ret.lc_sum > 0 && ret.lc_count != 0) {
751 			/* first argument to do_div MUST be __u64 */
752 			__u64 sum = ret.lc_sum;
753 
754 			do_div(sum, ret.lc_count);
755 			ret.lc_sum = sum;
756 			seq_printf(m,
757 				      "       %s_per_rpc: %llu\n",
758 				      header->lc_units, ret.lc_sum);
759 			j = (int)ret.lc_sum;
760 			if (j > 0)
761 				seq_printf(m,
762 					      "       MB_per_sec: %u.%.02u\n",
763 					      k / j, (100 * k / j) % 100);
764 		}
765 	}
766 
767 out_climp:
768 	LPROCFS_CLIMP_EXIT(obd);
769 	return 0;
770 }
771 EXPORT_SYMBOL(lprocfs_rd_import);
772 
lprocfs_rd_state(struct seq_file * m,void * data)773 int lprocfs_rd_state(struct seq_file *m, void *data)
774 {
775 	struct obd_device *obd = data;
776 	struct obd_import *imp;
777 	int j, k, rc;
778 
779 	LASSERT(obd != NULL);
780 	rc = lprocfs_climp_check(obd);
781 	if (rc)
782 		return rc;
783 
784 	imp = obd->u.cli.cl_import;
785 
786 	seq_printf(m, "current_state: %s\n",
787 		     ptlrpc_import_state_name(imp->imp_state));
788 	seq_printf(m, "state_history:\n");
789 	k = imp->imp_state_hist_idx;
790 	for (j = 0; j < IMP_STATE_HIST_LEN; j++) {
791 		struct import_state_hist *ish =
792 			&imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN];
793 		if (ish->ish_state == 0)
794 			continue;
795 		seq_printf(m, " - [%lld, %s]\n", (s64)ish->ish_time,
796 			   ptlrpc_import_state_name(ish->ish_state));
797 	}
798 
799 	LPROCFS_CLIMP_EXIT(obd);
800 	return 0;
801 }
802 EXPORT_SYMBOL(lprocfs_rd_state);
803 
lprocfs_at_hist_helper(struct seq_file * m,struct adaptive_timeout * at)804 int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at)
805 {
806 	int i;
807 
808 	for (i = 0; i < AT_BINS; i++)
809 		seq_printf(m, "%3u ", at->at_hist[i]);
810 	seq_printf(m, "\n");
811 	return 0;
812 }
813 EXPORT_SYMBOL(lprocfs_at_hist_helper);
814 
815 /* See also ptlrpc_lprocfs_rd_timeouts */
lprocfs_rd_timeouts(struct seq_file * m,void * data)816 int lprocfs_rd_timeouts(struct seq_file *m, void *data)
817 {
818 	struct obd_device *obd = data;
819 	struct obd_import *imp;
820 	unsigned int cur, worst;
821 	time64_t now, worstt;
822 	struct dhms ts;
823 	int i, rc;
824 
825 	LASSERT(obd != NULL);
826 	rc = lprocfs_climp_check(obd);
827 	if (rc)
828 		return rc;
829 
830 	imp = obd->u.cli.cl_import;
831 
832 	now = ktime_get_real_seconds();
833 
834 	/* Some network health info for kicks */
835 	s2dhms(&ts, now - imp->imp_last_reply_time);
836 	seq_printf(m, "%-10s : %lld, " DHMS_FMT " ago\n",
837 		   "last reply", (s64)imp->imp_last_reply_time, DHMS_VARS(&ts));
838 
839 	cur = at_get(&imp->imp_at.iat_net_latency);
840 	worst = imp->imp_at.iat_net_latency.at_worst_ever;
841 	worstt = imp->imp_at.iat_net_latency.at_worst_time;
842 	s2dhms(&ts, now - worstt);
843 	seq_printf(m, "%-10s : cur %3u  worst %3u (at %lld, " DHMS_FMT " ago) ",
844 		   "network", cur, worst, (s64)worstt, DHMS_VARS(&ts));
845 	lprocfs_at_hist_helper(m, &imp->imp_at.iat_net_latency);
846 
847 	for (i = 0; i < IMP_AT_MAX_PORTALS; i++) {
848 		if (imp->imp_at.iat_portal[i] == 0)
849 			break;
850 		cur = at_get(&imp->imp_at.iat_service_estimate[i]);
851 		worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
852 		worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
853 		s2dhms(&ts, now - worstt);
854 		seq_printf(m, "portal %-2d  : cur %3u  worst %3u (at %lld, "
855 			   DHMS_FMT " ago) ", imp->imp_at.iat_portal[i],
856 			   cur, worst, (s64)worstt, DHMS_VARS(&ts));
857 		lprocfs_at_hist_helper(m, &imp->imp_at.iat_service_estimate[i]);
858 	}
859 
860 	LPROCFS_CLIMP_EXIT(obd);
861 	return 0;
862 }
863 EXPORT_SYMBOL(lprocfs_rd_timeouts);
864 
lprocfs_rd_connect_flags(struct seq_file * m,void * data)865 int lprocfs_rd_connect_flags(struct seq_file *m, void *data)
866 {
867 	struct obd_device *obd = data;
868 	__u64 flags;
869 	int rc;
870 
871 	rc = lprocfs_climp_check(obd);
872 	if (rc)
873 		return rc;
874 
875 	flags = obd->u.cli.cl_import->imp_connect_data.ocd_connect_flags;
876 	seq_printf(m, "flags=%#llx\n", flags);
877 	obd_connect_seq_flags2str(m, flags, "\n");
878 	seq_printf(m, "\n");
879 	LPROCFS_CLIMP_EXIT(obd);
880 	return 0;
881 }
882 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
883 
884 static struct attribute *obd_def_attrs[] = {
885 	&lustre_attr_blocksize.attr,
886 	&lustre_attr_kbytestotal.attr,
887 	&lustre_attr_kbytesfree.attr,
888 	&lustre_attr_kbytesavail.attr,
889 	&lustre_attr_filestotal.attr,
890 	&lustre_attr_filesfree.attr,
891 	&lustre_attr_uuid.attr,
892 	NULL,
893 };
894 
obd_sysfs_release(struct kobject * kobj)895 static void obd_sysfs_release(struct kobject *kobj)
896 {
897 	struct obd_device *obd = container_of(kobj, struct obd_device,
898 					      obd_kobj);
899 
900 	complete(&obd->obd_kobj_unregister);
901 }
902 
903 static struct kobj_type obd_ktype = {
904 	.default_attrs	= obd_def_attrs,
905 	.sysfs_ops	= &lustre_sysfs_ops,
906 	.release	= obd_sysfs_release,
907 };
908 
lprocfs_obd_setup(struct obd_device * obd,struct lprocfs_vars * list,struct attribute_group * attrs)909 int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list,
910 		      struct attribute_group *attrs)
911 {
912 	int rc = 0;
913 
914 	init_completion(&obd->obd_kobj_unregister);
915 	rc = kobject_init_and_add(&obd->obd_kobj, &obd_ktype,
916 				  obd->obd_type->typ_kobj,
917 				  "%s", obd->obd_name);
918 	if (rc)
919 		return rc;
920 
921 	if (attrs) {
922 		rc = sysfs_create_group(&obd->obd_kobj, attrs);
923 		if (rc) {
924 			kobject_put(&obd->obd_kobj);
925 			return rc;
926 		}
927 	}
928 
929 	obd->obd_debugfs_entry = ldebugfs_register(obd->obd_name,
930 						   obd->obd_type->typ_debugfs_entry,
931 						   list, obd);
932 	if (IS_ERR_OR_NULL(obd->obd_debugfs_entry)) {
933 		rc = obd->obd_debugfs_entry ? PTR_ERR(obd->obd_debugfs_entry)
934 					    : -ENOMEM;
935 		CERROR("error %d setting up lprocfs for %s\n",
936 		       rc, obd->obd_name);
937 		obd->obd_debugfs_entry = NULL;
938 	}
939 
940 	return rc;
941 }
942 EXPORT_SYMBOL(lprocfs_obd_setup);
943 
lprocfs_obd_cleanup(struct obd_device * obd)944 int lprocfs_obd_cleanup(struct obd_device *obd)
945 {
946 	if (!obd)
947 		return -EINVAL;
948 
949 	if (!IS_ERR_OR_NULL(obd->obd_debugfs_entry))
950 		ldebugfs_remove(&obd->obd_debugfs_entry);
951 
952 	kobject_put(&obd->obd_kobj);
953 	wait_for_completion(&obd->obd_kobj_unregister);
954 
955 	return 0;
956 }
957 EXPORT_SYMBOL(lprocfs_obd_cleanup);
958 
lprocfs_stats_alloc_one(struct lprocfs_stats * stats,unsigned int cpuid)959 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
960 {
961 	struct lprocfs_counter  *cntr;
962 	unsigned int            percpusize;
963 	int                     rc = -ENOMEM;
964 	unsigned long           flags = 0;
965 	int                     i;
966 
967 	LASSERT(stats->ls_percpu[cpuid] == NULL);
968 	LASSERT((stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) == 0);
969 
970 	percpusize = lprocfs_stats_counter_size(stats);
971 	LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[cpuid], percpusize);
972 	if (stats->ls_percpu[cpuid] != NULL) {
973 		rc = 0;
974 		if (unlikely(stats->ls_biggest_alloc_num <= cpuid)) {
975 			if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
976 				spin_lock_irqsave(&stats->ls_lock, flags);
977 			else
978 				spin_lock(&stats->ls_lock);
979 			if (stats->ls_biggest_alloc_num <= cpuid)
980 				stats->ls_biggest_alloc_num = cpuid + 1;
981 			if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
982 				spin_unlock_irqrestore(&stats->ls_lock, flags);
983 			else
984 				spin_unlock(&stats->ls_lock);
985 		}
986 		/* initialize the ls_percpu[cpuid] non-zero counter */
987 		for (i = 0; i < stats->ls_num; ++i) {
988 			cntr = lprocfs_stats_counter_get(stats, cpuid, i);
989 			cntr->lc_min = LC_MIN_INIT;
990 		}
991 	}
992 	return rc;
993 }
994 EXPORT_SYMBOL(lprocfs_stats_alloc_one);
995 
lprocfs_alloc_stats(unsigned int num,enum lprocfs_stats_flags flags)996 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
997 					  enum lprocfs_stats_flags flags)
998 {
999 	struct lprocfs_stats	*stats;
1000 	unsigned int		num_entry;
1001 	unsigned int		percpusize = 0;
1002 	int			i;
1003 
1004 	if (num == 0)
1005 		return NULL;
1006 
1007 	if (lprocfs_no_percpu_stats != 0)
1008 		flags |= LPROCFS_STATS_FLAG_NOPERCPU;
1009 
1010 	if (flags & LPROCFS_STATS_FLAG_NOPERCPU)
1011 		num_entry = 1;
1012 	else
1013 		num_entry = num_possible_cpus();
1014 
1015 	/* alloc percpu pointers for all possible cpu slots */
1016 	LIBCFS_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1017 	if (stats == NULL)
1018 		return NULL;
1019 
1020 	stats->ls_num = num;
1021 	stats->ls_flags = flags;
1022 	spin_lock_init(&stats->ls_lock);
1023 
1024 	/* alloc num of counter headers */
1025 	LIBCFS_ALLOC(stats->ls_cnt_header,
1026 		     stats->ls_num * sizeof(struct lprocfs_counter_header));
1027 	if (stats->ls_cnt_header == NULL)
1028 		goto fail;
1029 
1030 	if ((flags & LPROCFS_STATS_FLAG_NOPERCPU) != 0) {
1031 		/* contains only one set counters */
1032 		percpusize = lprocfs_stats_counter_size(stats);
1033 		LIBCFS_ALLOC_ATOMIC(stats->ls_percpu[0], percpusize);
1034 		if (stats->ls_percpu[0] == NULL)
1035 			goto fail;
1036 		stats->ls_biggest_alloc_num = 1;
1037 	} else if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0) {
1038 		/* alloc all percpu data */
1039 		for (i = 0; i < num_entry; ++i)
1040 			if (lprocfs_stats_alloc_one(stats, i) < 0)
1041 				goto fail;
1042 	}
1043 
1044 	return stats;
1045 
1046 fail:
1047 	lprocfs_free_stats(&stats);
1048 	return NULL;
1049 }
1050 EXPORT_SYMBOL(lprocfs_alloc_stats);
1051 
lprocfs_free_stats(struct lprocfs_stats ** statsh)1052 void lprocfs_free_stats(struct lprocfs_stats **statsh)
1053 {
1054 	struct lprocfs_stats *stats = *statsh;
1055 	unsigned int num_entry;
1056 	unsigned int percpusize;
1057 	unsigned int i;
1058 
1059 	if (stats == NULL || stats->ls_num == 0)
1060 		return;
1061 	*statsh = NULL;
1062 
1063 	if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
1064 		num_entry = 1;
1065 	else
1066 		num_entry = num_possible_cpus();
1067 
1068 	percpusize = lprocfs_stats_counter_size(stats);
1069 	for (i = 0; i < num_entry; i++)
1070 		if (stats->ls_percpu[i] != NULL)
1071 			LIBCFS_FREE(stats->ls_percpu[i], percpusize);
1072 	if (stats->ls_cnt_header != NULL)
1073 		LIBCFS_FREE(stats->ls_cnt_header, stats->ls_num *
1074 					sizeof(struct lprocfs_counter_header));
1075 	LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
1076 }
1077 EXPORT_SYMBOL(lprocfs_free_stats);
1078 
lprocfs_clear_stats(struct lprocfs_stats * stats)1079 void lprocfs_clear_stats(struct lprocfs_stats *stats)
1080 {
1081 	struct lprocfs_counter		*percpu_cntr;
1082 	int				i;
1083 	int				j;
1084 	unsigned int			num_entry;
1085 	unsigned long			flags = 0;
1086 
1087 	num_entry = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1088 
1089 	for (i = 0; i < num_entry; i++) {
1090 		if (stats->ls_percpu[i] == NULL)
1091 			continue;
1092 		for (j = 0; j < stats->ls_num; j++) {
1093 			percpu_cntr = lprocfs_stats_counter_get(stats, i, j);
1094 			percpu_cntr->lc_count		= 0;
1095 			percpu_cntr->lc_min		= LC_MIN_INIT;
1096 			percpu_cntr->lc_max		= 0;
1097 			percpu_cntr->lc_sumsquare	= 0;
1098 			percpu_cntr->lc_sum		= 0;
1099 			if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
1100 				percpu_cntr->lc_sum_irq	= 0;
1101 		}
1102 	}
1103 
1104 	lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1105 }
1106 EXPORT_SYMBOL(lprocfs_clear_stats);
1107 
lprocfs_stats_seq_write(struct file * file,const char __user * buf,size_t len,loff_t * off)1108 static ssize_t lprocfs_stats_seq_write(struct file *file,
1109 				       const char __user *buf,
1110 				       size_t len, loff_t *off)
1111 {
1112 	struct seq_file *seq = file->private_data;
1113 	struct lprocfs_stats *stats = seq->private;
1114 
1115 	lprocfs_clear_stats(stats);
1116 
1117 	return len;
1118 }
1119 
lprocfs_stats_seq_start(struct seq_file * p,loff_t * pos)1120 static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos)
1121 {
1122 	struct lprocfs_stats *stats = p->private;
1123 
1124 	return (*pos < stats->ls_num) ? pos : NULL;
1125 }
1126 
lprocfs_stats_seq_stop(struct seq_file * p,void * v)1127 static void lprocfs_stats_seq_stop(struct seq_file *p, void *v)
1128 {
1129 }
1130 
lprocfs_stats_seq_next(struct seq_file * p,void * v,loff_t * pos)1131 static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos)
1132 {
1133 	(*pos)++;
1134 	return lprocfs_stats_seq_start(p, pos);
1135 }
1136 
1137 /* seq file export of one lprocfs counter */
lprocfs_stats_seq_show(struct seq_file * p,void * v)1138 static int lprocfs_stats_seq_show(struct seq_file *p, void *v)
1139 {
1140 	struct lprocfs_stats		*stats	= p->private;
1141 	struct lprocfs_counter_header   *hdr;
1142 	struct lprocfs_counter           ctr;
1143 	int                              idx    = *(loff_t *)v;
1144 
1145 	if (idx == 0) {
1146 		struct timespec64 now;
1147 
1148 		ktime_get_real_ts64(&now);
1149 		seq_printf(p, "%-25s %llu.%9lu secs.usecs\n",
1150 			   "snapshot_time",
1151 			   (s64)now.tv_sec, (unsigned long)now.tv_nsec);
1152 	}
1153 
1154 	hdr = &stats->ls_cnt_header[idx];
1155 	lprocfs_stats_collect(stats, idx, &ctr);
1156 
1157 	if (ctr.lc_count != 0) {
1158 		seq_printf(p, "%-25s %lld samples [%s]",
1159 			   hdr->lc_name, ctr.lc_count, hdr->lc_units);
1160 
1161 		if ((hdr->lc_config & LPROCFS_CNTR_AVGMINMAX) &&
1162 		    (ctr.lc_count > 0)) {
1163 			seq_printf(p, " %lld %lld %lld",
1164 				   ctr.lc_min, ctr.lc_max, ctr.lc_sum);
1165 			if (hdr->lc_config & LPROCFS_CNTR_STDDEV)
1166 				seq_printf(p, " %lld", ctr.lc_sumsquare);
1167 		}
1168 		seq_putc(p, '\n');
1169 	}
1170 
1171 	return 0;
1172 }
1173 
1174 static const struct seq_operations lprocfs_stats_seq_sops = {
1175 	.start	= lprocfs_stats_seq_start,
1176 	.stop	= lprocfs_stats_seq_stop,
1177 	.next	= lprocfs_stats_seq_next,
1178 	.show	= lprocfs_stats_seq_show,
1179 };
1180 
lprocfs_stats_seq_open(struct inode * inode,struct file * file)1181 static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
1182 {
1183 	struct seq_file *seq;
1184 	int rc;
1185 
1186 	rc = seq_open(file, &lprocfs_stats_seq_sops);
1187 	if (rc)
1188 		return rc;
1189 
1190 	seq = file->private_data;
1191 	seq->private = inode->i_private;
1192 
1193 	return 0;
1194 }
1195 
1196 struct file_operations lprocfs_stats_seq_fops = {
1197 	.owner   = THIS_MODULE,
1198 	.open    = lprocfs_stats_seq_open,
1199 	.read    = seq_read,
1200 	.write   = lprocfs_stats_seq_write,
1201 	.llseek  = seq_lseek,
1202 	.release = lprocfs_seq_release,
1203 };
1204 
ldebugfs_register_stats(struct dentry * parent,const char * name,struct lprocfs_stats * stats)1205 int ldebugfs_register_stats(struct dentry *parent, const char *name,
1206 			   struct lprocfs_stats *stats)
1207 {
1208 	struct dentry *entry;
1209 
1210 	LASSERT(!IS_ERR_OR_NULL(parent));
1211 
1212 	entry = debugfs_create_file(name, 0644, parent, stats,
1213 				    &lprocfs_stats_seq_fops);
1214 	if (IS_ERR_OR_NULL(entry))
1215 		return entry ? PTR_ERR(entry) : -ENOMEM;
1216 
1217 	return 0;
1218 }
1219 EXPORT_SYMBOL(ldebugfs_register_stats);
1220 
lprocfs_counter_init(struct lprocfs_stats * stats,int index,unsigned conf,const char * name,const char * units)1221 void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
1222 			  unsigned conf, const char *name, const char *units)
1223 {
1224 	struct lprocfs_counter_header	*header;
1225 	struct lprocfs_counter		*percpu_cntr;
1226 	unsigned long			flags = 0;
1227 	unsigned int			i;
1228 	unsigned int			num_cpu;
1229 
1230 	LASSERT(stats != NULL);
1231 
1232 	header = &stats->ls_cnt_header[index];
1233 	LASSERTF(header != NULL, "Failed to allocate stats header:[%d]%s/%s\n",
1234 		 index, name, units);
1235 
1236 	header->lc_config = conf;
1237 	header->lc_name   = name;
1238 	header->lc_units  = units;
1239 
1240 	num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU, &flags);
1241 	for (i = 0; i < num_cpu; ++i) {
1242 		if (stats->ls_percpu[i] == NULL)
1243 			continue;
1244 		percpu_cntr = lprocfs_stats_counter_get(stats, i, index);
1245 		percpu_cntr->lc_count		= 0;
1246 		percpu_cntr->lc_min		= LC_MIN_INIT;
1247 		percpu_cntr->lc_max		= 0;
1248 		percpu_cntr->lc_sumsquare	= 0;
1249 		percpu_cntr->lc_sum		= 0;
1250 		if ((stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1251 			percpu_cntr->lc_sum_irq	= 0;
1252 	}
1253 	lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
1254 }
1255 EXPORT_SYMBOL(lprocfs_counter_init);
1256 
lprocfs_exp_cleanup(struct obd_export * exp)1257 int lprocfs_exp_cleanup(struct obd_export *exp)
1258 {
1259 	return 0;
1260 }
1261 EXPORT_SYMBOL(lprocfs_exp_cleanup);
1262 
lprocfs_read_helper(struct lprocfs_counter * lc,struct lprocfs_counter_header * header,enum lprocfs_stats_flags flags,enum lprocfs_fields_flags field)1263 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
1264 			  struct lprocfs_counter_header *header,
1265 			  enum lprocfs_stats_flags flags,
1266 			  enum lprocfs_fields_flags field)
1267 {
1268 	__s64 ret = 0;
1269 
1270 	if (lc == NULL || header == NULL)
1271 		return 0;
1272 
1273 	switch (field) {
1274 	case LPROCFS_FIELDS_FLAGS_CONFIG:
1275 		ret = header->lc_config;
1276 		break;
1277 	case LPROCFS_FIELDS_FLAGS_SUM:
1278 		ret = lc->lc_sum;
1279 		if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
1280 			ret += lc->lc_sum_irq;
1281 		break;
1282 	case LPROCFS_FIELDS_FLAGS_MIN:
1283 		ret = lc->lc_min;
1284 		break;
1285 	case LPROCFS_FIELDS_FLAGS_MAX:
1286 		ret = lc->lc_max;
1287 		break;
1288 	case LPROCFS_FIELDS_FLAGS_AVG:
1289 		ret = (lc->lc_max - lc->lc_min) / 2;
1290 		break;
1291 	case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
1292 		ret = lc->lc_sumsquare;
1293 		break;
1294 	case LPROCFS_FIELDS_FLAGS_COUNT:
1295 		ret = lc->lc_count;
1296 		break;
1297 	default:
1298 		break;
1299 	}
1300 
1301 	return 0;
1302 }
1303 EXPORT_SYMBOL(lprocfs_read_helper);
1304 
lprocfs_write_helper(const char __user * buffer,unsigned long count,int * val)1305 int lprocfs_write_helper(const char __user *buffer, unsigned long count,
1306 			 int *val)
1307 {
1308 	return lprocfs_write_frac_helper(buffer, count, val, 1);
1309 }
1310 EXPORT_SYMBOL(lprocfs_write_helper);
1311 
lprocfs_write_u64_helper(const char __user * buffer,unsigned long count,__u64 * val)1312 int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count,
1313 			     __u64 *val)
1314 {
1315 	return lprocfs_write_frac_u64_helper(buffer, count, val, 1);
1316 }
1317 EXPORT_SYMBOL(lprocfs_write_u64_helper);
1318 
lprocfs_write_frac_u64_helper(const char * buffer,unsigned long count,__u64 * val,int mult)1319 int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
1320 			      __u64 *val, int mult)
1321 {
1322 	char kernbuf[22], *end, *pbuf;
1323 	__u64 whole, frac = 0, units;
1324 	unsigned frac_d = 1;
1325 	int sign = 1;
1326 
1327 	if (count > (sizeof(kernbuf) - 1))
1328 		return -EINVAL;
1329 
1330 	if (copy_from_user(kernbuf, buffer, count))
1331 		return -EFAULT;
1332 
1333 	kernbuf[count] = '\0';
1334 	pbuf = kernbuf;
1335 	if (*pbuf == '-') {
1336 		sign = -1;
1337 		pbuf++;
1338 	}
1339 
1340 	whole = simple_strtoull(pbuf, &end, 10);
1341 	if (pbuf == end)
1342 		return -EINVAL;
1343 
1344 	if (*end == '.') {
1345 		int i;
1346 
1347 		pbuf = end + 1;
1348 
1349 		/* need to limit frac_d to a __u32 */
1350 		if (strlen(pbuf) > 10)
1351 			pbuf[10] = '\0';
1352 
1353 		frac = simple_strtoull(pbuf, &end, 10);
1354 		/* count decimal places */
1355 		for (i = 0; i < (end - pbuf); i++)
1356 			frac_d *= 10;
1357 	}
1358 
1359 	units = 1;
1360 	switch (tolower(*end)) {
1361 	case 'p':
1362 		units <<= 10;
1363 	case 't':
1364 		units <<= 10;
1365 	case 'g':
1366 		units <<= 10;
1367 	case 'm':
1368 		units <<= 10;
1369 	case 'k':
1370 		units <<= 10;
1371 	}
1372 	/* Specified units override the multiplier */
1373 	if (units > 1)
1374 		mult = units;
1375 
1376 	frac *= mult;
1377 	do_div(frac, frac_d);
1378 	*val = sign * (whole * mult + frac);
1379 	return 0;
1380 }
1381 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper);
1382 
lprocfs_strnstr(const char * s1,const char * s2,size_t len)1383 static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
1384 {
1385 	size_t l2;
1386 
1387 	l2 = strlen(s2);
1388 	if (!l2)
1389 		return (char *)s1;
1390 	while (len >= l2) {
1391 		len--;
1392 		if (!memcmp(s1, s2, l2))
1393 			return (char *)s1;
1394 		s1++;
1395 	}
1396 	return NULL;
1397 }
1398 
1399 /**
1400  * Find the string \a name in the input \a buffer, and return a pointer to the
1401  * value immediately following \a name, reducing \a count appropriately.
1402  * If \a name is not found the original \a buffer is returned.
1403  */
lprocfs_find_named_value(const char * buffer,const char * name,size_t * count)1404 char *lprocfs_find_named_value(const char *buffer, const char *name,
1405 			       size_t *count)
1406 {
1407 	char *val;
1408 	size_t buflen = *count;
1409 
1410 	/* there is no strnstr() in rhel5 and ubuntu kernels */
1411 	val = lprocfs_strnstr(buffer, name, buflen);
1412 	if (val == NULL)
1413 		return (char *)buffer;
1414 
1415 	val += strlen(name);			     /* skip prefix */
1416 	while (val < buffer + buflen && isspace(*val)) /* skip separator */
1417 		val++;
1418 
1419 	*count = 0;
1420 	while (val < buffer + buflen && isalnum(*val)) {
1421 		++*count;
1422 		++val;
1423 	}
1424 
1425 	return val - *count;
1426 }
1427 EXPORT_SYMBOL(lprocfs_find_named_value);
1428 
ldebugfs_seq_create(struct dentry * parent,const char * name,umode_t mode,const struct file_operations * seq_fops,void * data)1429 int ldebugfs_seq_create(struct dentry *parent,
1430 		       const char *name,
1431 		       umode_t mode,
1432 		       const struct file_operations *seq_fops,
1433 		       void *data)
1434 {
1435 	struct dentry *entry;
1436 
1437 	/* Disallow secretly (un)writable entries. */
1438 	LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0));
1439 
1440 	entry = debugfs_create_file(name, mode, parent, data, seq_fops);
1441 	if (IS_ERR_OR_NULL(entry))
1442 		return entry ? PTR_ERR(entry) : -ENOMEM;
1443 
1444 	return 0;
1445 }
1446 EXPORT_SYMBOL(ldebugfs_seq_create);
1447 
ldebugfs_obd_seq_create(struct obd_device * dev,const char * name,umode_t mode,const struct file_operations * seq_fops,void * data)1448 int ldebugfs_obd_seq_create(struct obd_device *dev,
1449 			    const char *name,
1450 			    umode_t mode,
1451 			    const struct file_operations *seq_fops,
1452 			    void *data)
1453 {
1454 	return ldebugfs_seq_create(dev->obd_debugfs_entry, name,
1455 				   mode, seq_fops, data);
1456 }
1457 EXPORT_SYMBOL(ldebugfs_obd_seq_create);
1458 
lprocfs_oh_tally(struct obd_histogram * oh,unsigned int value)1459 void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
1460 {
1461 	if (value >= OBD_HIST_MAX)
1462 		value = OBD_HIST_MAX - 1;
1463 
1464 	spin_lock(&oh->oh_lock);
1465 	oh->oh_buckets[value]++;
1466 	spin_unlock(&oh->oh_lock);
1467 }
1468 EXPORT_SYMBOL(lprocfs_oh_tally);
1469 
lprocfs_oh_tally_log2(struct obd_histogram * oh,unsigned int value)1470 void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value)
1471 {
1472 	unsigned int val;
1473 
1474 	for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++)
1475 		;
1476 
1477 	lprocfs_oh_tally(oh, val);
1478 }
1479 EXPORT_SYMBOL(lprocfs_oh_tally_log2);
1480 
lprocfs_oh_sum(struct obd_histogram * oh)1481 unsigned long lprocfs_oh_sum(struct obd_histogram *oh)
1482 {
1483 	unsigned long ret = 0;
1484 	int i;
1485 
1486 	for (i = 0; i < OBD_HIST_MAX; i++)
1487 		ret +=  oh->oh_buckets[i];
1488 	return ret;
1489 }
1490 EXPORT_SYMBOL(lprocfs_oh_sum);
1491 
lprocfs_oh_clear(struct obd_histogram * oh)1492 void lprocfs_oh_clear(struct obd_histogram *oh)
1493 {
1494 	spin_lock(&oh->oh_lock);
1495 	memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets));
1496 	spin_unlock(&oh->oh_lock);
1497 }
1498 EXPORT_SYMBOL(lprocfs_oh_clear);
1499 
lustre_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)1500 static ssize_t lustre_attr_show(struct kobject *kobj,
1501 				struct attribute *attr, char *buf)
1502 {
1503 	struct lustre_attr *a = container_of(attr, struct lustre_attr, attr);
1504 
1505 	return a->show ? a->show(kobj, attr, buf) : 0;
1506 }
1507 
lustre_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)1508 static ssize_t lustre_attr_store(struct kobject *kobj, struct attribute *attr,
1509 				 const char *buf, size_t len)
1510 {
1511 	struct lustre_attr *a = container_of(attr, struct lustre_attr, attr);
1512 
1513 	return a->store ? a->store(kobj, attr, buf, len) : len;
1514 }
1515 
1516 const struct sysfs_ops lustre_sysfs_ops = {
1517 	.show  = lustre_attr_show,
1518 	.store = lustre_attr_store,
1519 };
1520 EXPORT_SYMBOL_GPL(lustre_sysfs_ops);
1521