-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_nfs4_server(const char *instance, char **fields,
+ size_t fields_num) {
+ static int suppress_warning;
+ size_t proc4x_names_num;
+
+ switch (fields_num) {
+ case NFS4_SERVER40_NUM_PROC:
+ case NFS4_SERVER40_NUM_PROC + 19: /* NFS 4.1 */
+ case NFS4_SERVER40_NUM_PROC + 31: /* NFS 4.2 */
+ case NFS4_SERVER40_NUM_PROC + 32: /* NFS 4.2 */
+ break;
+ default:
+ if (!suppress_warning) {
+ WARNING("nfs plugin: Unexpected number of fields for "
+ "NFSv4 %s statistics: %" PRIsz ". ",
+ 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_server40_procedures_names_num) {
+ proc4x_names_num = fields_num - nfs4_server40_procedures_names_num;
+ fields += nfs4_server40_procedures_names_num;
+
+ nfs_submit_fields(4, instance, fields, proc4x_names_num,
+ nfs4_server4x_procedures_names);
+ }
+
+ return 0;
+}
+
+static int nfs_submit_nfs4_client(const char *instance, char **fields,
+ size_t fields_num) {
+ size_t proc40_names_num, proc4x_names_num;
+
+ static int suppress_warning;
+
+ 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:
+ case 55:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ proc40_names_num = 38;
+ break;
+ default:
+ if (!suppress_warning) {
+ WARNING("nfs plugin: Unexpected number of fields for NFSv4 %s "
+ "statistics: %" PRIsz ". ",
+ 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) {
+ proc4x_names_num = fields_num - proc40_names_num;
+ fields += proc40_names_num;
+
+ nfs_submit_fields(4, instance, fields, proc4x_names_num,
+ nfs4_client4x_procedures_names);
+ }
+
+ return 0;
+}
+
+static void nfs_read_linux(FILE *fh, const char *inst) {
+ char buffer[1024];
+
+ // The stats line is prefixed with type and number of fields, thus plus 2
+ char *fields[MAX(NFS4_SERVER_MAX_PROC, NFS4_CLIENT_MAX_PROC) + 2];
+ 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 && report_v2) {
+ 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 && report_v3) {
+ 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 && report_v4) {
+ if (inst[0] == 's')
+ nfs_submit_nfs4_server(inst, fields + 2, (size_t)(fields_num - 2));
+ } else if (strcmp(fields[0], "proc4") == 0 && report_v4) {
+ if (inst[0] == 'c')
+ nfs_submit_nfs4_client(inst, fields + 2, (size_t)(fields_num - 2));
+ }
+ } /* while (fgets) */