devmntstats.c 3.9 KB

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