1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7
8 void (*mntstats)(int, Chan*, uvlong, ulong);
9
10 enum
11 {
12 Qmntstat = 1<<12,
13
14 Nhash= 31,
15 Nms= 256,
16 Nrpc= (Tmax-Tnop)/2,
17 };
18
19 typedef struct Mntstats Mntstats;
20 struct Mntstats
21 {
22 Mntstats *next;
23 int inuse;
24 Chan c;
25 uvlong hi[Nrpc]; /* high water time spent */
26 uvlong tot[Nrpc]; /* cumulative time spent */
27 uvlong bytes[Nrpc]; /* cumulative bytes xfered */
28 ulong n[Nrpc]; /* number of messages/msg type */
29 uvlong bigtot[Nrpc]; /* cumulative time spent in big messages */
30 uvlong bigbytes[Nrpc]; /* cumulative bytes xfered in big messages */
31 ulong bign[Nrpc]; /* number of big messages */
32 };
33
34 static struct
35 {
36 Lock;
37 Mntstats *hash[Nhash];
38 Mntstats all[Nms];
39 int n;
40 } msalloc;
41
42 static void
43 _mntstats(int type, Chan *c, uvlong start, ulong bytes)
44 {
45 uint h;
46 Mntstats **l, *m;
47 uvlong elapsed;
48
49 elapsed = fastticks(nil) - start;
50 type -= Tnop;
51 type >>= 1;
52
53 h = (c->dev<<4)+(c->type<<2)+c->qid.path;
54 h %= Nhash;
55 for(l = &msalloc.hash[h]; *l; l = &(*l)->next)
56 if(eqchan(&(*l)->c, c, 0))
57 break;
58 m = *l;
59
60 if(m == nil){
61 lock(&msalloc);
62 for(m = msalloc.all; m < &msalloc.all[Nms]; m++)
63 if(m->inuse && eqchan(&m->c, c, 0))
64 break;
65 if(m == &msalloc.all[Nms])
66 for(m = msalloc.all; m < &msalloc.all[Nms]; m++){
67 if(m->inuse == 0){
68 m->inuse = 1;
69 m->c = *c;
70 *l = m;
71 msalloc.n++;
72 break;
73 }
74 }
75 unlock(&msalloc);
76 if(m >= &msalloc.all[Nms])
77 return;
78 }
79
80 if(m->hi[type] < elapsed)
81 m->hi[type] = elapsed;
82 m->tot[type] += elapsed;
83 m->n[type]++;
84 m->bytes[type] += bytes;
85
86 if(bytes >= 8*1024){
87 m->bigtot[type] += elapsed;
88 m->bign[type]++;
89 m->bigbytes[type] += bytes;
90 }
91 }
92
93 static int
94 mntstatsgen(Chan *c, Dirtab*, int, int i, Dir *dp)
95 {
96 Qid q;
97 Mntstats *m;
98
99 if(i == DEVDOTDOT){
100 devdir(c, (Qid){CHDIR,0}, "#z", 0, eve, 0555, dp);
101 return 1;
102 }
103
104 m = &msalloc.all[i];
105 if(i > Nms || m->inuse == 0)
106 return -1;
107
108 q = (Qid){Qmntstat+i, 0};
109 snprint(up->genbuf, sizeof up->genbuf, "%C%lud.%lux", devtab[m->c.type]->dc, m->c.dev, m->c.qid.path);
110 devdir(c, q, up->genbuf, 0, eve, 0666, dp);
111
112 return 1;
113 }
114
115 static void
116 mntstatsinit(void)
117 {
118 mntstats = _mntstats;
119 }
120
121 static Chan*
122 mntstatsattach(char *spec)
123 {
124 return devattach('z', spec);
125 }
126
127 static int
128 mntstatswalk(Chan *c, char *name)
129 {
130 return devwalk(c, name, 0, msalloc.n, mntstatsgen);
131 }
132
133 static void
134 mntstatsstat(Chan *c, char *dp)
135 {
136 devstat(c, dp, 0, msalloc.n, mntstatsgen);
137 }
138
139 static Chan*
140 mntstatsopen(Chan *c, int omode)
141 {
142 return devopen(c, omode, 0, msalloc.n, mntstatsgen);
143 }
144
145 static void
146 mntstatsclose(Chan*)
147 {
148 }
149
150 enum
151 {
152 Nline= 136,
153 };
154
155 char *rpcname[Nrpc] =
156 {
157 "nop",
158 "osession",
159 "error",
160 "flush",
161 "oattach",
162 "clone",
163 "walk",
164 "open",
165 "create",
166 "read",
167 "write",
168 "clunk",
169 "remove",
170 "stat",
171 "wstat",
172 "clwalk",
173 "auth",
174 "session",
175 "attach",
176 };
177
178 static long
179 mntstatsread(Chan *c, void *buf, long n, vlong off)
180 {
181 char *a, *start;
182 ulong o;
183 char xbuf[Nline+1];
184 Mntstats *m;
185
186 start = a = buf;
187
188 if(n <= 0)
189 return n;
190
191 if(c->qid.path & CHDIR)
192 return devdirread(c, buf, n, 0, msalloc.n, mntstatsgen);
193
194 m = &msalloc.all[c->qid.path - Qmntstat];
195 o = off;
196 if((o % Nline) != 0)
197 error(Ebadarg);
198 n = n/Nline;
199 o = o/Nline;
200 while(n > 0 && o < Nrpc){
201 snprint(xbuf, sizeof(xbuf), "%-8.8s\t%20.0llud\n\t%20.0llud %20.0llud %9.0lud\n\t%20.0llud %20.0llud %9.0lud\n",
202 rpcname[o], m->hi[o],
203 m->tot[o], m->bytes[o], m->n[o],
204 m->bigtot[o], m->bigbytes[o], m->bign[o]);
205 memmove(a, xbuf, Nline);
206 a += Nline;
207 o++;
208 n--;
209 }
210 return a - start;
211 }
212
213 static long
214 mntstatswrite(Chan*, void*, long, vlong)
215 {
216 lock(&msalloc);
217 memset(msalloc.all, 0, sizeof(msalloc.all));
218 msalloc.n = 0;
219 unlock(&msalloc);
220 return 0;
221 }
222
223 Dev mntstatsdevtab = {
224 'z',
225 "mntstats",
226
227 devreset,
228 mntstatsinit,
229 mntstatsattach,
230 devclone,
231 mntstatswalk,
232 mntstatsstat,
233 mntstatsopen,
234 devcreate,
235 mntstatsclose,
236 mntstatsread,
237 devbread,
238 mntstatswrite,
239 devbwrite,
240 devremove,
241 devwstat,
242 };
Cache object: 489e5a2be4595a3a56ea3717260612f6
|