proc_net_rpc_nfsd.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "plugin_proc.h"
  3. #define PLUGIN_PROC_MODULE_NFSD_NAME "/proc/net/rpc/nfsd"
  4. struct nfsd_procs {
  5. char name[30];
  6. unsigned long long value;
  7. int present;
  8. RRDDIM *rd;
  9. };
  10. struct nfsd_procs nfsd_proc2_values[] = {
  11. { "null" , 0ULL, 0, NULL}
  12. , {"getattr" , 0ULL, 0, NULL}
  13. , {"setattr" , 0ULL, 0, NULL}
  14. , {"root" , 0ULL, 0, NULL}
  15. , {"lookup" , 0ULL, 0, NULL}
  16. , {"readlink", 0ULL, 0, NULL}
  17. , {"read" , 0ULL, 0, NULL}
  18. , {"wrcache" , 0ULL, 0, NULL}
  19. , {"write" , 0ULL, 0, NULL}
  20. , {"create" , 0ULL, 0, NULL}
  21. , {"remove" , 0ULL, 0, NULL}
  22. , {"rename" , 0ULL, 0, NULL}
  23. , {"link" , 0ULL, 0, NULL}
  24. , {"symlink" , 0ULL, 0, NULL}
  25. , {"mkdir" , 0ULL, 0, NULL}
  26. , {"rmdir" , 0ULL, 0, NULL}
  27. , {"readdir" , 0ULL, 0, NULL}
  28. , {"fsstat" , 0ULL, 0, NULL}
  29. ,
  30. /* termination */
  31. { "" , 0ULL, 0, NULL}
  32. };
  33. struct nfsd_procs nfsd_proc3_values[] = {
  34. { "null" , 0ULL, 0, NULL}
  35. , {"getattr" , 0ULL, 0, NULL}
  36. , {"setattr" , 0ULL, 0, NULL}
  37. , {"lookup" , 0ULL, 0, NULL}
  38. , {"access" , 0ULL, 0, NULL}
  39. , {"readlink" , 0ULL, 0, NULL}
  40. , {"read" , 0ULL, 0, NULL}
  41. , {"write" , 0ULL, 0, NULL}
  42. , {"create" , 0ULL, 0, NULL}
  43. , {"mkdir" , 0ULL, 0, NULL}
  44. , {"symlink" , 0ULL, 0, NULL}
  45. , {"mknod" , 0ULL, 0, NULL}
  46. , {"remove" , 0ULL, 0, NULL}
  47. , {"rmdir" , 0ULL, 0, NULL}
  48. , {"rename" , 0ULL, 0, NULL}
  49. , {"link" , 0ULL, 0, NULL}
  50. , {"readdir" , 0ULL, 0, NULL}
  51. , {"readdirplus", 0ULL, 0, NULL}
  52. , {"fsstat" , 0ULL, 0, NULL}
  53. , {"fsinfo" , 0ULL, 0, NULL}
  54. , {"pathconf" , 0ULL, 0, NULL}
  55. , {"commit" , 0ULL, 0, NULL}
  56. ,
  57. /* termination */
  58. { "" , 0ULL, 0, NULL}
  59. };
  60. struct nfsd_procs nfsd_proc4_values[] = {
  61. { "null" , 0ULL, 0, NULL}
  62. , {"read" , 0ULL, 0, NULL}
  63. , {"write" , 0ULL, 0, NULL}
  64. , {"commit" , 0ULL, 0, NULL}
  65. , {"open" , 0ULL, 0, NULL}
  66. , {"open_conf" , 0ULL, 0, NULL}
  67. , {"open_noat" , 0ULL, 0, NULL}
  68. , {"open_dgrd" , 0ULL, 0, NULL}
  69. , {"close" , 0ULL, 0, NULL}
  70. , {"setattr" , 0ULL, 0, NULL}
  71. , {"fsinfo" , 0ULL, 0, NULL}
  72. , {"renew" , 0ULL, 0, NULL}
  73. , {"setclntid" , 0ULL, 0, NULL}
  74. , {"confirm" , 0ULL, 0, NULL}
  75. , {"lock" , 0ULL, 0, NULL}
  76. , {"lockt" , 0ULL, 0, NULL}
  77. , {"locku" , 0ULL, 0, NULL}
  78. , {"access" , 0ULL, 0, NULL}
  79. , {"getattr" , 0ULL, 0, NULL}
  80. , {"lookup" , 0ULL, 0, NULL}
  81. , {"lookup_root" , 0ULL, 0, NULL}
  82. , {"remove" , 0ULL, 0, NULL}
  83. , {"rename" , 0ULL, 0, NULL}
  84. , {"link" , 0ULL, 0, NULL}
  85. , {"symlink" , 0ULL, 0, NULL}
  86. , {"create" , 0ULL, 0, NULL}
  87. , {"pathconf" , 0ULL, 0, NULL}
  88. , {"statfs" , 0ULL, 0, NULL}
  89. , {"readlink" , 0ULL, 0, NULL}
  90. , {"readdir" , 0ULL, 0, NULL}
  91. , {"server_caps" , 0ULL, 0, NULL}
  92. , {"delegreturn" , 0ULL, 0, NULL}
  93. , {"getacl" , 0ULL, 0, NULL}
  94. , {"setacl" , 0ULL, 0, NULL}
  95. , {"fs_locations" , 0ULL, 0, NULL}
  96. , {"rel_lkowner" , 0ULL, 0, NULL}
  97. , {"secinfo" , 0ULL, 0, NULL}
  98. , {"fsid_present" , 0ULL, 0, NULL}
  99. ,
  100. /* nfsv4.1 client ops */
  101. { "exchange_id" , 0ULL, 0, NULL}
  102. , {"create_session" , 0ULL, 0, NULL}
  103. , {"destroy_session" , 0ULL, 0, NULL}
  104. , {"sequence" , 0ULL, 0, NULL}
  105. , {"get_lease_time" , 0ULL, 0, NULL}
  106. , {"reclaim_comp" , 0ULL, 0, NULL}
  107. , {"layoutget" , 0ULL, 0, NULL}
  108. , {"getdevinfo" , 0ULL, 0, NULL}
  109. , {"layoutcommit" , 0ULL, 0, NULL}
  110. , {"layoutreturn" , 0ULL, 0, NULL}
  111. , {"secinfo_no" , 0ULL, 0, NULL}
  112. , {"test_stateid" , 0ULL, 0, NULL}
  113. , {"free_stateid" , 0ULL, 0, NULL}
  114. , {"getdevicelist" , 0ULL, 0, NULL}
  115. , {"bind_conn_to_ses", 0ULL, 0, NULL}
  116. , {"destroy_clientid", 0ULL, 0, NULL}
  117. ,
  118. /* nfsv4.2 client ops */
  119. { "seek" , 0ULL, 0, NULL}
  120. , {"allocate" , 0ULL, 0, NULL}
  121. , {"deallocate" , 0ULL, 0, NULL}
  122. , {"layoutstats" , 0ULL, 0, NULL}
  123. , {"clone" , 0ULL, 0, NULL}
  124. ,
  125. /* termination */
  126. { "" , 0ULL, 0, NULL}
  127. };
  128. struct nfsd_procs nfsd4_ops_values[] = {
  129. { "unused_op0" , 0ULL, 0, NULL}
  130. , {"unused_op1" , 0ULL, 0, NULL}
  131. , {"future_op2" , 0ULL, 0, NULL}
  132. , {"access" , 0ULL, 0, NULL}
  133. , {"close" , 0ULL, 0, NULL}
  134. , {"commit" , 0ULL, 0, NULL}
  135. , {"create" , 0ULL, 0, NULL}
  136. , {"delegpurge" , 0ULL, 0, NULL}
  137. , {"delegreturn" , 0ULL, 0, NULL}
  138. , {"getattr" , 0ULL, 0, NULL}
  139. , {"getfh" , 0ULL, 0, NULL}
  140. , {"link" , 0ULL, 0, NULL}
  141. , {"lock" , 0ULL, 0, NULL}
  142. , {"lockt" , 0ULL, 0, NULL}
  143. , {"locku" , 0ULL, 0, NULL}
  144. , {"lookup" , 0ULL, 0, NULL}
  145. , {"lookup_root" , 0ULL, 0, NULL}
  146. , {"nverify" , 0ULL, 0, NULL}
  147. , {"open" , 0ULL, 0, NULL}
  148. , {"openattr" , 0ULL, 0, NULL}
  149. , {"open_confirm" , 0ULL, 0, NULL}
  150. , {"open_downgrade" , 0ULL, 0, NULL}
  151. , {"putfh" , 0ULL, 0, NULL}
  152. , {"putpubfh" , 0ULL, 0, NULL}
  153. , {"putrootfh" , 0ULL, 0, NULL}
  154. , {"read" , 0ULL, 0, NULL}
  155. , {"readdir" , 0ULL, 0, NULL}
  156. , {"readlink" , 0ULL, 0, NULL}
  157. , {"remove" , 0ULL, 0, NULL}
  158. , {"rename" , 0ULL, 0, NULL}
  159. , {"renew" , 0ULL, 0, NULL}
  160. , {"restorefh" , 0ULL, 0, NULL}
  161. , {"savefh" , 0ULL, 0, NULL}
  162. , {"secinfo" , 0ULL, 0, NULL}
  163. , {"setattr" , 0ULL, 0, NULL}
  164. , {"setclientid" , 0ULL, 0, NULL}
  165. , {"setclientid_confirm" , 0ULL, 0, NULL}
  166. , {"verify" , 0ULL, 0, NULL}
  167. , {"write" , 0ULL, 0, NULL}
  168. , {"release_lockowner" , 0ULL, 0, NULL}
  169. ,
  170. /* nfs41 */
  171. { "backchannel_ctl" , 0ULL, 0, NULL}
  172. , {"bind_conn_to_session", 0ULL, 0, NULL}
  173. , {"exchange_id" , 0ULL, 0, NULL}
  174. , {"create_session" , 0ULL, 0, NULL}
  175. , {"destroy_session" , 0ULL, 0, NULL}
  176. , {"free_stateid" , 0ULL, 0, NULL}
  177. , {"get_dir_delegation" , 0ULL, 0, NULL}
  178. , {"getdeviceinfo" , 0ULL, 0, NULL}
  179. , {"getdevicelist" , 0ULL, 0, NULL}
  180. , {"layoutcommit" , 0ULL, 0, NULL}
  181. , {"layoutget" , 0ULL, 0, NULL}
  182. , {"layoutreturn" , 0ULL, 0, NULL}
  183. , {"secinfo_no_name" , 0ULL, 0, NULL}
  184. , {"sequence" , 0ULL, 0, NULL}
  185. , {"set_ssv" , 0ULL, 0, NULL}
  186. , {"test_stateid" , 0ULL, 0, NULL}
  187. , {"want_delegation" , 0ULL, 0, NULL}
  188. , {"destroy_clientid" , 0ULL, 0, NULL}
  189. , {"reclaim_complete" , 0ULL, 0, NULL}
  190. ,
  191. /* nfs42 */
  192. { "allocate" , 0ULL, 0, NULL}
  193. , {"copy" , 0ULL, 0, NULL}
  194. , {"copy_notify" , 0ULL, 0, NULL}
  195. , {"deallocate" , 0ULL, 0, NULL}
  196. , {"ioadvise" , 0ULL, 0, NULL}
  197. , {"layouterror" , 0ULL, 0, NULL}
  198. , {"layoutstats" , 0ULL, 0, NULL}
  199. , {"offload_cancel" , 0ULL, 0, NULL}
  200. , {"offload_status" , 0ULL, 0, NULL}
  201. , {"read_plus" , 0ULL, 0, NULL}
  202. , {"seek" , 0ULL, 0, NULL}
  203. , {"write_same" , 0ULL, 0, NULL}
  204. ,
  205. /* termination */
  206. { "" , 0ULL, 0, NULL}
  207. };
  208. int do_proc_net_rpc_nfsd(int update_every, usec_t dt) {
  209. (void)dt;
  210. static procfile *ff = NULL;
  211. static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_ra = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1;
  212. static int ra_warning = 0, proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0;
  213. if(unlikely(!ff)) {
  214. char filename[FILENAME_MAX + 1];
  215. snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/rpc/nfsd");
  216. ff = procfile_open(config_get("plugin:proc:/proc/net/rpc/nfsd", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
  217. if(unlikely(!ff)) return 1;
  218. }
  219. ff = procfile_readall(ff);
  220. if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
  221. if(unlikely(do_rc == -1)) {
  222. do_rc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read cache", 1);
  223. do_fh = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "file handles", 1);
  224. do_io = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "I/O", 1);
  225. do_th = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "threads", 1);
  226. do_ra = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read ahead", 1);
  227. do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "network", 1);
  228. do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "rpc", 1);
  229. do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v2 procedures", 1);
  230. do_proc3 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v3 procedures", 1);
  231. do_proc4 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 procedures", 1);
  232. do_proc4ops = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 operations", 1);
  233. }
  234. // if they are enabled, reset them to 1
  235. // later we do them = 2 to avoid doing strcmp() for all lines
  236. if(do_rc) do_rc = 1;
  237. if(do_fh) do_fh = 1;
  238. if(do_io) do_io = 1;
  239. if(do_th) do_th = 1;
  240. if(do_ra) do_ra = 1;
  241. if(do_net) do_net = 1;
  242. if(do_rpc) do_rpc = 1;
  243. if(do_proc2) do_proc2 = 1;
  244. if(do_proc3) do_proc3 = 1;
  245. if(do_proc4) do_proc4 = 1;
  246. if(do_proc4ops) do_proc4ops = 1;
  247. size_t lines = procfile_lines(ff), l;
  248. char *type;
  249. unsigned long long rc_hits = 0, rc_misses = 0, rc_nocache = 0;
  250. unsigned long long fh_stale = 0;
  251. unsigned long long io_read = 0, io_write = 0;
  252. unsigned long long th_threads = 0;
  253. unsigned long long ra_size = 0, ra_hist10 = 0, ra_hist20 = 0, ra_hist30 = 0, ra_hist40 = 0, ra_hist50 = 0, ra_hist60 = 0, ra_hist70 = 0, ra_hist80 = 0, ra_hist90 = 0, ra_hist100 = 0, ra_none = 0;
  254. unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0;
  255. unsigned long long rpc_calls = 0, rpc_bad_format = 0, rpc_bad_auth = 0, rpc_bad_client = 0;
  256. for(l = 0; l < lines ;l++) {
  257. size_t words = procfile_linewords(ff, l);
  258. if(unlikely(!words)) continue;
  259. type = procfile_lineword(ff, l, 0);
  260. if(do_rc == 1 && strcmp(type, "rc") == 0) {
  261. if(unlikely(words < 4)) {
  262. error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 4);
  263. continue;
  264. }
  265. rc_hits = str2ull(procfile_lineword(ff, l, 1));
  266. rc_misses = str2ull(procfile_lineword(ff, l, 2));
  267. rc_nocache = str2ull(procfile_lineword(ff, l, 3));
  268. unsigned long long sum = rc_hits + rc_misses + rc_nocache;
  269. if(sum == 0ULL) do_rc = -1;
  270. else do_rc = 2;
  271. }
  272. else if(do_fh == 1 && strcmp(type, "fh") == 0) {
  273. if(unlikely(words < 6)) {
  274. error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 6);
  275. continue;
  276. }
  277. fh_stale = str2ull(procfile_lineword(ff, l, 1));
  278. // other file handler metrics were never used and are always zero
  279. if(fh_stale == 0ULL) do_fh = -1;
  280. else do_fh = 2;
  281. }
  282. else if(do_io == 1 && strcmp(type, "io") == 0) {
  283. if(unlikely(words < 3)) {
  284. error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 3);
  285. continue;
  286. }
  287. io_read = str2ull(procfile_lineword(ff, l, 1));
  288. io_write = str2ull(procfile_lineword(ff, l, 2));
  289. unsigned long long sum = io_read + io_write;
  290. if(sum == 0ULL) do_io = -1;
  291. else do_io = 2;
  292. }
  293. else if(do_th == 1 && strcmp(type, "th") == 0) {
  294. if(unlikely(words < 13)) {
  295. error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 13);
  296. continue;
  297. }
  298. th_threads = str2ull(procfile_lineword(ff, l, 1));
  299. // thread histogram has been disabled since 2009 (kernel 2.6.30)
  300. // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8bbfa9f3889b643fc7de82c0c761ef17097f8faf
  301. do_th = 2;
  302. }
  303. else if(do_ra == 1 && strcmp(type, "ra") == 0) {
  304. if(unlikely(words < 13)) {
  305. error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 13);
  306. continue;
  307. }
  308. // readahead cache has been disabled since 2019 (kernel 5.4)
  309. // https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/fs/nfsd/vfs.c?id=501cb1849f865960501d19d54e6a5af306f9b6fd
  310. ra_size = str2ull(procfile_lineword(ff, l, 1));
  311. ra_hist10 = str2ull(procfile_lineword(ff, l, 2));
  312. ra_hist20 = str2ull(procfile_lineword(ff, l, 3));
  313. ra_hist30 = str2ull(procfile_lineword(ff, l, 4));
  314. ra_hist40 = str2ull(procfile_lineword(ff, l, 5));
  315. ra_hist50 = str2ull(procfile_lineword(ff, l, 6));
  316. ra_hist60 = str2ull(procfile_lineword(ff, l, 7));
  317. ra_hist70 = str2ull(procfile_lineword(ff, l, 8));
  318. ra_hist80 = str2ull(procfile_lineword(ff, l, 9));
  319. ra_hist90 = str2ull(procfile_lineword(ff, l, 10));
  320. ra_hist100 = str2ull(procfile_lineword(ff, l, 11));
  321. ra_none = str2ull(procfile_lineword(ff, l, 12));
  322. unsigned long long sum = ra_hist10 + ra_hist20 + ra_hist30 + ra_hist40 + ra_hist50 + ra_hist60 + ra_hist70 + ra_hist80 + ra_hist90 + ra_hist100 + ra_none;
  323. if(sum == 0ULL) {
  324. if(!ra_warning) {
  325. info("Disabling /proc/net/rpc/nfsd read ahead histogram. It seems unused on this machine. It will be enabled automatically when found with data in it.");
  326. ra_warning = 1;
  327. }
  328. do_ra = -1;
  329. }
  330. else do_ra = 2;
  331. }
  332. else if(do_net == 1 && strcmp(type, "net") == 0) {
  333. if(unlikely(words < 5)) {
  334. error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 5);
  335. continue;
  336. }
  337. net_count = str2ull(procfile_lineword(ff, l, 1));
  338. net_udp_count = str2ull(procfile_lineword(ff, l, 2));
  339. net_tcp_count = str2ull(procfile_lineword(ff, l, 3));
  340. net_tcp_connections = str2ull(procfile_lineword(ff, l, 4));
  341. unsigned long long sum = net_count + net_udp_count + net_tcp_count + net_tcp_connections;
  342. if(sum == 0ULL) do_net = -1;
  343. else do_net = 2;
  344. }
  345. else if(do_rpc == 1 && strcmp(type, "rpc") == 0) {
  346. if(unlikely(words < 6)) {
  347. error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 6);
  348. continue;
  349. }
  350. rpc_calls = str2ull(procfile_lineword(ff, l, 1));
  351. rpc_bad_format = str2ull(procfile_lineword(ff, l, 3));
  352. rpc_bad_auth = str2ull(procfile_lineword(ff, l, 4));
  353. rpc_bad_client = str2ull(procfile_lineword(ff, l, 5));
  354. unsigned long long sum = rpc_calls + rpc_bad_format + rpc_bad_auth + rpc_bad_client;
  355. if(sum == 0ULL) do_rpc = -1;
  356. else do_rpc = 2;
  357. }
  358. else if(do_proc2 == 1 && strcmp(type, "proc2") == 0) {
  359. // the first number is the count of numbers present
  360. // so we start for word 2
  361. unsigned long long sum = 0;
  362. unsigned int i, j;
  363. for(i = 0, j = 2; j < words && nfsd_proc2_values[i].name[0] ; i++, j++) {
  364. nfsd_proc2_values[i].value = str2ull(procfile_lineword(ff, l, j));
  365. nfsd_proc2_values[i].present = 1;
  366. sum += nfsd_proc2_values[i].value;
  367. }
  368. if(sum == 0ULL) {
  369. if(!proc2_warning) {
  370. error("Disabling /proc/net/rpc/nfsd v2 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
  371. proc2_warning = 1;
  372. }
  373. do_proc2 = 0;
  374. }
  375. else do_proc2 = 2;
  376. }
  377. else if(do_proc3 == 1 && strcmp(type, "proc3") == 0) {
  378. // the first number is the count of numbers present
  379. // so we start for word 2
  380. unsigned long long sum = 0;
  381. unsigned int i, j;
  382. for(i = 0, j = 2; j < words && nfsd_proc3_values[i].name[0] ; i++, j++) {
  383. nfsd_proc3_values[i].value = str2ull(procfile_lineword(ff, l, j));
  384. nfsd_proc3_values[i].present = 1;
  385. sum += nfsd_proc3_values[i].value;
  386. }
  387. if(sum == 0ULL) {
  388. if(!proc3_warning) {
  389. info("Disabling /proc/net/rpc/nfsd v3 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
  390. proc3_warning = 1;
  391. }
  392. do_proc3 = 0;
  393. }
  394. else do_proc3 = 2;
  395. }
  396. else if(do_proc4 == 1 && strcmp(type, "proc4") == 0) {
  397. // the first number is the count of numbers present
  398. // so we start for word 2
  399. unsigned long long sum = 0;
  400. unsigned int i, j;
  401. for(i = 0, j = 2; j < words && nfsd_proc4_values[i].name[0] ; i++, j++) {
  402. nfsd_proc4_values[i].value = str2ull(procfile_lineword(ff, l, j));
  403. nfsd_proc4_values[i].present = 1;
  404. sum += nfsd_proc4_values[i].value;
  405. }
  406. if(sum == 0ULL) {
  407. if(!proc4_warning) {
  408. info("Disabling /proc/net/rpc/nfsd v4 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
  409. proc4_warning = 1;
  410. }
  411. do_proc4 = 0;
  412. }
  413. else do_proc4 = 2;
  414. }
  415. else if(do_proc4ops == 1 && strcmp(type, "proc4ops") == 0) {
  416. // the first number is the count of numbers present
  417. // so we start for word 2
  418. unsigned long long sum = 0;
  419. unsigned int i, j;
  420. for(i = 0, j = 2; j < words && nfsd4_ops_values[i].name[0] ; i++, j++) {
  421. nfsd4_ops_values[i].value = str2ull(procfile_lineword(ff, l, j));
  422. nfsd4_ops_values[i].present = 1;
  423. sum += nfsd4_ops_values[i].value;
  424. }
  425. if(sum == 0ULL) {
  426. if(!proc4ops_warning) {
  427. info("Disabling /proc/net/rpc/nfsd v4 operations chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
  428. proc4ops_warning = 1;
  429. }
  430. do_proc4ops = 0;
  431. }
  432. else do_proc4ops = 2;
  433. }
  434. }
  435. // --------------------------------------------------------------------
  436. if(do_rc == 2) {
  437. static RRDSET *st = NULL;
  438. static RRDDIM *rd_hits = NULL,
  439. *rd_misses = NULL,
  440. *rd_nocache = NULL;
  441. if(unlikely(!st)) {
  442. st = rrdset_create_localhost(
  443. "nfsd"
  444. , "readcache"
  445. , NULL
  446. , "cache"
  447. , NULL
  448. , "NFS Server Read Cache"
  449. , "reads/s"
  450. , PLUGIN_PROC_NAME
  451. , PLUGIN_PROC_MODULE_NFSD_NAME
  452. , NETDATA_CHART_PRIO_NFSD_READCACHE
  453. , update_every
  454. , RRDSET_TYPE_STACKED
  455. );
  456. rd_hits = rrddim_add(st, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  457. rd_misses = rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  458. rd_nocache = rrddim_add(st, "nocache", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  459. }
  460. else rrdset_next(st);
  461. rrddim_set_by_pointer(st, rd_hits, rc_hits);
  462. rrddim_set_by_pointer(st, rd_misses, rc_misses);
  463. rrddim_set_by_pointer(st, rd_nocache, rc_nocache);
  464. rrdset_done(st);
  465. }
  466. // --------------------------------------------------------------------
  467. if(do_fh == 2) {
  468. static RRDSET *st = NULL;
  469. static RRDDIM *rd_stale = NULL;
  470. if(unlikely(!st)) {
  471. st = rrdset_create_localhost(
  472. "nfsd"
  473. , "filehandles"
  474. , NULL
  475. , "filehandles"
  476. , NULL
  477. , "NFS Server File Handles"
  478. , "handles/s"
  479. , PLUGIN_PROC_NAME
  480. , PLUGIN_PROC_MODULE_NFSD_NAME
  481. , NETDATA_CHART_PRIO_NFSD_FILEHANDLES
  482. , update_every
  483. , RRDSET_TYPE_LINE
  484. );
  485. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  486. rd_stale = rrddim_add(st, "stale", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  487. }
  488. else rrdset_next(st);
  489. rrddim_set_by_pointer(st, rd_stale, fh_stale);
  490. rrdset_done(st);
  491. }
  492. // --------------------------------------------------------------------
  493. if(do_io == 2) {
  494. static RRDSET *st = NULL;
  495. static RRDDIM *rd_read = NULL,
  496. *rd_write = NULL;
  497. if(unlikely(!st)) {
  498. st = rrdset_create_localhost(
  499. "nfsd"
  500. , "io"
  501. , NULL
  502. , "io"
  503. , NULL
  504. , "NFS Server I/O"
  505. , "kilobytes/s"
  506. , PLUGIN_PROC_NAME
  507. , PLUGIN_PROC_MODULE_NFSD_NAME
  508. , NETDATA_CHART_PRIO_NFSD_IO
  509. , update_every
  510. , RRDSET_TYPE_AREA
  511. );
  512. rd_read = rrddim_add(st, "read", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
  513. rd_write = rrddim_add(st, "write", NULL, -1, 1000, RRD_ALGORITHM_INCREMENTAL);
  514. }
  515. else rrdset_next(st);
  516. rrddim_set_by_pointer(st, rd_read, io_read);
  517. rrddim_set_by_pointer(st, rd_write, io_write);
  518. rrdset_done(st);
  519. }
  520. // --------------------------------------------------------------------
  521. if(do_th == 2) {
  522. static RRDSET *st = NULL;
  523. static RRDDIM *rd_threads = NULL;
  524. if(unlikely(!st)) {
  525. st = rrdset_create_localhost(
  526. "nfsd"
  527. , "threads"
  528. , NULL
  529. , "threads"
  530. , NULL
  531. , "NFS Server Threads"
  532. , "threads"
  533. , PLUGIN_PROC_NAME
  534. , PLUGIN_PROC_MODULE_NFSD_NAME
  535. , NETDATA_CHART_PRIO_NFSD_THREADS
  536. , update_every
  537. , RRDSET_TYPE_LINE
  538. );
  539. rd_threads = rrddim_add(st, "threads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
  540. }
  541. else rrdset_next(st);
  542. rrddim_set_by_pointer(st, rd_threads, th_threads);
  543. rrdset_done(st);
  544. }
  545. // --------------------------------------------------------------------
  546. if(do_ra == 2) {
  547. static RRDSET *st = NULL;
  548. static RRDDIM *rd_ra_hist10 = NULL,
  549. *rd_ra_hist20 = NULL,
  550. *rd_ra_hist30 = NULL,
  551. *rd_ra_hist40 = NULL,
  552. *rd_ra_hist50 = NULL,
  553. *rd_ra_hist60 = NULL,
  554. *rd_ra_hist70 = NULL,
  555. *rd_ra_hist80 = NULL,
  556. *rd_ra_hist90 = NULL,
  557. *rd_ra_hist100 = NULL,
  558. *rd_ra_none = NULL;
  559. if(unlikely(!st)) {
  560. st = rrdset_create_localhost(
  561. "nfsd"
  562. , "readahead"
  563. , NULL
  564. , "readahead"
  565. , NULL
  566. , "NFS Server Read Ahead Depth"
  567. , "percentage"
  568. , PLUGIN_PROC_NAME
  569. , PLUGIN_PROC_MODULE_NFSD_NAME
  570. , NETDATA_CHART_PRIO_NFSD_READAHEAD
  571. , update_every
  572. , RRDSET_TYPE_STACKED
  573. );
  574. rd_ra_hist10 = rrddim_add(st, "10%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  575. rd_ra_hist20 = rrddim_add(st, "20%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  576. rd_ra_hist30 = rrddim_add(st, "30%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  577. rd_ra_hist40 = rrddim_add(st, "40%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  578. rd_ra_hist50 = rrddim_add(st, "50%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  579. rd_ra_hist60 = rrddim_add(st, "60%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  580. rd_ra_hist70 = rrddim_add(st, "70%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  581. rd_ra_hist80 = rrddim_add(st, "80%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  582. rd_ra_hist90 = rrddim_add(st, "90%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  583. rd_ra_hist100 = rrddim_add(st, "100%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  584. rd_ra_none = rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
  585. }
  586. else rrdset_next(st);
  587. // ignore ra_size
  588. (void)ra_size;
  589. rrddim_set_by_pointer(st, rd_ra_hist10, ra_hist10);
  590. rrddim_set_by_pointer(st, rd_ra_hist20, ra_hist20);
  591. rrddim_set_by_pointer(st, rd_ra_hist30, ra_hist30);
  592. rrddim_set_by_pointer(st, rd_ra_hist40, ra_hist40);
  593. rrddim_set_by_pointer(st, rd_ra_hist50, ra_hist50);
  594. rrddim_set_by_pointer(st, rd_ra_hist60, ra_hist60);
  595. rrddim_set_by_pointer(st, rd_ra_hist70, ra_hist70);
  596. rrddim_set_by_pointer(st, rd_ra_hist80, ra_hist80);
  597. rrddim_set_by_pointer(st, rd_ra_hist90, ra_hist90);
  598. rrddim_set_by_pointer(st, rd_ra_hist100,ra_hist100);
  599. rrddim_set_by_pointer(st, rd_ra_none, ra_none);
  600. rrdset_done(st);
  601. }
  602. // --------------------------------------------------------------------
  603. if(do_net == 2) {
  604. static RRDSET *st = NULL;
  605. static RRDDIM *rd_udp = NULL,
  606. *rd_tcp = NULL;
  607. if(unlikely(!st)) {
  608. st = rrdset_create_localhost(
  609. "nfsd"
  610. , "net"
  611. , NULL
  612. , "network"
  613. , NULL
  614. , "NFS Server Network Statistics"
  615. , "packets/s"
  616. , PLUGIN_PROC_NAME
  617. , PLUGIN_PROC_MODULE_NFSD_NAME
  618. , NETDATA_CHART_PRIO_NFSD_NET
  619. , update_every
  620. , RRDSET_TYPE_STACKED
  621. );
  622. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  623. rd_udp = rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  624. rd_tcp = rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  625. }
  626. else rrdset_next(st);
  627. // ignore net_count, net_tcp_connections
  628. (void)net_count;
  629. (void)net_tcp_connections;
  630. rrddim_set_by_pointer(st, rd_udp, net_udp_count);
  631. rrddim_set_by_pointer(st, rd_tcp, net_tcp_count);
  632. rrdset_done(st);
  633. }
  634. // --------------------------------------------------------------------
  635. if(do_rpc == 2) {
  636. static RRDSET *st = NULL;
  637. static RRDDIM *rd_calls = NULL,
  638. *rd_bad_format = NULL,
  639. *rd_bad_auth = NULL;
  640. if(unlikely(!st)) {
  641. st = rrdset_create_localhost(
  642. "nfsd"
  643. , "rpc"
  644. , NULL
  645. , "rpc"
  646. , NULL
  647. , "NFS Server Remote Procedure Calls Statistics"
  648. , "calls/s"
  649. , PLUGIN_PROC_NAME
  650. , PLUGIN_PROC_MODULE_NFSD_NAME
  651. , NETDATA_CHART_PRIO_NFSD_RPC
  652. , update_every
  653. , RRDSET_TYPE_LINE
  654. );
  655. rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
  656. rd_calls = rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  657. rd_bad_format = rrddim_add(st, "bad_format", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
  658. rd_bad_auth = rrddim_add(st, "bad_auth", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
  659. }
  660. else rrdset_next(st);
  661. // ignore rpc_bad_client
  662. (void)rpc_bad_client;
  663. rrddim_set_by_pointer(st, rd_calls, rpc_calls);
  664. rrddim_set_by_pointer(st, rd_bad_format, rpc_bad_format);
  665. rrddim_set_by_pointer(st, rd_bad_auth, rpc_bad_auth);
  666. rrdset_done(st);
  667. }
  668. // --------------------------------------------------------------------
  669. if(do_proc2 == 2) {
  670. static RRDSET *st = NULL;
  671. if(unlikely(!st)) {
  672. st = rrdset_create_localhost(
  673. "nfsd"
  674. , "proc2"
  675. , NULL
  676. , "nfsv2rpc"
  677. , NULL
  678. , "NFS v2 Server Remote Procedure Calls"
  679. , "calls/s"
  680. , PLUGIN_PROC_NAME
  681. , PLUGIN_PROC_MODULE_NFSD_NAME
  682. , NETDATA_CHART_PRIO_NFSD_PROC2
  683. , update_every
  684. , RRDSET_TYPE_STACKED
  685. );
  686. }
  687. else rrdset_next(st);
  688. size_t i;
  689. for(i = 0; nfsd_proc2_values[i].present ; i++) {
  690. if(unlikely(!nfsd_proc2_values[i].rd))
  691. nfsd_proc2_values[i].rd = rrddim_add(st, nfsd_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  692. rrddim_set_by_pointer(st, nfsd_proc2_values[i].rd, nfsd_proc2_values[i].value);
  693. }
  694. rrdset_done(st);
  695. }
  696. // --------------------------------------------------------------------
  697. if(do_proc3 == 2) {
  698. static RRDSET *st = NULL;
  699. if(unlikely(!st)) {
  700. st = rrdset_create_localhost(
  701. "nfsd"
  702. , "proc3"
  703. , NULL
  704. , "nfsv3rpc"
  705. , NULL
  706. , "NFS v3 Server Remote Procedure Calls"
  707. , "calls/s"
  708. , PLUGIN_PROC_NAME
  709. , PLUGIN_PROC_MODULE_NFSD_NAME
  710. , NETDATA_CHART_PRIO_NFSD_PROC3
  711. , update_every
  712. , RRDSET_TYPE_STACKED
  713. );
  714. }
  715. else rrdset_next(st);
  716. size_t i;
  717. for(i = 0; nfsd_proc3_values[i].present ; i++) {
  718. if(unlikely(!nfsd_proc3_values[i].rd))
  719. nfsd_proc3_values[i].rd = rrddim_add(st, nfsd_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  720. rrddim_set_by_pointer(st, nfsd_proc3_values[i].rd, nfsd_proc3_values[i].value);
  721. }
  722. rrdset_done(st);
  723. }
  724. // --------------------------------------------------------------------
  725. if(do_proc4 == 2) {
  726. static RRDSET *st = NULL;
  727. if(unlikely(!st)) {
  728. st = rrdset_create_localhost(
  729. "nfsd"
  730. , "proc4"
  731. , NULL
  732. , "nfsv4rpc"
  733. , NULL
  734. , "NFS v4 Server Remote Procedure Calls"
  735. , "calls/s"
  736. , PLUGIN_PROC_NAME
  737. , PLUGIN_PROC_MODULE_NFSD_NAME
  738. , NETDATA_CHART_PRIO_NFSD_PROC4
  739. , update_every
  740. , RRDSET_TYPE_STACKED
  741. );
  742. }
  743. else rrdset_next(st);
  744. size_t i;
  745. for(i = 0; nfsd_proc4_values[i].present ; i++) {
  746. if(unlikely(!nfsd_proc4_values[i].rd))
  747. nfsd_proc4_values[i].rd = rrddim_add(st, nfsd_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  748. rrddim_set_by_pointer(st, nfsd_proc4_values[i].rd, nfsd_proc4_values[i].value);
  749. }
  750. rrdset_done(st);
  751. }
  752. // --------------------------------------------------------------------
  753. if(do_proc4ops == 2) {
  754. static RRDSET *st = NULL;
  755. if(unlikely(!st)) {
  756. st = rrdset_create_localhost(
  757. "nfsd"
  758. , "proc4ops"
  759. , NULL
  760. , "nfsv4ops"
  761. , NULL
  762. , "NFS v4 Server Operations"
  763. , "operations/s"
  764. , PLUGIN_PROC_NAME
  765. , PLUGIN_PROC_MODULE_NFSD_NAME
  766. , NETDATA_CHART_PRIO_NFSD_PROC4OPS
  767. , update_every
  768. , RRDSET_TYPE_STACKED
  769. );
  770. }
  771. else rrdset_next(st);
  772. size_t i;
  773. for(i = 0; nfsd4_ops_values[i].present ; i++) {
  774. if(unlikely(!nfsd4_ops_values[i].rd))
  775. nfsd4_ops_values[i].rd = rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
  776. rrddim_set_by_pointer(st, nfsd4_ops_values[i].rd, nfsd4_ops_values[i].value);
  777. }
  778. rrdset_done(st);
  779. }
  780. return 0;
  781. }