1 use std::{
2 io::{Error, Result},
3 os::raw::c_void
4 };
5
6 #[allow(non_camel_case_types)]
7 #[allow(dead_code)]
8 mod ffi;
9
bintime_to_ns(bintime: &ffi::bintime) -> u6410 fn bintime_to_ns(bintime: &ffi::bintime) -> u64 {
11 (bintime.sec as u64).wrapping_mul(1_000_000_000)
12 .wrapping_add(bintime.frac / (1 << 30) / ((1 << 34) / 1_000_000_000))
13 }
14
15 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
16 pub struct PerRW {
17 pub read: u64,
18 pub write: u64,
19 }
20
21 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
22 pub struct PerRWC {
23 pub read: u64,
24 pub write: u64,
25 pub commit: u64,
26 }
27
28 /// Counts of every RPC processed
29 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
30 pub struct PerRPC {
31 pub access: u64,
32 pub backchannelctrl: u64,
33 pub bindconntosess: u64,
34 pub close: u64,
35 pub commit: u64,
36 pub create: u64,
37 pub createsess: u64,
38 pub delegpurge: u64,
39 pub delegreturn: u64,
40 pub destroyclid: u64,
41 pub destroysess: u64,
42 pub exchangeid: u64,
43 pub freestateid: u64,
44 pub fsinfo: u64,
45 pub fsstat: u64,
46 pub getattr: u64,
47 pub getdevinfo: u64,
48 pub getdevlist: u64,
49 pub getdirdeleg: u64,
50 pub getfh: u64,
51 pub layoutcommit: u64,
52 pub layoutget: u64,
53 pub layoutreturn: u64,
54 pub link: u64,
55 pub lock: u64,
56 pub lockt: u64,
57 pub locku: u64,
58 pub lookup: u64,
59 pub lookupp: u64,
60 pub mkdir: u64,
61 pub mknod: u64,
62 pub nverify: u64,
63 pub open: u64,
64 pub openattr: u64,
65 pub openconfirm: u64,
66 pub opendgrd: u64,
67 pub pathconf: u64,
68 pub putfh: u64,
69 pub putpubfh: u64,
70 pub putrootfh: u64,
71 pub read: u64,
72 pub readdir: u64,
73 pub readdirplus: u64,
74 pub readlink: u64,
75 pub reclaimcompl: u64,
76 pub rellckown: u64,
77 pub remove: u64,
78 pub rename: u64,
79 pub renew: u64,
80 pub restorefh: u64,
81 pub rmdir: u64,
82 pub savefh: u64,
83 pub secinfo: u64,
84 pub secinfononame: u64,
85 pub sequence: u64,
86 pub setattr: u64,
87 pub setclid: u64,
88 pub setclidcf: u64,
89 pub setssv: u64,
90 pub symlink: u64,
91 pub teststateid: u64,
92 pub v3create: u64,
93 pub verify: u64,
94 pub wantdeleg: u64,
95 pub write: u64,
96 }
97
98 /// Server cache statistics
99 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
100 pub struct ServerCache {
101 pub inprog: u64,
102 pub nonidem: u64,
103 pub misses: u64,
104 pub size: u64,
105 pub tcp_peak: u64
106 }
107
108 /// Miscellaneous NFS server stats
109 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
110 pub struct ServerMisc {
111 /// Number of currently connected NFS v4.0+ clients?
112 pub clients: u64,
113 pub delegs: u64,
114 pub lock_owner: u64,
115 pub locks: u64,
116 pub open_owner: u64,
117 pub opens: u64,
118 }
119
120 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
121 pub struct NfsStat {
122 /// Total time in ns that nfsd was busy with at least one operation.
123 /// May wrap!
124 pub busytime: u64,
125 /// Total bytes processed by each operation
126 pub bytes: PerRW,
127 /// Total number of operations that have completed since boot
128 pub donecnt: u64,
129 /// Cumulative duration spent processing each operation, in nanoseconds.
130 /// May wrap!
131 pub duration: PerRWC,
132 pub server_cache: ServerCache,
133 pub server_misc: ServerMisc,
134 /// Count of each RPC processed by the server
135 pub server_rpcs: PerRPC,
136 /// Total number of operations that have been started since boot
137 pub startcnt: u64,
138 }
139
collect() -> Result<NfsStat>140 pub fn collect() -> Result<NfsStat> {
141 let mut raw = ffi::nfsstatsv1::default();
142 raw.vers = ffi::NFSSTATS_V1 as i32;
143 let flag = ffi::NFSSVC_GETSTATS | ffi::NFSSVC_NEWSTRUCT;
144 let raw = unsafe {
145 let r = ffi::nfssvc(flag as i32, &mut raw as *mut _ as *mut c_void);
146 if r != 0 {
147 return Err(Error::last_os_error());
148 }
149 raw
150 };
151 let bytes = PerRW {
152 read: raw.srvbytes[ffi::NFSV4OP_READ as usize],
153 write: raw.srvbytes[ffi::NFSV4OP_WRITE as usize],
154 };
155 let duration = PerRWC {
156 read: bintime_to_ns(&raw.srvduration[ffi::NFSV4OP_READ as usize]),
157 write: bintime_to_ns(&raw.srvduration[ffi::NFSV4OP_WRITE as usize]),
158 commit: bintime_to_ns(&raw.srvduration[ffi::NFSV4OP_COMMIT as usize]),
159 };
160 let server_cache = ServerCache {
161 inprog: raw.srvcache_inproghits,
162 nonidem: raw.srvcache_nonidemdonehits,
163 misses: raw.srvcache_misses,
164 size: i64::max(0, i64::from(raw.srvcache_size)) as u64,
165 tcp_peak: raw.srvcache_tcppeak
166 };
167 let server_misc = ServerMisc {
168 clients: raw.srvclients,
169 delegs: raw.srvdelegates,
170 lock_owner: raw.srvlockowners,
171 locks: raw.srvlocks,
172 open_owner: raw.srvopenowners,
173 opens: raw.srvopens,
174 };
175 let server_rpcs = PerRPC {
176 access: raw.srvrpccnt[ffi::NFSV4OP_ACCESS as usize],
177 backchannelctrl: raw.srvrpccnt[ffi::NFSV4OP_BACKCHANNELCTL as usize],
178 bindconntosess: raw.srvrpccnt[ffi::NFSV4OP_BINDCONNTOSESS as usize],
179 close: raw.srvrpccnt[ffi::NFSV4OP_CLOSE as usize],
180 commit: raw.srvrpccnt[ffi::NFSV4OP_COMMIT as usize],
181 create: raw.srvrpccnt[ffi::NFSV4OP_CREATE as usize],
182 createsess: raw.srvrpccnt[ffi::NFSV4OP_CREATESESSION as usize],
183 delegpurge: raw.srvrpccnt[ffi::NFSV4OP_DELEGPURGE as usize],
184 delegreturn: raw.srvrpccnt[ffi::NFSV4OP_DELEGRETURN as usize],
185 destroyclid: raw.srvrpccnt[ffi::NFSV4OP_DESTROYCLIENTID as usize],
186 destroysess: raw.srvrpccnt[ffi::NFSV4OP_DESTROYSESSION as usize],
187 exchangeid: raw.srvrpccnt[ffi::NFSV4OP_EXCHANGEID as usize],
188 freestateid: raw.srvrpccnt[ffi::NFSV4OP_FREESTATEID as usize],
189 fsinfo: raw.srvrpccnt[ffi::NFSV4OP_FSINFO as usize],
190 fsstat: raw.srvrpccnt[ffi::NFSV4OP_FSSTAT as usize],
191 getattr: raw.srvrpccnt[ffi::NFSV4OP_GETATTR as usize],
192 getdevinfo: raw.srvrpccnt[ffi::NFSV4OP_GETDEVINFO as usize],
193 getdevlist: raw.srvrpccnt[ffi::NFSV4OP_GETDEVLIST as usize],
194 getdirdeleg: raw.srvrpccnt[ffi::NFSV4OP_GETDIRDELEG as usize],
195 getfh: raw.srvrpccnt[ffi::NFSV4OP_GETFH as usize],
196 layoutcommit: raw.srvrpccnt[ffi::NFSV4OP_LAYOUTCOMMIT as usize],
197 layoutget: raw.srvrpccnt[ffi::NFSV4OP_LAYOUTGET as usize],
198 layoutreturn: raw.srvrpccnt[ffi::NFSV4OP_LAYOUTRETURN as usize],
199 link: raw.srvrpccnt[ffi::NFSV4OP_LINK as usize],
200 lock: raw.srvrpccnt[ffi::NFSV4OP_LOCK as usize],
201 lockt: raw.srvrpccnt[ffi::NFSV4OP_LOCKT as usize],
202 locku: raw.srvrpccnt[ffi::NFSV4OP_LOCKU as usize],
203 lookup: raw.srvrpccnt[ffi::NFSV4OP_LOOKUP as usize],
204 lookupp: raw.srvrpccnt[ffi::NFSV4OP_LOOKUPP as usize],
205 mkdir: raw.srvrpccnt[ffi::NFSV4OP_MKDIR as usize],
206 mknod: raw.srvrpccnt[ffi::NFSV4OP_MKNOD as usize],
207 nverify: raw.srvrpccnt[ffi::NFSV4OP_NVERIFY as usize],
208 open: raw.srvrpccnt[ffi::NFSV4OP_OPEN as usize],
209 openattr: raw.srvrpccnt[ffi::NFSV4OP_OPENATTR as usize],
210 openconfirm: raw.srvrpccnt[ffi::NFSV4OP_OPENCONFIRM as usize],
211 opendgrd: raw.srvrpccnt[ffi::NFSV4OP_OPENDOWNGRADE as usize],
212 pathconf: raw.srvrpccnt[ffi::NFSV4OP_PATHCONF as usize],
213 putfh: raw.srvrpccnt[ffi::NFSV4OP_PUTFH as usize],
214 putpubfh: raw.srvrpccnt[ffi::NFSV4OP_PUTPUBFH as usize],
215 putrootfh: raw.srvrpccnt[ffi::NFSV4OP_PUTROOTFH as usize],
216 read: raw.srvrpccnt[ffi::NFSV4OP_READ as usize],
217 readdir: raw.srvrpccnt[ffi::NFSV4OP_READDIR as usize],
218 readdirplus: raw.srvrpccnt[ffi::NFSV4OP_READDIRPLUS as usize],
219 readlink: raw.srvrpccnt[ffi::NFSV4OP_READLINK as usize],
220 reclaimcompl: raw.srvrpccnt[ffi::NFSV4OP_RECLAIMCOMPL as usize],
221 rellckown: raw.srvrpccnt[ffi::NFSV4OP_RELEASELCKOWN as usize],
222 remove: raw.srvrpccnt[ffi::NFSV4OP_REMOVE as usize],
223 rename: raw.srvrpccnt[ffi::NFSV4OP_RENAME as usize],
224 renew: raw.srvrpccnt[ffi::NFSV4OP_RENEW as usize],
225 restorefh: raw.srvrpccnt[ffi::NFSV4OP_RESTOREFH as usize],
226 rmdir: raw.srvrpccnt[ffi::NFSV4OP_RMDIR as usize],
227 savefh: raw.srvrpccnt[ffi::NFSV4OP_SAVEFH as usize],
228 secinfo: raw.srvrpccnt[ffi::NFSV4OP_SECINFO as usize],
229 secinfononame: raw.srvrpccnt[ffi::NFSV4OP_SECINFONONAME as usize],
230 sequence: raw.srvrpccnt[ffi::NFSV4OP_SEQUENCE as usize],
231 setattr: raw.srvrpccnt[ffi::NFSV4OP_SETATTR as usize],
232 setclid: raw.srvrpccnt[ffi::NFSV4OP_SETCLIENTID as usize],
233 setclidcf: raw.srvrpccnt[ffi::NFSV4OP_SETCLIENTIDCFRM as usize],
234 setssv: raw.srvrpccnt[ffi::NFSV4OP_SETSSV as usize],
235 symlink: raw.srvrpccnt[ffi::NFSV4OP_SYMLINK as usize],
236 teststateid: raw.srvrpccnt[ffi::NFSV4OP_TESTSTATEID as usize],
237 v3create: raw.srvrpccnt[ffi::NFSV4OP_V3CREATE as usize],
238 verify: raw.srvrpccnt[ffi::NFSV4OP_VERIFY as usize],
239 wantdeleg: raw.srvrpccnt[ffi::NFSV4OP_WANTDELEG as usize],
240 write: raw.srvrpccnt[ffi::NFSV4OP_WRITE as usize],
241 };
242 Ok(NfsStat{
243 bytes,
244 duration,
245 startcnt: raw.srvstartcnt,
246 donecnt: raw.srvdonecnt,
247 busytime: bintime_to_ns(&raw.busytime),
248 server_cache,
249 server_misc,
250 server_rpcs
251 })
252 }
253