4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2011, 2015, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
32 * lustre/obdclass/lprocfs_status.c
34 * Author: Hariharan Thantry <thantry@users.sourceforge.net>
37 #define DEBUG_SUBSYSTEM S_CLASS
39 #include "../include/obd_class.h"
40 #include "../include/lprocfs_status.h"
41 #include "../include/lustre/lustre_idl.h"
42 #include <linux/seq_file.h>
43 #include <linux/ctype.h>
45 static const char * const obd_connect_names
[] = {
59 "join_file(obsolete)",
63 "remote_client_by_force",
75 "alt_checksum_algorithm",
109 int obd_connect_flags2str(char *page
, int count
, __u64 flags
, char *sep
)
114 for (i
= 0; obd_connect_names
[i
]; i
++, mask
<<= 1) {
116 ret
+= snprintf(page
+ ret
, count
- ret
, "%s%s",
117 ret
? sep
: "", obd_connect_names
[i
]);
119 if (flags
& ~(mask
- 1))
120 ret
+= snprintf(page
+ ret
, count
- ret
,
121 "%sunknown flags %#llx",
122 ret
? sep
: "", flags
& ~(mask
- 1));
125 EXPORT_SYMBOL(obd_connect_flags2str
);
127 static void obd_connect_data_seqprint(struct seq_file
*m
,
128 struct obd_connect_data
*ocd
)
133 flags
= ocd
->ocd_connect_flags
;
135 seq_printf(m
, " connect_data:\n"
138 ocd
->ocd_connect_flags
,
140 if (flags
& OBD_CONNECT_VERSION
)
141 seq_printf(m
, " target_version: %u.%u.%u.%u\n",
142 OBD_OCD_VERSION_MAJOR(ocd
->ocd_version
),
143 OBD_OCD_VERSION_MINOR(ocd
->ocd_version
),
144 OBD_OCD_VERSION_PATCH(ocd
->ocd_version
),
145 OBD_OCD_VERSION_FIX(ocd
->ocd_version
));
146 if (flags
& OBD_CONNECT_MDS
)
147 seq_printf(m
, " mdt_index: %d\n", ocd
->ocd_group
);
148 if (flags
& OBD_CONNECT_GRANT
)
149 seq_printf(m
, " initial_grant: %d\n", ocd
->ocd_grant
);
150 if (flags
& OBD_CONNECT_INDEX
)
151 seq_printf(m
, " target_index: %u\n", ocd
->ocd_index
);
152 if (flags
& OBD_CONNECT_BRW_SIZE
)
153 seq_printf(m
, " max_brw_size: %d\n", ocd
->ocd_brw_size
);
154 if (flags
& OBD_CONNECT_IBITS
)
155 seq_printf(m
, " ibits_known: %llx\n",
156 ocd
->ocd_ibits_known
);
157 if (flags
& OBD_CONNECT_GRANT_PARAM
)
158 seq_printf(m
, " grant_block_size: %d\n"
159 " grant_inode_size: %d\n"
160 " grant_extent_overhead: %d\n",
163 ocd
->ocd_grant_extent
);
164 if (flags
& OBD_CONNECT_TRANSNO
)
165 seq_printf(m
, " first_transno: %llx\n",
167 if (flags
& OBD_CONNECT_CKSUM
)
168 seq_printf(m
, " cksum_types: %#x\n",
169 ocd
->ocd_cksum_types
);
170 if (flags
& OBD_CONNECT_MAX_EASIZE
)
171 seq_printf(m
, " max_easize: %d\n", ocd
->ocd_max_easize
);
172 if (flags
& OBD_CONNECT_MAXBYTES
)
173 seq_printf(m
, " max_object_bytes: %llx\n",
177 int lprocfs_read_frac_helper(char *buffer
, unsigned long count
, long val
,
180 long decimal_val
, frac_val
;
186 decimal_val
= val
/ mult
;
187 prtn
= snprintf(buffer
, count
, "%ld", decimal_val
);
188 frac_val
= val
% mult
;
190 if (prtn
< (count
- 4) && frac_val
> 0) {
192 int i
, temp_mult
= 1, frac_bits
= 0;
194 temp_frac
= frac_val
* 10;
195 buffer
[prtn
++] = '.';
196 while (frac_bits
< 2 && (temp_frac
/ mult
) < 1) {
197 /* only reserved 2 bits fraction */
198 buffer
[prtn
++] = '0';
203 * Need to think these cases :
204 * 1. #echo x.00 > /sys/xxx output result : x
205 * 2. #echo x.0x > /sys/xxx output result : x.0x
206 * 3. #echo x.x0 > /sys/xxx output result : x.x
207 * 4. #echo x.xx > /sys/xxx output result : x.xx
208 * Only reserved 2 bits fraction.
210 for (i
= 0; i
< (5 - prtn
); i
++)
213 frac_bits
= min((int)count
- prtn
, 3 - frac_bits
);
214 prtn
+= snprintf(buffer
+ prtn
, frac_bits
, "%ld",
215 frac_val
* temp_mult
/ mult
);
218 while (buffer
[prtn
] < '1' || buffer
[prtn
] > '9') {
220 if (buffer
[prtn
] == '.') {
227 buffer
[prtn
++] = '\n';
230 EXPORT_SYMBOL(lprocfs_read_frac_helper
);
232 int lprocfs_write_frac_helper(const char __user
*buffer
, unsigned long count
,
235 char kernbuf
[20], *end
, *pbuf
;
237 if (count
> (sizeof(kernbuf
) - 1))
240 if (copy_from_user(kernbuf
, buffer
, count
))
243 kernbuf
[count
] = '\0';
250 *val
= (int)simple_strtoul(pbuf
, &end
, 10) * mult
;
254 if (end
&& *end
== '.') {
255 int temp_val
, pow
= 1;
259 if (strlen(pbuf
) > 5)
260 pbuf
[5] = '\0'; /*only allow 5bits fractional*/
262 temp_val
= (int)simple_strtoul(pbuf
, &end
, 10) * mult
;
265 for (i
= 0; i
< (end
- pbuf
); i
++)
268 *val
+= temp_val
/ pow
;
273 EXPORT_SYMBOL(lprocfs_write_frac_helper
);
275 static int lprocfs_no_percpu_stats
;
276 module_param(lprocfs_no_percpu_stats
, int, 0644);
277 MODULE_PARM_DESC(lprocfs_no_percpu_stats
, "Do not alloc percpu data for lprocfs stats");
279 #define MAX_STRING_SIZE 128
281 int lprocfs_single_release(struct inode
*inode
, struct file
*file
)
283 return single_release(inode
, file
);
285 EXPORT_SYMBOL(lprocfs_single_release
);
287 int lprocfs_seq_release(struct inode
*inode
, struct file
*file
)
289 return seq_release(inode
, file
);
291 EXPORT_SYMBOL(lprocfs_seq_release
);
293 /* lprocfs API calls */
295 struct dentry
*ldebugfs_add_simple(struct dentry
*root
,
296 char *name
, void *data
,
297 struct file_operations
*fops
)
299 struct dentry
*entry
;
302 if (!root
|| !name
|| !fops
)
303 return ERR_PTR(-EINVAL
);
309 entry
= debugfs_create_file(name
, mode
, root
, data
, fops
);
310 if (IS_ERR_OR_NULL(entry
)) {
311 CERROR("LprocFS: No memory to create <debugfs> entry %s\n", name
);
312 return entry
?: ERR_PTR(-ENOMEM
);
316 EXPORT_SYMBOL_GPL(ldebugfs_add_simple
);
318 static const struct file_operations lprocfs_generic_fops
= { };
320 int ldebugfs_add_vars(struct dentry
*parent
,
321 struct lprocfs_vars
*list
,
324 if (IS_ERR_OR_NULL(parent
) || IS_ERR_OR_NULL(list
))
328 struct dentry
*entry
;
331 if (list
->proc_mode
!= 0000) {
332 mode
= list
->proc_mode
;
333 } else if (list
->fops
) {
334 if (list
->fops
->read
)
336 if (list
->fops
->write
)
339 entry
= debugfs_create_file(list
->name
, mode
, parent
,
341 list
->fops
?: &lprocfs_generic_fops
343 if (IS_ERR_OR_NULL(entry
))
344 return entry
? PTR_ERR(entry
) : -ENOMEM
;
349 EXPORT_SYMBOL_GPL(ldebugfs_add_vars
);
351 void ldebugfs_remove(struct dentry
**entryp
)
353 debugfs_remove_recursive(*entryp
);
356 EXPORT_SYMBOL_GPL(ldebugfs_remove
);
358 struct dentry
*ldebugfs_register(const char *name
,
359 struct dentry
*parent
,
360 struct lprocfs_vars
*list
, void *data
)
362 struct dentry
*entry
;
364 entry
= debugfs_create_dir(name
, parent
);
365 if (IS_ERR_OR_NULL(entry
)) {
366 entry
= entry
?: ERR_PTR(-ENOMEM
);
370 if (!IS_ERR_OR_NULL(list
)) {
373 rc
= ldebugfs_add_vars(entry
, list
, data
);
375 debugfs_remove(entry
);
382 EXPORT_SYMBOL_GPL(ldebugfs_register
);
384 /* Generic callbacks */
385 int lprocfs_rd_uint(struct seq_file
*m
, void *data
)
387 seq_printf(m
, "%u\n", *(unsigned int *)data
);
390 EXPORT_SYMBOL(lprocfs_rd_uint
);
392 int lprocfs_wr_uint(struct file
*file
, const char __user
*buffer
,
393 unsigned long count
, void *data
)
396 char dummy
[MAX_STRING_SIZE
+ 1], *end
;
399 dummy
[MAX_STRING_SIZE
] = '\0';
400 if (copy_from_user(dummy
, buffer
, MAX_STRING_SIZE
))
403 tmp
= simple_strtoul(dummy
, &end
, 0);
407 *p
= (unsigned int)tmp
;
410 EXPORT_SYMBOL(lprocfs_wr_uint
);
412 static ssize_t
uuid_show(struct kobject
*kobj
, struct attribute
*attr
,
415 struct obd_device
*obd
= container_of(kobj
, struct obd_device
,
418 return sprintf(buf
, "%s\n", obd
->obd_uuid
.uuid
);
420 LUSTRE_RO_ATTR(uuid
);
422 static ssize_t
blocksize_show(struct kobject
*kobj
, struct attribute
*attr
,
425 struct obd_device
*obd
= container_of(kobj
, struct obd_device
,
427 struct obd_statfs osfs
;
428 int rc
= obd_statfs(NULL
, obd
->obd_self_export
, &osfs
,
429 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
432 return sprintf(buf
, "%u\n", osfs
.os_bsize
);
436 LUSTRE_RO_ATTR(blocksize
);
438 static ssize_t
kbytestotal_show(struct kobject
*kobj
, struct attribute
*attr
,
441 struct obd_device
*obd
= container_of(kobj
, struct obd_device
,
443 struct obd_statfs osfs
;
444 int rc
= obd_statfs(NULL
, obd
->obd_self_export
, &osfs
,
445 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
448 __u32 blk_size
= osfs
.os_bsize
>> 10;
449 __u64 result
= osfs
.os_blocks
;
451 while (blk_size
>>= 1)
454 return sprintf(buf
, "%llu\n", result
);
459 LUSTRE_RO_ATTR(kbytestotal
);
461 static ssize_t
kbytesfree_show(struct kobject
*kobj
, struct attribute
*attr
,
464 struct obd_device
*obd
= container_of(kobj
, struct obd_device
,
466 struct obd_statfs osfs
;
467 int rc
= obd_statfs(NULL
, obd
->obd_self_export
, &osfs
,
468 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
471 __u32 blk_size
= osfs
.os_bsize
>> 10;
472 __u64 result
= osfs
.os_bfree
;
474 while (blk_size
>>= 1)
477 return sprintf(buf
, "%llu\n", result
);
482 LUSTRE_RO_ATTR(kbytesfree
);
484 static ssize_t
kbytesavail_show(struct kobject
*kobj
, struct attribute
*attr
,
487 struct obd_device
*obd
= container_of(kobj
, struct obd_device
,
489 struct obd_statfs osfs
;
490 int rc
= obd_statfs(NULL
, obd
->obd_self_export
, &osfs
,
491 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
494 __u32 blk_size
= osfs
.os_bsize
>> 10;
495 __u64 result
= osfs
.os_bavail
;
497 while (blk_size
>>= 1)
500 return sprintf(buf
, "%llu\n", result
);
505 LUSTRE_RO_ATTR(kbytesavail
);
507 static ssize_t
filestotal_show(struct kobject
*kobj
, struct attribute
*attr
,
510 struct obd_device
*obd
= container_of(kobj
, struct obd_device
,
512 struct obd_statfs osfs
;
513 int rc
= obd_statfs(NULL
, obd
->obd_self_export
, &osfs
,
514 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
517 return sprintf(buf
, "%llu\n", osfs
.os_files
);
521 LUSTRE_RO_ATTR(filestotal
);
523 static ssize_t
filesfree_show(struct kobject
*kobj
, struct attribute
*attr
,
526 struct obd_device
*obd
= container_of(kobj
, struct obd_device
,
528 struct obd_statfs osfs
;
529 int rc
= obd_statfs(NULL
, obd
->obd_self_export
, &osfs
,
530 cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS
),
533 return sprintf(buf
, "%llu\n", osfs
.os_ffree
);
537 LUSTRE_RO_ATTR(filesfree
);
539 int lprocfs_rd_server_uuid(struct seq_file
*m
, void *data
)
541 struct obd_device
*obd
= data
;
542 struct obd_import
*imp
;
543 char *imp_state_name
= NULL
;
547 rc
= lprocfs_climp_check(obd
);
551 imp
= obd
->u
.cli
.cl_import
;
552 imp_state_name
= ptlrpc_import_state_name(imp
->imp_state
);
553 seq_printf(m
, "%s\t%s%s\n",
554 obd2cli_tgt(obd
), imp_state_name
,
555 imp
->imp_deactive
? "\tDEACTIVATED" : "");
557 up_read(&obd
->u
.cli
.cl_sem
);
561 EXPORT_SYMBOL(lprocfs_rd_server_uuid
);
563 int lprocfs_rd_conn_uuid(struct seq_file
*m
, void *data
)
565 struct obd_device
*obd
= data
;
566 struct ptlrpc_connection
*conn
;
571 rc
= lprocfs_climp_check(obd
);
575 conn
= obd
->u
.cli
.cl_import
->imp_connection
;
576 if (conn
&& obd
->u
.cli
.cl_import
)
577 seq_printf(m
, "%s\n", conn
->c_remote_uuid
.uuid
);
579 seq_puts(m
, "<none>\n");
581 up_read(&obd
->u
.cli
.cl_sem
);
585 EXPORT_SYMBOL(lprocfs_rd_conn_uuid
);
587 /** add up per-cpu counters */
588 void lprocfs_stats_collect(struct lprocfs_stats
*stats
, int idx
,
589 struct lprocfs_counter
*cnt
)
591 unsigned int num_entry
;
592 struct lprocfs_counter
*percpu_cntr
;
594 unsigned long flags
= 0;
596 memset(cnt
, 0, sizeof(*cnt
));
599 /* set count to 1 to avoid divide-by-zero errs in callers */
604 cnt
->lc_min
= LC_MIN_INIT
;
606 num_entry
= lprocfs_stats_lock(stats
, LPROCFS_GET_NUM_CPU
, &flags
);
608 for (i
= 0; i
< num_entry
; i
++) {
609 if (!stats
->ls_percpu
[i
])
611 percpu_cntr
= lprocfs_stats_counter_get(stats
, i
, idx
);
613 cnt
->lc_count
+= percpu_cntr
->lc_count
;
614 cnt
->lc_sum
+= percpu_cntr
->lc_sum
;
615 if (percpu_cntr
->lc_min
< cnt
->lc_min
)
616 cnt
->lc_min
= percpu_cntr
->lc_min
;
617 if (percpu_cntr
->lc_max
> cnt
->lc_max
)
618 cnt
->lc_max
= percpu_cntr
->lc_max
;
619 cnt
->lc_sumsquare
+= percpu_cntr
->lc_sumsquare
;
622 lprocfs_stats_unlock(stats
, LPROCFS_GET_NUM_CPU
, &flags
);
624 EXPORT_SYMBOL(lprocfs_stats_collect
);
627 * Append a space separated list of current set flags to str.
629 #define flag2str(flag, first) \
631 if (imp->imp_##flag) \
632 seq_printf(m, "%s" #flag, first ? "" : ", "); \
634 static int obd_import_flags2str(struct obd_import
*imp
, struct seq_file
*m
)
638 if (imp
->imp_obd
->obd_no_recov
) {
639 seq_printf(m
, "no_recov");
643 flag2str(invalid
, first
);
645 flag2str(deactive
, first
);
646 flag2str(replayable
, first
);
647 flag2str(pingable
, first
);
653 static void obd_connect_seq_flags2str(struct seq_file
*m
, __u64 flags
, char *sep
)
659 for (i
= 0; obd_connect_names
[i
]; i
++, mask
<<= 1) {
661 seq_printf(m
, "%s%s",
662 first
? sep
: "", obd_connect_names
[i
]);
666 if (flags
& ~(mask
- 1))
667 seq_printf(m
, "%sunknown flags %#llx",
668 first
? sep
: "", flags
& ~(mask
- 1));
671 int lprocfs_rd_import(struct seq_file
*m
, void *data
)
673 char nidstr
[LNET_NIDSTR_SIZE
];
674 struct lprocfs_counter ret
;
675 struct lprocfs_counter_header
*header
;
676 struct obd_device
*obd
= data
;
677 struct obd_import
*imp
;
678 struct obd_import_conn
*conn
;
679 struct obd_connect_data
*ocd
;
686 rc
= lprocfs_climp_check(obd
);
690 imp
= obd
->u
.cli
.cl_import
;
691 ocd
= &imp
->imp_connect_data
;
693 seq_printf(m
, "import:\n"
698 " connect_flags: [ ",
701 ptlrpc_import_state_name(imp
->imp_state
),
702 imp
->imp_connect_data
.ocd_instance
);
703 obd_connect_seq_flags2str(m
, imp
->imp_connect_data
.ocd_connect_flags
,
705 seq_printf(m
, " ]\n");
706 obd_connect_data_seqprint(m
, ocd
);
707 seq_printf(m
, " import_flags: [ ");
708 obd_import_flags2str(imp
, m
);
713 " failover_nids: [ ");
714 spin_lock(&imp
->imp_lock
);
716 list_for_each_entry(conn
, &imp
->imp_conn_list
, oic_item
) {
717 libcfs_nid2str_r(conn
->oic_conn
->c_peer
.nid
,
718 nidstr
, sizeof(nidstr
));
719 seq_printf(m
, "%s%s", j
? ", " : "", nidstr
);
722 if (imp
->imp_connection
)
723 libcfs_nid2str_r(imp
->imp_connection
->c_peer
.nid
,
724 nidstr
, sizeof(nidstr
));
726 strncpy(nidstr
, "<none>", sizeof(nidstr
));
729 " current_connection: %s\n"
730 " connection_attempts: %u\n"
732 " in-progress_invalidations: %u\n",
736 atomic_read(&imp
->imp_inval_count
));
737 spin_unlock(&imp
->imp_lock
);
739 if (!obd
->obd_svc_stats
)
742 header
= &obd
->obd_svc_stats
->ls_cnt_header
[PTLRPC_REQWAIT_CNTR
];
743 lprocfs_stats_collect(obd
->obd_svc_stats
, PTLRPC_REQWAIT_CNTR
, &ret
);
744 if (ret
.lc_count
!= 0) {
745 /* first argument to do_div MUST be __u64 */
746 __u64 sum
= ret
.lc_sum
;
748 do_div(sum
, ret
.lc_count
);
756 " unregistering: %u\n"
758 " avg_waittime: %llu %s\n",
759 atomic_read(&imp
->imp_inflight
),
760 atomic_read(&imp
->imp_unregistering
),
761 atomic_read(&imp
->imp_timeouts
),
762 ret
.lc_sum
, header
->lc_units
);
765 for (j
= 0; j
< IMP_AT_MAX_PORTALS
; j
++) {
766 if (imp
->imp_at
.iat_portal
[j
] == 0)
768 k
= max_t(unsigned int, k
,
769 at_get(&imp
->imp_at
.iat_service_estimate
[j
]));
772 " service_estimates:\n"
773 " services: %u sec\n"
774 " network: %u sec\n",
776 at_get(&imp
->imp_at
.iat_net_latency
));
780 " last_replay: %llu\n"
781 " peer_committed: %llu\n"
782 " last_checked: %llu\n",
783 imp
->imp_last_replay_transno
,
784 imp
->imp_peer_committed_transno
,
785 imp
->imp_last_transno_checked
);
788 for (rw
= 0; rw
<= 1; rw
++) {
789 lprocfs_stats_collect(obd
->obd_svc_stats
,
790 PTLRPC_LAST_CNTR
+ BRW_READ_BYTES
+ rw
,
792 if (ret
.lc_sum
> 0 && ret
.lc_count
> 0) {
793 /* first argument to do_div MUST be __u64 */
794 __u64 sum
= ret
.lc_sum
;
796 do_div(sum
, ret
.lc_count
);
799 " %s_data_averages:\n"
800 " bytes_per_rpc: %llu\n",
801 rw
? "write" : "read",
805 j
= opcode_offset(OST_READ
+ rw
) + EXTRA_MAX_OPCODES
;
806 header
= &obd
->obd_svc_stats
->ls_cnt_header
[j
];
807 lprocfs_stats_collect(obd
->obd_svc_stats
, j
, &ret
);
808 if (ret
.lc_sum
> 0 && ret
.lc_count
!= 0) {
809 /* first argument to do_div MUST be __u64 */
810 __u64 sum
= ret
.lc_sum
;
812 do_div(sum
, ret
.lc_count
);
815 " %s_per_rpc: %llu\n",
816 header
->lc_units
, ret
.lc_sum
);
820 " MB_per_sec: %u.%.02u\n",
821 k
/ j
, (100 * k
/ j
) % 100);
826 up_read(&obd
->u
.cli
.cl_sem
);
829 EXPORT_SYMBOL(lprocfs_rd_import
);
831 int lprocfs_rd_state(struct seq_file
*m
, void *data
)
833 struct obd_device
*obd
= data
;
834 struct obd_import
*imp
;
838 rc
= lprocfs_climp_check(obd
);
842 imp
= obd
->u
.cli
.cl_import
;
844 seq_printf(m
, "current_state: %s\n",
845 ptlrpc_import_state_name(imp
->imp_state
));
846 seq_printf(m
, "state_history:\n");
847 k
= imp
->imp_state_hist_idx
;
848 for (j
= 0; j
< IMP_STATE_HIST_LEN
; j
++) {
849 struct import_state_hist
*ish
=
850 &imp
->imp_state_hist
[(k
+ j
) % IMP_STATE_HIST_LEN
];
851 if (ish
->ish_state
== 0)
853 seq_printf(m
, " - [ %lld, %s ]\n", (s64
)ish
->ish_time
,
854 ptlrpc_import_state_name(ish
->ish_state
));
857 up_read(&obd
->u
.cli
.cl_sem
);
860 EXPORT_SYMBOL(lprocfs_rd_state
);
862 int lprocfs_at_hist_helper(struct seq_file
*m
, struct adaptive_timeout
*at
)
866 for (i
= 0; i
< AT_BINS
; i
++)
867 seq_printf(m
, "%3u ", at
->at_hist
[i
]);
871 EXPORT_SYMBOL(lprocfs_at_hist_helper
);
873 /* See also ptlrpc_lprocfs_rd_timeouts */
874 int lprocfs_rd_timeouts(struct seq_file
*m
, void *data
)
876 struct obd_device
*obd
= data
;
877 struct obd_import
*imp
;
878 unsigned int cur
, worst
;
879 time64_t now
, worstt
;
884 rc
= lprocfs_climp_check(obd
);
888 imp
= obd
->u
.cli
.cl_import
;
890 now
= ktime_get_real_seconds();
892 /* Some network health info for kicks */
893 s2dhms(&ts
, now
- imp
->imp_last_reply_time
);
894 seq_printf(m
, "%-10s : %lld, " DHMS_FMT
" ago\n",
895 "last reply", (s64
)imp
->imp_last_reply_time
, DHMS_VARS(&ts
));
897 cur
= at_get(&imp
->imp_at
.iat_net_latency
);
898 worst
= imp
->imp_at
.iat_net_latency
.at_worst_ever
;
899 worstt
= imp
->imp_at
.iat_net_latency
.at_worst_time
;
900 s2dhms(&ts
, now
- worstt
);
901 seq_printf(m
, "%-10s : cur %3u worst %3u (at %lld, " DHMS_FMT
" ago) ",
902 "network", cur
, worst
, (s64
)worstt
, DHMS_VARS(&ts
));
903 lprocfs_at_hist_helper(m
, &imp
->imp_at
.iat_net_latency
);
905 for (i
= 0; i
< IMP_AT_MAX_PORTALS
; i
++) {
906 if (imp
->imp_at
.iat_portal
[i
] == 0)
908 cur
= at_get(&imp
->imp_at
.iat_service_estimate
[i
]);
909 worst
= imp
->imp_at
.iat_service_estimate
[i
].at_worst_ever
;
910 worstt
= imp
->imp_at
.iat_service_estimate
[i
].at_worst_time
;
911 s2dhms(&ts
, now
- worstt
);
912 seq_printf(m
, "portal %-2d : cur %3u worst %3u (at %lld, "
913 DHMS_FMT
" ago) ", imp
->imp_at
.iat_portal
[i
],
914 cur
, worst
, (s64
)worstt
, DHMS_VARS(&ts
));
915 lprocfs_at_hist_helper(m
, &imp
->imp_at
.iat_service_estimate
[i
]);
918 up_read(&obd
->u
.cli
.cl_sem
);
921 EXPORT_SYMBOL(lprocfs_rd_timeouts
);
923 int lprocfs_rd_connect_flags(struct seq_file
*m
, void *data
)
925 struct obd_device
*obd
= data
;
929 rc
= lprocfs_climp_check(obd
);
933 flags
= obd
->u
.cli
.cl_import
->imp_connect_data
.ocd_connect_flags
;
934 seq_printf(m
, "flags=%#llx\n", flags
);
935 obd_connect_seq_flags2str(m
, flags
, "\n");
937 up_read(&obd
->u
.cli
.cl_sem
);
940 EXPORT_SYMBOL(lprocfs_rd_connect_flags
);
942 static struct attribute
*obd_def_attrs
[] = {
943 &lustre_attr_blocksize
.attr
,
944 &lustre_attr_kbytestotal
.attr
,
945 &lustre_attr_kbytesfree
.attr
,
946 &lustre_attr_kbytesavail
.attr
,
947 &lustre_attr_filestotal
.attr
,
948 &lustre_attr_filesfree
.attr
,
949 &lustre_attr_uuid
.attr
,
953 static void obd_sysfs_release(struct kobject
*kobj
)
955 struct obd_device
*obd
= container_of(kobj
, struct obd_device
,
958 complete(&obd
->obd_kobj_unregister
);
961 static struct kobj_type obd_ktype
= {
962 .default_attrs
= obd_def_attrs
,
963 .sysfs_ops
= &lustre_sysfs_ops
,
964 .release
= obd_sysfs_release
,
967 int lprocfs_obd_setup(struct obd_device
*obd
, struct lprocfs_vars
*list
,
968 struct attribute_group
*attrs
)
972 init_completion(&obd
->obd_kobj_unregister
);
973 rc
= kobject_init_and_add(&obd
->obd_kobj
, &obd_ktype
,
974 obd
->obd_type
->typ_kobj
,
975 "%s", obd
->obd_name
);
980 rc
= sysfs_create_group(&obd
->obd_kobj
, attrs
);
982 kobject_put(&obd
->obd_kobj
);
987 obd
->obd_debugfs_entry
= ldebugfs_register(obd
->obd_name
,
988 obd
->obd_type
->typ_debugfs_entry
,
990 if (IS_ERR_OR_NULL(obd
->obd_debugfs_entry
)) {
991 rc
= obd
->obd_debugfs_entry
? PTR_ERR(obd
->obd_debugfs_entry
)
993 CERROR("error %d setting up lprocfs for %s\n",
995 obd
->obd_debugfs_entry
= NULL
;
1000 EXPORT_SYMBOL_GPL(lprocfs_obd_setup
);
1002 int lprocfs_obd_cleanup(struct obd_device
*obd
)
1007 if (!IS_ERR_OR_NULL(obd
->obd_debugfs_entry
))
1008 ldebugfs_remove(&obd
->obd_debugfs_entry
);
1010 kobject_put(&obd
->obd_kobj
);
1011 wait_for_completion(&obd
->obd_kobj_unregister
);
1015 EXPORT_SYMBOL_GPL(lprocfs_obd_cleanup
);
1017 int lprocfs_stats_alloc_one(struct lprocfs_stats
*stats
, unsigned int cpuid
)
1019 struct lprocfs_counter
*cntr
;
1020 unsigned int percpusize
;
1022 unsigned long flags
= 0;
1025 LASSERT(!stats
->ls_percpu
[cpuid
]);
1026 LASSERT((stats
->ls_flags
& LPROCFS_STATS_FLAG_NOPERCPU
) == 0);
1028 percpusize
= lprocfs_stats_counter_size(stats
);
1029 LIBCFS_ALLOC_ATOMIC(stats
->ls_percpu
[cpuid
], percpusize
);
1030 if (stats
->ls_percpu
[cpuid
]) {
1032 if (unlikely(stats
->ls_biggest_alloc_num
<= cpuid
)) {
1033 if (stats
->ls_flags
& LPROCFS_STATS_FLAG_IRQ_SAFE
)
1034 spin_lock_irqsave(&stats
->ls_lock
, flags
);
1036 spin_lock(&stats
->ls_lock
);
1037 if (stats
->ls_biggest_alloc_num
<= cpuid
)
1038 stats
->ls_biggest_alloc_num
= cpuid
+ 1;
1039 if (stats
->ls_flags
& LPROCFS_STATS_FLAG_IRQ_SAFE
)
1040 spin_unlock_irqrestore(&stats
->ls_lock
, flags
);
1042 spin_unlock(&stats
->ls_lock
);
1044 /* initialize the ls_percpu[cpuid] non-zero counter */
1045 for (i
= 0; i
< stats
->ls_num
; ++i
) {
1046 cntr
= lprocfs_stats_counter_get(stats
, cpuid
, i
);
1047 cntr
->lc_min
= LC_MIN_INIT
;
1052 EXPORT_SYMBOL(lprocfs_stats_alloc_one
);
1054 struct lprocfs_stats
*lprocfs_alloc_stats(unsigned int num
,
1055 enum lprocfs_stats_flags flags
)
1057 struct lprocfs_stats
*stats
;
1058 unsigned int num_entry
;
1059 unsigned int percpusize
= 0;
1065 if (lprocfs_no_percpu_stats
!= 0)
1066 flags
|= LPROCFS_STATS_FLAG_NOPERCPU
;
1068 if (flags
& LPROCFS_STATS_FLAG_NOPERCPU
)
1071 num_entry
= num_possible_cpus();
1073 /* alloc percpu pointers for all possible cpu slots */
1074 LIBCFS_ALLOC(stats
, offsetof(typeof(*stats
), ls_percpu
[num_entry
]));
1078 stats
->ls_num
= num
;
1079 stats
->ls_flags
= flags
;
1080 spin_lock_init(&stats
->ls_lock
);
1082 /* alloc num of counter headers */
1083 LIBCFS_ALLOC(stats
->ls_cnt_header
,
1084 stats
->ls_num
* sizeof(struct lprocfs_counter_header
));
1085 if (!stats
->ls_cnt_header
)
1088 if ((flags
& LPROCFS_STATS_FLAG_NOPERCPU
) != 0) {
1089 /* contains only one set counters */
1090 percpusize
= lprocfs_stats_counter_size(stats
);
1091 LIBCFS_ALLOC_ATOMIC(stats
->ls_percpu
[0], percpusize
);
1092 if (!stats
->ls_percpu
[0])
1094 stats
->ls_biggest_alloc_num
= 1;
1095 } else if ((flags
& LPROCFS_STATS_FLAG_IRQ_SAFE
) != 0) {
1096 /* alloc all percpu data */
1097 for (i
= 0; i
< num_entry
; ++i
)
1098 if (lprocfs_stats_alloc_one(stats
, i
) < 0)
1105 lprocfs_free_stats(&stats
);
1108 EXPORT_SYMBOL(lprocfs_alloc_stats
);
1110 void lprocfs_free_stats(struct lprocfs_stats
**statsh
)
1112 struct lprocfs_stats
*stats
= *statsh
;
1113 unsigned int num_entry
;
1114 unsigned int percpusize
;
1117 if (!stats
|| stats
->ls_num
== 0)
1121 if (stats
->ls_flags
& LPROCFS_STATS_FLAG_NOPERCPU
)
1124 num_entry
= num_possible_cpus();
1126 percpusize
= lprocfs_stats_counter_size(stats
);
1127 for (i
= 0; i
< num_entry
; i
++)
1128 if (stats
->ls_percpu
[i
])
1129 LIBCFS_FREE(stats
->ls_percpu
[i
], percpusize
);
1130 if (stats
->ls_cnt_header
)
1131 LIBCFS_FREE(stats
->ls_cnt_header
, stats
->ls_num
*
1132 sizeof(struct lprocfs_counter_header
));
1133 LIBCFS_FREE(stats
, offsetof(typeof(*stats
), ls_percpu
[num_entry
]));
1135 EXPORT_SYMBOL(lprocfs_free_stats
);
1137 void lprocfs_clear_stats(struct lprocfs_stats
*stats
)
1139 struct lprocfs_counter
*percpu_cntr
;
1142 unsigned int num_entry
;
1143 unsigned long flags
= 0;
1145 num_entry
= lprocfs_stats_lock(stats
, LPROCFS_GET_NUM_CPU
, &flags
);
1147 for (i
= 0; i
< num_entry
; i
++) {
1148 if (!stats
->ls_percpu
[i
])
1150 for (j
= 0; j
< stats
->ls_num
; j
++) {
1151 percpu_cntr
= lprocfs_stats_counter_get(stats
, i
, j
);
1152 percpu_cntr
->lc_count
= 0;
1153 percpu_cntr
->lc_min
= LC_MIN_INIT
;
1154 percpu_cntr
->lc_max
= 0;
1155 percpu_cntr
->lc_sumsquare
= 0;
1156 percpu_cntr
->lc_sum
= 0;
1157 if (stats
->ls_flags
& LPROCFS_STATS_FLAG_IRQ_SAFE
)
1158 percpu_cntr
->lc_sum_irq
= 0;
1162 lprocfs_stats_unlock(stats
, LPROCFS_GET_NUM_CPU
, &flags
);
1164 EXPORT_SYMBOL(lprocfs_clear_stats
);
1166 static ssize_t
lprocfs_stats_seq_write(struct file
*file
,
1167 const char __user
*buf
,
1168 size_t len
, loff_t
*off
)
1170 struct seq_file
*seq
= file
->private_data
;
1171 struct lprocfs_stats
*stats
= seq
->private;
1173 lprocfs_clear_stats(stats
);
1178 static void *lprocfs_stats_seq_start(struct seq_file
*p
, loff_t
*pos
)
1180 struct lprocfs_stats
*stats
= p
->private;
1182 return (*pos
< stats
->ls_num
) ? pos
: NULL
;
1185 static void lprocfs_stats_seq_stop(struct seq_file
*p
, void *v
)
1189 static void *lprocfs_stats_seq_next(struct seq_file
*p
, void *v
, loff_t
*pos
)
1192 return lprocfs_stats_seq_start(p
, pos
);
1195 /* seq file export of one lprocfs counter */
1196 static int lprocfs_stats_seq_show(struct seq_file
*p
, void *v
)
1198 struct lprocfs_stats
*stats
= p
->private;
1199 struct lprocfs_counter_header
*hdr
;
1200 struct lprocfs_counter ctr
;
1201 int idx
= *(loff_t
*)v
;
1204 struct timespec64 now
;
1206 ktime_get_real_ts64(&now
);
1207 seq_printf(p
, "%-25s %llu.%9lu secs.usecs\n",
1209 (s64
)now
.tv_sec
, (unsigned long)now
.tv_nsec
);
1212 hdr
= &stats
->ls_cnt_header
[idx
];
1213 lprocfs_stats_collect(stats
, idx
, &ctr
);
1215 if (ctr
.lc_count
!= 0) {
1216 seq_printf(p
, "%-25s %lld samples [%s]",
1217 hdr
->lc_name
, ctr
.lc_count
, hdr
->lc_units
);
1219 if ((hdr
->lc_config
& LPROCFS_CNTR_AVGMINMAX
) &&
1220 (ctr
.lc_count
> 0)) {
1221 seq_printf(p
, " %lld %lld %lld",
1222 ctr
.lc_min
, ctr
.lc_max
, ctr
.lc_sum
);
1223 if (hdr
->lc_config
& LPROCFS_CNTR_STDDEV
)
1224 seq_printf(p
, " %lld", ctr
.lc_sumsquare
);
1232 static const struct seq_operations lprocfs_stats_seq_sops
= {
1233 .start
= lprocfs_stats_seq_start
,
1234 .stop
= lprocfs_stats_seq_stop
,
1235 .next
= lprocfs_stats_seq_next
,
1236 .show
= lprocfs_stats_seq_show
,
1239 static int lprocfs_stats_seq_open(struct inode
*inode
, struct file
*file
)
1241 struct seq_file
*seq
;
1244 rc
= seq_open(file
, &lprocfs_stats_seq_sops
);
1248 seq
= file
->private_data
;
1249 seq
->private = inode
->i_private
;
1254 static const struct file_operations lprocfs_stats_seq_fops
= {
1255 .owner
= THIS_MODULE
,
1256 .open
= lprocfs_stats_seq_open
,
1258 .write
= lprocfs_stats_seq_write
,
1259 .llseek
= seq_lseek
,
1260 .release
= lprocfs_seq_release
,
1263 int ldebugfs_register_stats(struct dentry
*parent
, const char *name
,
1264 struct lprocfs_stats
*stats
)
1266 struct dentry
*entry
;
1268 LASSERT(!IS_ERR_OR_NULL(parent
));
1270 entry
= debugfs_create_file(name
, 0644, parent
, stats
,
1271 &lprocfs_stats_seq_fops
);
1272 if (IS_ERR_OR_NULL(entry
))
1273 return entry
? PTR_ERR(entry
) : -ENOMEM
;
1277 EXPORT_SYMBOL_GPL(ldebugfs_register_stats
);
1279 void lprocfs_counter_init(struct lprocfs_stats
*stats
, int index
,
1280 unsigned conf
, const char *name
, const char *units
)
1282 struct lprocfs_counter_header
*header
;
1283 struct lprocfs_counter
*percpu_cntr
;
1284 unsigned long flags
= 0;
1286 unsigned int num_cpu
;
1288 header
= &stats
->ls_cnt_header
[index
];
1289 LASSERTF(header
, "Failed to allocate stats header:[%d]%s/%s\n",
1290 index
, name
, units
);
1292 header
->lc_config
= conf
;
1293 header
->lc_name
= name
;
1294 header
->lc_units
= units
;
1296 num_cpu
= lprocfs_stats_lock(stats
, LPROCFS_GET_NUM_CPU
, &flags
);
1297 for (i
= 0; i
< num_cpu
; ++i
) {
1298 if (!stats
->ls_percpu
[i
])
1300 percpu_cntr
= lprocfs_stats_counter_get(stats
, i
, index
);
1301 percpu_cntr
->lc_count
= 0;
1302 percpu_cntr
->lc_min
= LC_MIN_INIT
;
1303 percpu_cntr
->lc_max
= 0;
1304 percpu_cntr
->lc_sumsquare
= 0;
1305 percpu_cntr
->lc_sum
= 0;
1306 if ((stats
->ls_flags
& LPROCFS_STATS_FLAG_IRQ_SAFE
) != 0)
1307 percpu_cntr
->lc_sum_irq
= 0;
1309 lprocfs_stats_unlock(stats
, LPROCFS_GET_NUM_CPU
, &flags
);
1311 EXPORT_SYMBOL(lprocfs_counter_init
);
1313 int lprocfs_exp_cleanup(struct obd_export
*exp
)
1317 EXPORT_SYMBOL(lprocfs_exp_cleanup
);
1319 __s64
lprocfs_read_helper(struct lprocfs_counter
*lc
,
1320 struct lprocfs_counter_header
*header
,
1321 enum lprocfs_stats_flags flags
,
1322 enum lprocfs_fields_flags field
)
1330 case LPROCFS_FIELDS_FLAGS_CONFIG
:
1331 ret
= header
->lc_config
;
1333 case LPROCFS_FIELDS_FLAGS_SUM
:
1335 if ((flags
& LPROCFS_STATS_FLAG_IRQ_SAFE
) != 0)
1336 ret
+= lc
->lc_sum_irq
;
1338 case LPROCFS_FIELDS_FLAGS_MIN
:
1341 case LPROCFS_FIELDS_FLAGS_MAX
:
1344 case LPROCFS_FIELDS_FLAGS_AVG
:
1345 ret
= (lc
->lc_max
- lc
->lc_min
) / 2;
1347 case LPROCFS_FIELDS_FLAGS_SUMSQUARE
:
1348 ret
= lc
->lc_sumsquare
;
1350 case LPROCFS_FIELDS_FLAGS_COUNT
:
1359 EXPORT_SYMBOL(lprocfs_read_helper
);
1361 int lprocfs_write_helper(const char __user
*buffer
, unsigned long count
,
1364 return lprocfs_write_frac_helper(buffer
, count
, val
, 1);
1366 EXPORT_SYMBOL(lprocfs_write_helper
);
1368 int lprocfs_write_u64_helper(const char __user
*buffer
, unsigned long count
,
1371 return lprocfs_write_frac_u64_helper(buffer
, count
, val
, 1);
1373 EXPORT_SYMBOL(lprocfs_write_u64_helper
);
1375 int lprocfs_write_frac_u64_helper(const char __user
*buffer
,
1376 unsigned long count
, __u64
*val
, int mult
)
1378 char kernbuf
[22], *end
, *pbuf
;
1379 __u64 whole
, frac
= 0, units
;
1380 unsigned frac_d
= 1;
1383 if (count
> (sizeof(kernbuf
) - 1))
1386 if (copy_from_user(kernbuf
, buffer
, count
))
1389 kernbuf
[count
] = '\0';
1396 whole
= simple_strtoull(pbuf
, &end
, 10);
1405 /* need to limit frac_d to a __u32 */
1406 if (strlen(pbuf
) > 10)
1409 frac
= simple_strtoull(pbuf
, &end
, 10);
1410 /* count decimal places */
1411 for (i
= 0; i
< (end
- pbuf
); i
++)
1417 switch (tolower(*end
)) {
1430 /* Specified units override the multiplier */
1435 do_div(frac
, frac_d
);
1436 *val
= sign
* (whole
* mult
+ frac
);
1439 EXPORT_SYMBOL(lprocfs_write_frac_u64_helper
);
1441 static char *lprocfs_strnstr(const char *s1
, const char *s2
, size_t len
)
1450 if (!memcmp(s1
, s2
, l2
))
1458 * Find the string \a name in the input \a buffer, and return a pointer to the
1459 * value immediately following \a name, reducing \a count appropriately.
1460 * If \a name is not found the original \a buffer is returned.
1462 char *lprocfs_find_named_value(const char *buffer
, const char *name
,
1466 size_t buflen
= *count
;
1468 /* there is no strnstr() in rhel5 and ubuntu kernels */
1469 val
= lprocfs_strnstr(buffer
, name
, buflen
);
1471 return (char *)buffer
;
1473 val
+= strlen(name
); /* skip prefix */
1474 while (val
< buffer
+ buflen
&& isspace(*val
)) /* skip separator */
1478 while (val
< buffer
+ buflen
&& isalnum(*val
)) {
1483 return val
- *count
;
1485 EXPORT_SYMBOL(lprocfs_find_named_value
);
1487 int ldebugfs_seq_create(struct dentry
*parent
, const char *name
,
1488 umode_t mode
, const struct file_operations
*seq_fops
,
1491 struct dentry
*entry
;
1493 /* Disallow secretly (un)writable entries. */
1494 LASSERT((seq_fops
->write
== NULL
) == ((mode
& 0222) == 0));
1496 entry
= debugfs_create_file(name
, mode
, parent
, data
, seq_fops
);
1497 if (IS_ERR_OR_NULL(entry
))
1498 return entry
? PTR_ERR(entry
) : -ENOMEM
;
1502 EXPORT_SYMBOL_GPL(ldebugfs_seq_create
);
1504 int ldebugfs_obd_seq_create(struct obd_device
*dev
,
1507 const struct file_operations
*seq_fops
,
1510 return ldebugfs_seq_create(dev
->obd_debugfs_entry
, name
,
1511 mode
, seq_fops
, data
);
1513 EXPORT_SYMBOL_GPL(ldebugfs_obd_seq_create
);
1515 void lprocfs_oh_tally(struct obd_histogram
*oh
, unsigned int value
)
1517 if (value
>= OBD_HIST_MAX
)
1518 value
= OBD_HIST_MAX
- 1;
1520 spin_lock(&oh
->oh_lock
);
1521 oh
->oh_buckets
[value
]++;
1522 spin_unlock(&oh
->oh_lock
);
1524 EXPORT_SYMBOL(lprocfs_oh_tally
);
1526 void lprocfs_oh_tally_log2(struct obd_histogram
*oh
, unsigned int value
)
1528 unsigned int val
= 0;
1530 if (likely(value
!= 0))
1531 val
= min(fls(value
- 1), OBD_HIST_MAX
);
1533 lprocfs_oh_tally(oh
, val
);
1535 EXPORT_SYMBOL(lprocfs_oh_tally_log2
);
1537 unsigned long lprocfs_oh_sum(struct obd_histogram
*oh
)
1539 unsigned long ret
= 0;
1542 for (i
= 0; i
< OBD_HIST_MAX
; i
++)
1543 ret
+= oh
->oh_buckets
[i
];
1546 EXPORT_SYMBOL(lprocfs_oh_sum
);
1548 void lprocfs_oh_clear(struct obd_histogram
*oh
)
1550 spin_lock(&oh
->oh_lock
);
1551 memset(oh
->oh_buckets
, 0, sizeof(oh
->oh_buckets
));
1552 spin_unlock(&oh
->oh_lock
);
1554 EXPORT_SYMBOL(lprocfs_oh_clear
);
1556 int lprocfs_wr_root_squash(const char __user
*buffer
, unsigned long count
,
1557 struct root_squash_info
*squash
, char *name
)
1559 char kernbuf
[64], *tmp
, *errmsg
;
1560 unsigned long uid
, gid
;
1563 if (count
>= sizeof(kernbuf
)) {
1564 errmsg
= "string too long";
1566 goto failed_noprint
;
1568 if (copy_from_user(kernbuf
, buffer
, count
)) {
1569 errmsg
= "bad address";
1571 goto failed_noprint
;
1573 kernbuf
[count
] = '\0';
1575 /* look for uid gid separator */
1576 tmp
= strchr(kernbuf
, ':');
1578 errmsg
= "needs uid:gid format";
1586 if (kstrtoul(kernbuf
, 0, &uid
) != 0) {
1592 if (kstrtoul(tmp
, 0, &gid
) != 0) {
1598 squash
->rsi_uid
= uid
;
1599 squash
->rsi_gid
= gid
;
1601 LCONSOLE_INFO("%s: root_squash is set to %u:%u\n",
1602 name
, squash
->rsi_uid
, squash
->rsi_gid
);
1610 CWARN("%s: failed to set root_squash to \"%s\", %s, rc = %d\n",
1611 name
, kernbuf
, errmsg
, rc
);
1614 CWARN("%s: failed to set root_squash due to %s, rc = %d\n",
1618 EXPORT_SYMBOL(lprocfs_wr_root_squash
);
1620 int lprocfs_wr_nosquash_nids(const char __user
*buffer
, unsigned long count
,
1621 struct root_squash_info
*squash
, char *name
)
1623 char *kernbuf
= NULL
, *errmsg
;
1624 struct list_head tmp
;
1629 errmsg
= "string too long";
1634 kernbuf
= kzalloc(count
+ 1, GFP_NOFS
);
1636 errmsg
= "no memory";
1641 if (copy_from_user(kernbuf
, buffer
, count
)) {
1642 errmsg
= "bad address";
1646 kernbuf
[count
] = '\0';
1648 if (count
> 0 && kernbuf
[count
- 1] == '\n')
1651 if ((len
== 4 && !strncmp(kernbuf
, "NONE", len
)) ||
1652 (len
== 5 && !strncmp(kernbuf
, "clear", len
))) {
1653 /* empty string is special case */
1654 down_write(&squash
->rsi_sem
);
1655 if (!list_empty(&squash
->rsi_nosquash_nids
))
1656 cfs_free_nidlist(&squash
->rsi_nosquash_nids
);
1657 up_write(&squash
->rsi_sem
);
1658 LCONSOLE_INFO("%s: nosquash_nids is cleared\n", name
);
1663 INIT_LIST_HEAD(&tmp
);
1664 if (cfs_parse_nidlist(kernbuf
, count
, &tmp
) <= 0) {
1665 errmsg
= "can't parse";
1669 LCONSOLE_INFO("%s: nosquash_nids set to %s\n",
1674 down_write(&squash
->rsi_sem
);
1675 if (!list_empty(&squash
->rsi_nosquash_nids
))
1676 cfs_free_nidlist(&squash
->rsi_nosquash_nids
);
1677 list_splice(&tmp
, &squash
->rsi_nosquash_nids
);
1678 up_write(&squash
->rsi_sem
);
1684 CWARN("%s: failed to set nosquash_nids to \"%s\", %s rc = %d\n",
1685 name
, kernbuf
, errmsg
, rc
);
1689 CWARN("%s: failed to set nosquash_nids due to %s rc = %d\n",
1694 EXPORT_SYMBOL(lprocfs_wr_nosquash_nids
);
1696 static ssize_t
lustre_attr_show(struct kobject
*kobj
,
1697 struct attribute
*attr
, char *buf
)
1699 struct lustre_attr
*a
= container_of(attr
, struct lustre_attr
, attr
);
1701 return a
->show
? a
->show(kobj
, attr
, buf
) : 0;
1704 static ssize_t
lustre_attr_store(struct kobject
*kobj
, struct attribute
*attr
,
1705 const char *buf
, size_t len
)
1707 struct lustre_attr
*a
= container_of(attr
, struct lustre_attr
, attr
);
1709 return a
->store
? a
->store(kobj
, attr
, buf
, len
) : len
;
1712 const struct sysfs_ops lustre_sysfs_ops
= {
1713 .show
= lustre_attr_show
,
1714 .store
= lustre_attr_store
,
1716 EXPORT_SYMBOL_GPL(lustre_sysfs_ops
);