-static void nfs_read_linux (FILE *fh, char *inst)
-{
- char buffer[1024];
-
- char *fields[48];
- int fields_num = 0;
-
- if (fh == NULL)
- return;
-
- while (fgets (buffer, sizeof (buffer), fh) != NULL)
- {
- fields_num = strsplit (buffer,
- fields, STATIC_ARRAY_SIZE (fields));
-
- if (fields_num < 3)
- continue;
-
- if (strcmp (fields[0], "proc2") == 0)
- {
- nfs_submit_fields (/* version = */ 2, inst,
- fields + 2, (size_t) (fields_num - 2),
- nfs2_procedures_names,
- nfs2_procedures_names_num);
- }
- else if (strncmp (fields[0], "proc3", 5) == 0)
- {
- nfs_submit_fields (/* version = */ 3, inst,
- fields + 2, (size_t) (fields_num - 2),
- nfs3_procedures_names,
- nfs3_procedures_names_num);
- }
- } /* while (fgets) */
+static int nfs_submit_fields_safe(int nfs_version, const char *instance,
+ char **fields, size_t fields_num,
+ const char **proc_names,
+ size_t proc_names_num) {
+ if (fields_num != proc_names_num) {
+ WARNING("nfs plugin: Wrong number of fields for "
+ "NFSv%i %s statistics. Expected %zu, got %zu.",
+ nfs_version, instance, proc_names_num, fields_num);
+ return (EINVAL);
+ }
+
+ nfs_submit_fields(nfs_version, instance, fields, fields_num, proc_names);
+
+ return (0);
+}
+
+static int nfs_submit_nfs4_server(const char *instance, char **fields,
+ size_t fields_num) {
+ static int suppress_warning = 0;
+
+ if (fields_num != NFS4_SERVER40_NUM_PROC &&
+ fields_num != NFS4_SERVER41_NUM_PROC) {
+ if (!suppress_warning) {
+ WARNING("nfs plugin: Unexpected number of fields for "
+ "NFSv4 %s statistics: %zu. ",
+ instance, fields_num);
+ }
+
+ if (fields_num > NFS4_SERVER_MAX_PROC) {
+ fields_num = NFS4_SERVER_MAX_PROC;
+ suppress_warning = 1;
+ } else {
+ return (EINVAL);
+ }
+ }
+
+ nfs_submit_fields(4, instance, fields, nfs4_server40_procedures_names_num,
+ nfs4_server40_procedures_names);
+
+ if (fields_num >= NFS4_SERVER41_NUM_PROC) {
+ fields += nfs4_server40_procedures_names_num;
+
+ nfs_submit_fields(4, instance, fields, nfs4_server41_procedures_names_num,
+ nfs4_server41_procedures_names);
+ }
+
+ return (0);
+}
+
+static int nfs_submit_nfs4_client(const char *instance, char **fields,
+ size_t fields_num) {
+ size_t proc40_names_num, proc41_names_num;
+
+ static int suppress_warning = 0;
+
+ switch (fields_num) {
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ /* 4.0-only configuration */
+ proc40_names_num = fields_num;
+ break;
+ case 40:
+ case 41:
+ proc40_names_num = 35;
+ break;
+ case 42:
+ case 44:
+ proc40_names_num = 36;
+ break;
+ case 46:
+ case 47:
+ case 51:
+ case 53:
+ proc40_names_num = 37;
+ break;
+ case 54:
+ proc40_names_num = 38;
+ break;
+ default:
+ if (!suppress_warning) {
+ WARNING("nfs plugin: Unexpected number of "
+ "fields for NFSv4 %s "
+ "statistics: %zu. ",
+ instance, fields_num);
+ }
+
+ if (fields_num > 34) {
+ /* safe fallback to basic nfs40 procedures */
+ fields_num = 34;
+ proc40_names_num = 34;
+
+ suppress_warning = 1;
+ } else {
+ return (EINVAL);
+ }
+ }
+
+ nfs_submit_fields(4, instance, fields, proc40_names_num,
+ nfs4_client40_procedures_names);
+
+ if (fields_num > proc40_names_num) {
+ proc41_names_num = fields_num - proc40_names_num;
+ fields += proc40_names_num;
+
+ nfs_submit_fields(4, instance, fields, proc41_names_num,
+ nfs4_client41_procedures_names);
+ }
+
+ return (0);
+}
+
+static void nfs_read_linux(FILE *fh, const char *inst) {
+ char buffer[1024];
+
+ char *fields[64];
+ int fields_num = 0;
+
+ if (fh == NULL)
+ return;
+
+ while (fgets(buffer, sizeof(buffer), fh) != NULL) {
+ fields_num = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields));
+
+ if (fields_num < 3)
+ continue;
+
+ if (strcmp(fields[0], "proc2") == 0) {
+ nfs_submit_fields_safe(/* version = */ 2, inst, fields + 2,
+ (size_t)(fields_num - 2), nfs2_procedures_names,
+ nfs2_procedures_names_num);
+ } else if (strncmp(fields[0], "proc3", 5) == 0) {
+ nfs_submit_fields_safe(/* version = */ 3, inst, fields + 2,
+ (size_t)(fields_num - 2), nfs3_procedures_names,
+ nfs3_procedures_names_num);
+ } else if (strcmp(fields[0], "proc4ops") == 0) {
+ if (inst[0] == 's')
+ nfs_submit_nfs4_server(inst, fields + 2, (size_t)(fields_num - 2));
+ } else if (strcmp(fields[0], "proc4") == 0) {
+ if (inst[0] == 'c')
+ nfs_submit_nfs4_client(inst, fields + 2, (size_t)(fields_num - 2));
+ }
+ } /* while (fgets) */