SOLARIS: provide cache manager stats via kstat
[openafs.git] / src / afs / SOLARIS / osi_kstat.c
1 /*
2  * Copyright (c) 2020 Sine Nomine Associates. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 /*
26  * Solaris kstat provider for OpenAFS.
27  */
28
29 #include <afsconfig.h>
30 #include "afs/param.h"
31
32 #include <sys/errno.h>
33 #include <sys/types.h>
34 #include <sys/kstat.h>
35
36 #include <rx/rx.h>
37
38 #include "afs/sysincludes.h"
39 #include "afsint.h"
40 #include "vldbint.h"
41 #include "afs/lock.h"
42 #include "afs/afs_stats.h"
43 #include "afs/afs.h"
44 #include "afs/afsincludes.h"
45 #include "afs/afs_prototypes.h"
46 #include "rx/rx_atomic.h"
47 #include "rx/rx_stats.h"
48
49 extern char *AFSVersion;
50
51 static kstat_t *afs_param_ksp;
52 static kstat_t *afs_cache_ksp;
53 static kstat_t *afs_rx_ksp;
54
55 static char cellname[AFSNAMEMAX];
56
57 /*
58  * Cache manager initialization parameters.
59  *
60  *      nChunkFiles     The number of disk files to allocate to the cache.
61  *      nStatCaches     The number of stat cache (vnode) entries to allocate.
62  *      nDataCaches     Number of dcache entries to allocate.
63  *      nVolumeCaches   Number of volume cache entries to allocate.
64  *      chunkSize       The size of file chunks.
65  *      cacheSize       The max number of 1 Kbyte blocks the cache may occupy.
66  *      setTime         Indicates clock setting is enabled.
67  *      memCache        Indicates memory-based cache is enabled.
68  */
69 struct afs_param_kstat {
70     kstat_named_t nChunkFiles;
71     kstat_named_t nStatCaches;
72     kstat_named_t nDataCaches;
73     kstat_named_t nVolumeCaches;
74     kstat_named_t chunkSize;
75     kstat_named_t cacheSize;
76     kstat_named_t setTime;
77     kstat_named_t memCache;
78 };
79 static struct afs_param_kstat param_kstats = {
80     .nChunkFiles = {"nChunkFiles", KSTAT_DATA_ULONG},
81     .nStatCaches = {"nStatCaches", KSTAT_DATA_ULONG},
82     .nDataCaches = {"nDataCaches", KSTAT_DATA_ULONG},
83     .nVolumeCaches = {"nVolumeCaches", KSTAT_DATA_ULONG},
84     .chunkSize = {"chunkSize", KSTAT_DATA_ULONG},
85     .cacheSize = {"cacheSize", KSTAT_DATA_ULONG},
86     .setTime = {"setTime", KSTAT_DATA_ULONG},
87     .memCache = {"memCache", KSTAT_DATA_ULONG},
88 };
89
90 /*
91  * Update the param kstat.
92  *
93  * All file chunks are the same size, so do not bother reporting the first
94  * chunk size and other chunk size as two different numbers.
95  */
96 static int
97 afs_param_ks_update(kstat_t * ksp, int rw)
98 {
99     struct afs_param_kstat *k = ksp->ks_data;
100     struct cm_initparams *s = &cm_initParams;
101
102     if (rw == KSTAT_WRITE) {
103         return EACCES;
104     }
105
106 #define KSET(ks) do { k->ks.value.ul = s->cmi_ ## ks; } while (0)
107 #define KSET2(ks,src) do { k->ks.value.ul = s->cmi_ ## src; } while (0)
108     KSET(nChunkFiles);
109     KSET(nStatCaches);
110     KSET(nDataCaches);
111     KSET(nVolumeCaches);
112     KSET2(chunkSize, firstChunkSize);  /* same as otherChunkSize */
113     KSET(cacheSize);
114     KSET(setTime);
115     KSET(memCache);
116 #undef KSET
117 #undef KSET2
118     return 0;
119 }
120
121 /*
122  * Cache statistics.
123  *
124  *      dlocalAccesses          Number of data accesses to files within cell.
125  *      vlocalAccesses          Number of stat accesses to files within cell.
126  *      dremoteAccesses         Number of data accesses to files outside of cell.
127  *      vremoteAccesses         Number of stat accesses to files outside of cell.
128  *      cacheNumEntries         Number of cache entries (should match cacheFilesTotal).
129  *      cacheBlocksTotal        Number of 1K blocks configured for cache.
130  *      cacheBlocksInUse        Number of cache blocks actively in use.
131  *      cacheMaxDirtyChunks     Max number of dirty cache chunks tolerated.
132  *      cacheCurrDirtyChunks    Current number of dirty cache chunks.
133  *      dcacheHits              Count of data files (daches) found in local cache.
134  *      vcacheHits              Count of stat entries (vcaches) found in local cache.
135  *      dcacheMisses            Count of data files NOT found in local cache.
136  *      vcacheMisses            Count of of stat entries NOT found in local cache.
137  *      cacheFlushes            Count of times files are flushed from cache.
138  *      cacheFilesReused        Number of cache files reused.
139  *      vcacheXAllocs           Count of additionally allocated vcaches.
140  *      dcacheXAllocs           Count of additionally allocated dcaches.
141  *      cacheFilesTotal         Number of cache files (chunks).
142  *      cacheFilesFree          Number of cache files (chunks) available.
143  *      cacheFilesInUse         Number of cache files (chunks) in use.
144  *      cacheTooFull            Number of times the cache size or number of files exceeded.
145  *      waitForDrain            Number of times waited for cache to drain.
146  *      cellname                Local cellname.
147  *      version                 OpenAFS version of the cache manager.
148  */
149 struct afs_cache_kstat {
150     kstat_named_t dlocalAccesses;
151     kstat_named_t vlocalAccesses;
152     kstat_named_t dremoteAccesses;
153     kstat_named_t vremoteAccesses;
154     kstat_named_t cacheNumEntries;
155     kstat_named_t cacheBlocksTotal;
156     kstat_named_t cacheBlocksInUse;
157     kstat_named_t cacheMaxDirtyChunks;
158     kstat_named_t cacheCurrDirtyChunks;
159     kstat_named_t dcacheHits;
160     kstat_named_t vcacheHits;
161     kstat_named_t dcacheMisses;
162     kstat_named_t vcacheMisses;
163     kstat_named_t cacheFlushes;
164     kstat_named_t cacheFilesReused;
165     kstat_named_t vcacheXAllocs;
166     kstat_named_t dcacheXAllocs;
167     kstat_named_t cacheFilesTotal;
168     kstat_named_t cacheFilesFree;
169     kstat_named_t cacheFilesInUse;
170     kstat_named_t cacheTooFull;
171     kstat_named_t waitForDrain;
172     kstat_named_t cellname;
173     kstat_named_t version;
174 };
175 static struct afs_cache_kstat cache_kstats = {
176     .dlocalAccesses = {"dlocalAccesses", KSTAT_DATA_ULONG},
177     .vlocalAccesses = {"vlocalAccesses", KSTAT_DATA_ULONG},
178     .dremoteAccesses = {"dremoteAccesses", KSTAT_DATA_ULONG},
179     .vremoteAccesses = {"vremoteAccesses", KSTAT_DATA_ULONG},
180     .cacheNumEntries = {"cacheNumEntries", KSTAT_DATA_ULONG},
181     .cacheBlocksTotal = {"cacheBlocksTotal", KSTAT_DATA_ULONG},
182     .cacheBlocksInUse = {"cacheBlocksInUse", KSTAT_DATA_ULONG},
183     .cacheMaxDirtyChunks = {"cacheMaxDirtyChunks", KSTAT_DATA_ULONG},
184     .cacheCurrDirtyChunks = {"cacheCurrDirtyChunks", KSTAT_DATA_ULONG},
185     .dcacheHits = {"dcacheHits", KSTAT_DATA_ULONG},
186     .vcacheHits = {"vcacheHits", KSTAT_DATA_ULONG},
187     .dcacheMisses = {"dcacheMisses", KSTAT_DATA_ULONG},
188     .vcacheMisses = {"vcacheMisses", KSTAT_DATA_ULONG},
189     .cacheFlushes = {"cacheFlushes", KSTAT_DATA_ULONG},
190     .cacheFilesReused = {"cacheFilesReused", KSTAT_DATA_ULONG},
191     .vcacheXAllocs = {"vcacheXAllocs", KSTAT_DATA_ULONG},
192     .dcacheXAllocs = {"dcacheXAllocs", KSTAT_DATA_ULONG},
193     .cacheFilesTotal = {"cacheFilesTotal", KSTAT_DATA_ULONG},
194     .cacheFilesFree = {"cacheFilesFree", KSTAT_DATA_ULONG},
195     .cacheFilesInUse = {"cacheFilesInUse", KSTAT_DATA_ULONG},
196     .cacheTooFull = {"cacheTooFull", KSTAT_DATA_ULONG},
197     .waitForDrain = {"waitForDrain", KSTAT_DATA_ULONG},
198     .cellname = {"cellname", KSTAT_DATA_STRING},
199     .version = {"version", KSTAT_DATA_STRING},
200 };
201
202 /*
203  * Update the cache kstat.
204  */
205 static int
206 afs_cache_ks_update(kstat_t * ksp, int rw)
207 {
208     struct afs_cache_kstat *k = ksp->ks_data;
209     struct afs_stats_CMPerf *s = &afs_stats_cmperf;
210
211     if (rw == KSTAT_WRITE) {
212         return EACCES;
213     }
214
215
216 #define KSET(ks) do {k->ks.value.ul = s->ks;} while (0)
217     KSET(dlocalAccesses);
218     KSET(vlocalAccesses);
219     KSET(dremoteAccesses);
220     KSET(vremoteAccesses);
221     KSET(cacheNumEntries);
222     KSET(cacheBlocksTotal);
223     KSET(cacheBlocksInUse);
224     /* cacheBlocksOrig is a duplicate of cacheSize, so not repeated here. */
225     KSET(cacheMaxDirtyChunks);
226     KSET(cacheCurrDirtyChunks);
227     KSET(dcacheHits);
228     KSET(vcacheHits);
229     KSET(dcacheMisses);
230     KSET(vcacheMisses);
231     KSET(cacheFlushes);
232     KSET(cacheFilesReused);
233     KSET(vcacheXAllocs);
234     KSET(dcacheXAllocs);
235 #undef KSET
236
237     /* The following stats not provided by xstat. */
238     k->cacheFilesTotal.value.ul = afs_cacheFiles;
239     k->cacheFilesFree.value.ul = afs_freeDCCount;
240     k->cacheFilesInUse.value.ul = afs_cacheFiles - afs_freeDCCount;
241     k->cacheTooFull.value.ul = afs_CacheTooFullCount;
242     k->waitForDrain.value.ul = afs_WaitForCacheDrainCount;
243     /* The following two values never change after OpenAFS init. */
244     kstat_named_setstr(&k->cellname, cellname);
245     kstat_named_setstr(&k->version, AFSVersion);
246
247     return 0;
248 }
249
250 /*
251  * Rx statistics.
252  *
253  *      packetRequests          Number of packet allocation requests.
254  *
255  *      receivePktAllocFailures Packet allocation failure, receive.
256  *      sendPktAllocFailures    Packet allocation failure, send.
257  *      specialPktAllocFailures Packet allocation failure, special.
258  *
259  *      socketGreedy            Whether SO_GREEDY succeeded.
260  *      bogusPacketOnRead       Number of inappropriately short packets received.
261  *      bogusHost               Host address from bogus packets.
262  *      noPacketOnRead          Number of read packets attempted when there was
263  *                               actually no packet to read off the wire.
264  *      noPacketBuffersOnRead   Number of dropped data packets due to lack of
265  *                               packet buffers.
266  *      selects                 Number of selects waiting for packet or timeout.
267  *      sendSelects             Number of selects forced when sending packet.
268  *
269  *      packetsRead_data        Packets read, data type.
270  *      packetsRead_ack         Packets read, ack type.
271  *      packetsRead_busy        Packets read, busy type.
272  *      packetsRead_abort       Packets read, abort type.
273  *      packetsRead_ackall      Packets read, ackall type.
274  *      packetsRead_challenge   Packets read, challenge type.
275  *      packetsRead_response    Packets read, response type.
276  *      packetsRead_debug       Packets read, debug type.
277  *      packetsRead_params      Packets read, params type.
278  *      packetsRead_unused0     Packets read, should be zero.
279  *      packetsRead_unused1     Packets read, should be zero.
280  *      packetsRead_unused2     Packets read, should be zero.
281  *      packetsRead_version     Packets read, version type.
282  *
283  *      dataPacketsRead         Number of unique data packets read off the wire.
284  *      ackPacketsRead          Number of ack packets read.
285  *      dupPacketsRead          Number of duplicate data packets read.
286  *      spuriousPacketsRead     Number of inappropriate data packets.
287  *
288  *      packetsSent_data        Packets sent, data type.
289  *      packetsSent_ack         Packets sent, ack type.
290  *      packetsSent_busy        Packets sent, busy type.
291  *      packetsSent_abort       Packets sent, abort type.
292  *      packetsSent_ackall      Packets sent, ackall type.
293  *      packetsSent_challenge   Packets sent, challenge type.
294  *      packetsSent_response    Packets sent, response type.
295  *      packetsSent_debug       Packets sent, debug type.
296  *      packetsSent_params      Packets sent, params type.
297  *      packetsSent_unused0     Packets sent, should be zero.
298  *      packetsSent_unused1     Packets sent, should be zero.
299  *      packetsSent_unused2     Packets sent, should be zero.
300  *      packetsSent_version     Packets sent, version type.
301  *
302  *      ackPacketsSent          Number of acks sent.
303  *      pingPacketsSent         Total number of ping packets sent.
304  *      abortPacketsSent        Total number of aborts sent.
305  *      busyPacketsSent         Total number of busies sent.
306  *      dataPacketsSent         Number of unique data packets sent.
307  *      dataPacketsReSent       Number of retransmissions.
308  *      dataPacketsPushed       Number of retransmissions pushed early by a NACK.
309  *      ignoreAckedPacket       Number of packets with acked flag, on rxi_Start.
310  *
311  *      totalRtt_sec            Total round trip time measured, sec component.
312  *      totalRtt_usec           Total rount trip time messured, usec component.
313  *      minRtt_sec              Minimum round trip time measured, sec component
314  *      minRtt_usec             Minimum rount trip time measured, usec component.
315  *      maxRtt_sec              Maximum round trip time measured, sec component.
316  *      maxRtt_usec             Maximum round trip time measured, usec component.
317  *
318  *      nRttSamples             Total number of round trip samples.
319  *      nServerConns            Total number of server connections.
320  *      nClientConns            Total number of client connections.
321  *      nPeerStructs            Total number of peer structures.
322  *      nCallStructs            Total number of call structures allocated.
323  *      nFreeCallStructs        Total number of previously allocated free call
324  *                               structures.
325  *
326  *      netSendFailures         Number of times osi_NetSend failed.
327  *      fatalErrors             Number of connection errors.
328  *      ignorePacketDally       Packets dropped because call is in dally state.
329  *
330  *      receiveCbufPktAllocFailures     Packet allocation failure, receive cbuf.
331  *      sendCbufPktAllocFailures        Packet allocation failure, send cbuf.
332  *
333  *      nBusies                 Number of times queued calls exceeds overload threshold.
334  */
335 struct afs_rx_kstat {
336     kstat_named_t packetRequests;
337     kstat_named_t receivePktAllocFailures;
338     kstat_named_t sendPktAllocFailures;
339     kstat_named_t specialPktAllocFailures;
340     kstat_named_t socketGreedy;
341     kstat_named_t bogusPacketOnRead;
342     kstat_named_t bogusHost;
343     kstat_named_t noPacketOnRead;
344     kstat_named_t noPacketBuffersOnRead;
345     kstat_named_t selects;
346     kstat_named_t sendSelects;
347     kstat_named_t packetsRead[RX_N_PACKET_TYPES];
348     kstat_named_t dataPacketsRead;
349     kstat_named_t ackPacketsRead;
350     kstat_named_t dupPacketsRead;
351     kstat_named_t spuriousPacketsRead;
352     kstat_named_t packetsSent[RX_N_PACKET_TYPES];
353     kstat_named_t ackPacketsSent;
354     kstat_named_t pingPacketsSent;
355     kstat_named_t abortPacketsSent;
356     kstat_named_t busyPacketsSent;
357     kstat_named_t dataPacketsSent;
358     kstat_named_t dataPacketsReSent;
359     kstat_named_t dataPacketsPushed;
360     kstat_named_t ignoreAckedPacket;
361     kstat_named_t totalRtt_sec;
362     kstat_named_t totalRtt_usec;
363     kstat_named_t minRtt_sec;
364     kstat_named_t minRtt_usec;
365     kstat_named_t maxRtt_sec;
366     kstat_named_t maxRtt_usec;
367     kstat_named_t nRttSamples;
368     kstat_named_t nServerConns;
369     kstat_named_t nClientConns;
370     kstat_named_t nPeerStructs;
371     kstat_named_t nCallStructs;
372     kstat_named_t nFreeCallStructs;
373     kstat_named_t netSendFailures;
374     kstat_named_t fatalErrors;
375     kstat_named_t ignorePacketDally;
376     kstat_named_t receiveCbufPktAllocFailures;
377     kstat_named_t sendCbufPktAllocFailures;
378     kstat_named_t nBusies;
379 };
380 static struct afs_rx_kstat rx_kstats = {
381     .packetRequests = {"packetRequests", KSTAT_DATA_ULONG},
382     .receivePktAllocFailures = {"receivePktAllocFailures", KSTAT_DATA_ULONG},
383     .sendPktAllocFailures = {"sendPktAllocFailures", KSTAT_DATA_ULONG},
384     .specialPktAllocFailures = {"specialPktAllocFailures", KSTAT_DATA_ULONG},
385     .socketGreedy = {"socketGreedy", KSTAT_DATA_ULONG},
386     .bogusPacketOnRead = {"bogusPacketOnRead", KSTAT_DATA_ULONG},
387     .bogusHost = {"bogusHost", KSTAT_DATA_ULONG},
388     .noPacketOnRead = {"noPacketOnRead", KSTAT_DATA_ULONG},
389     .noPacketBuffersOnRead = {"noPacketBuffersOnRead", KSTAT_DATA_ULONG},
390     .selects = {"selects", KSTAT_DATA_ULONG},
391     .sendSelects = {"sendSelects", KSTAT_DATA_ULONG},
392     .packetsRead = {
393         {"packetsRead_data", KSTAT_DATA_ULONG},
394         {"packetsRead_ack", KSTAT_DATA_ULONG},
395         {"packetsRead_busy", KSTAT_DATA_ULONG},
396         {"packetsRead_abort", KSTAT_DATA_ULONG},
397         {"packetsRead_ackall", KSTAT_DATA_ULONG},
398         {"packetsRead_challenge", KSTAT_DATA_ULONG},
399         {"packetsRead_response", KSTAT_DATA_ULONG},
400         {"packetsRead_debug", KSTAT_DATA_ULONG},
401         {"packetsRead_params", KSTAT_DATA_ULONG},
402         {"packetsRead_unused0", KSTAT_DATA_ULONG},
403         {"packetsRead_unused1", KSTAT_DATA_ULONG},
404         {"packetsRead_unused2", KSTAT_DATA_ULONG},
405         {"packetsRead_version", KSTAT_DATA_ULONG},
406     },
407     .dataPacketsRead = {"dataPacketsRead", KSTAT_DATA_ULONG},
408     .ackPacketsRead = {"ackPacketsRead", KSTAT_DATA_ULONG},
409     .dupPacketsRead = {"dupPacketsRead", KSTAT_DATA_ULONG},
410     .spuriousPacketsRead = {"spuriousPacketsRead", KSTAT_DATA_ULONG},
411     .packetsSent = {
412         {"packetsSent_data", KSTAT_DATA_ULONG},
413         {"packetsSent_ack", KSTAT_DATA_ULONG},
414         {"packetsSent_busy", KSTAT_DATA_ULONG},
415         {"packetsSent_abort", KSTAT_DATA_ULONG},
416         {"packetsSent_ackall", KSTAT_DATA_ULONG},
417         {"packetsSent_challenge", KSTAT_DATA_ULONG},
418         {"packetsSent_response", KSTAT_DATA_ULONG},
419         {"packetsSent_debug", KSTAT_DATA_ULONG},
420         {"packetsSent_params", KSTAT_DATA_ULONG},
421         {"packetsSent_unused0", KSTAT_DATA_ULONG},
422         {"packetsSent_unused1", KSTAT_DATA_ULONG},
423         {"packetsSent_unused2", KSTAT_DATA_ULONG},
424         {"packetsSent_version", KSTAT_DATA_ULONG},
425     },
426     .ackPacketsSent = {"ackPacketsSent", KSTAT_DATA_ULONG},
427     .pingPacketsSent = {"pingPacketsSent", KSTAT_DATA_ULONG},
428     .abortPacketsSent = {"abortPacketsSent", KSTAT_DATA_ULONG},
429     .busyPacketsSent = {"busyPacketsSent", KSTAT_DATA_ULONG},
430     .dataPacketsSent = {"dataPacketsSent", KSTAT_DATA_ULONG},
431     .dataPacketsReSent = {"dataPacketsReSent", KSTAT_DATA_ULONG},
432     .dataPacketsPushed = {"dataPacketsPushed", KSTAT_DATA_ULONG},
433
434     .ignoreAckedPacket = {"ignoreAckedPacket", KSTAT_DATA_ULONG},
435     .totalRtt_sec = {"totalRtt_sec", KSTAT_DATA_ULONG},
436     .totalRtt_usec = {"totalRtt_usec", KSTAT_DATA_ULONG},
437     .minRtt_sec = {"minRtt_sec", KSTAT_DATA_ULONG},
438     .minRtt_usec = {"minRtt_usec", KSTAT_DATA_ULONG},
439     .maxRtt_sec = {"maxRtt_sec", KSTAT_DATA_ULONG},
440     .maxRtt_usec = {"maxRtt_usec", KSTAT_DATA_ULONG},
441     .nRttSamples = {"nRttSamples", KSTAT_DATA_ULONG},
442     .nServerConns = {"nServerConns", KSTAT_DATA_ULONG},
443     .nClientConns = {"nClientConns", KSTAT_DATA_ULONG},
444     .nPeerStructs = {"nPeerStructs", KSTAT_DATA_ULONG},
445     .nCallStructs = {"nCallStructs", KSTAT_DATA_ULONG},
446     .nFreeCallStructs = {"nFreeCallStructs", KSTAT_DATA_ULONG},
447     .netSendFailures = {"netSendFailures", KSTAT_DATA_ULONG},
448     .fatalErrors = {"fatalErrors", KSTAT_DATA_ULONG},
449     .ignorePacketDally = {"ignorePacketDally", KSTAT_DATA_ULONG},
450     .receiveCbufPktAllocFailures = {"receiveCbufPktAllocFailures", KSTAT_DATA_ULONG},
451     .sendCbufPktAllocFailures = {"sendCbufPktAllocFailures", KSTAT_DATA_ULONG},
452     .nBusies = {"nBusies", KSTAT_DATA_ULONG},
453 };
454
455 /*
456  * Update the rx kstat.
457  */
458 static int
459 afs_rx_ks_update(kstat_t * ksp, int rw)
460 {
461     struct afs_rx_kstat *k = ksp->ks_data;  /* ks_data is void* */
462     struct rx_statisticsAtomic *s = &rx_stats;
463     int i;
464
465     if (rw == KSTAT_WRITE) {
466         return EACCES;
467     }
468
469 #define KSET(ks) do {k->ks.value.ul = s->ks;} while (0)
470 #define KSET_ATOM(ks) do {k->ks.value.ul = rx_atomic_read(&(s->ks));} while (0)
471     KSET_ATOM(packetRequests);
472     KSET_ATOM(receivePktAllocFailures);
473     KSET_ATOM(sendPktAllocFailures);
474     KSET_ATOM(specialPktAllocFailures);
475     KSET_ATOM(socketGreedy);
476     KSET_ATOM(bogusPacketOnRead);
477     KSET(bogusHost);
478     KSET_ATOM(noPacketOnRead);
479     KSET_ATOM(noPacketBuffersOnRead);
480     KSET_ATOM(selects);
481     KSET_ATOM(sendSelects);
482     for (i = 0; i < RX_N_PACKET_TYPES; i++) {
483         KSET_ATOM(packetsRead[i]);
484     }
485     KSET_ATOM(dataPacketsRead);
486     KSET_ATOM(ackPacketsRead);
487     KSET_ATOM(dupPacketsRead);
488     KSET_ATOM(spuriousPacketsRead);
489     for (i = 0; i < RX_N_PACKET_TYPES; i++) {
490         KSET_ATOM(packetsSent[i]);
491     }
492     KSET_ATOM(ackPacketsSent);
493     KSET_ATOM(pingPacketsSent);
494     KSET_ATOM(abortPacketsSent);
495     KSET_ATOM(busyPacketsSent);
496     KSET_ATOM(dataPacketsSent);
497     KSET_ATOM(dataPacketsReSent);
498     KSET_ATOM(dataPacketsPushed);
499     KSET_ATOM(ignoreAckedPacket);
500
501     /* not rx_atomic */
502     k->totalRtt_sec.value.ul = s->totalRtt.sec;
503     k->totalRtt_usec.value.ul = s->totalRtt.usec;
504     k->minRtt_sec.value.ul = s->minRtt.sec;
505     k->minRtt_usec.value.ul = s->minRtt.usec;
506     k->maxRtt_sec.value.ul = s->maxRtt.sec;
507     k->maxRtt_usec.value.ul = s->maxRtt.usec;
508
509     KSET_ATOM(nRttSamples);
510     KSET_ATOM(nServerConns);
511     KSET_ATOM(nClientConns);
512     KSET_ATOM(nPeerStructs);
513     KSET_ATOM(nCallStructs);
514     KSET_ATOM(nFreeCallStructs);
515     KSET_ATOM(netSendFailures);
516     KSET_ATOM(fatalErrors);
517     KSET_ATOM(ignorePacketDally);
518     KSET_ATOM(receiveCbufPktAllocFailures);
519     KSET_ATOM(sendCbufPktAllocFailures);
520     KSET_ATOM(nBusies);
521 #undef KSET
522 #undef KSET_ATOM
523     return 0;
524 }
525
526 /*
527  * Create and install the kstats for this module.
528  *
529  * /pre AFS_GLOCK held
530  */
531 void
532 afs_kstat_init(void)
533 {
534     char *thiscell = NULL;
535     struct cell *tcell;
536
537     afs_param_ksp = kstat_create("openafs", 0, "param", "misc", KSTAT_TYPE_NAMED,
538                        sizeof(param_kstats) / sizeof(kstat_named_t),
539                        KSTAT_FLAG_VIRTUAL);
540
541     if (afs_param_ksp == NULL) {
542         afs_warn("afs_kstat_init: kstat_create() failed for 'param'.\n");
543     } else {
544         afs_param_ksp->ks_data = &param_kstats;
545         afs_param_ksp->ks_update = afs_param_ks_update,
546         kstat_install(afs_param_ksp);
547     }
548
549     tcell = afs_GetPrimaryCell(READ_LOCK);
550     if (tcell)
551         thiscell = tcell->cellName;
552     if (thiscell == NULL || strlen(thiscell) == 0)
553         thiscell = "-UNKNOWN-";
554     strlcpy(cellname, thiscell, sizeof(cellname));
555     if (tcell)
556         afs_PutCell(tcell, READ_LOCK);
557
558     afs_cache_ksp = kstat_create("openafs", 0, "cache", "misc", KSTAT_TYPE_NAMED,
559                        sizeof(cache_kstats) / sizeof(kstat_named_t),
560                        KSTAT_FLAG_VIRTUAL);
561     if (afs_cache_ksp == NULL) {
562         afs_warn("afs_kstat_init: kstat_create() failed for 'cache'.\n");
563     } else {
564         /* Calculate the size of the KSTAT_DATA_STRINGs. */
565         afs_cache_ksp->ks_data_size += strlen(cellname) + 1;
566         afs_cache_ksp->ks_data_size += strlen(AFSVersion) + 1;
567         afs_cache_ksp->ks_data = &cache_kstats;
568         afs_cache_ksp->ks_update = afs_cache_ks_update;
569         kstat_install(afs_cache_ksp);
570     }
571
572     afs_rx_ksp = kstat_create("openafs", 0, "rx", "misc", KSTAT_TYPE_NAMED,
573                        sizeof(rx_kstats) / sizeof(kstat_named_t),
574                        KSTAT_FLAG_VIRTUAL);
575     if (afs_rx_ksp == NULL) {
576         afs_warn("afs_kstat_init: kstat_create() failed for 'rx'.\n");
577     } else {
578         afs_rx_ksp->ks_data = &rx_kstats;
579         afs_rx_ksp->ks_update = afs_rx_ks_update;
580         kstat_install(afs_rx_ksp);
581     }
582
583     return;
584 }
585
586 /*
587  * Remove the kstats.
588  */
589 void
590 afs_kstat_shutdown(void)
591 {
592     if (afs_param_ksp != NULL) {
593         kstat_delete(afs_param_ksp);
594         afs_param_ksp = NULL;
595     }
596     if (afs_cache_ksp != NULL) {
597         kstat_delete(afs_cache_ksp);
598         afs_cache_ksp = NULL;
599     }
600     if (afs_rx_ksp != NULL) {
601         kstat_delete(afs_rx_ksp);
602         afs_rx_ksp = NULL;
603     }
604 }