diff options
author | Matthias Eble <psychotrahe@users.sourceforge.net> | 2010-11-15 23:59:35 +0100 |
---|---|---|
committer | Matthias Eble <psychotrahe@users.sourceforge.net> | 2010-11-15 23:59:35 +0100 |
commit | 77f2c84d2f599d86a60586494169dcab17853e3a (patch) | |
tree | e964e05b70aff5f5b9ee7ff457b7c165db5f66aa /plugins | |
parent | 896962a1ad1b7d7c75d42c565b06cc799feb0a7c (diff) | |
download | monitoring-plugins-77f2c84d2f599d86a60586494169dcab17853e3a.tar.gz |
Fix check_disk free space calculation if blocksizes differ within a disk group (Bekar - #2973603)
Various values (dused_pct, dfree_pct, inodes_free, inodes_total, ...) are now carried in
the parameter_list structure. Assignments have been moved to a subroutine preventing
code redundancies.
Group metrics are now calculated based on units rather than blocks. This fixes freespace calculation
when blocksizes differ within a group.
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/check_disk.c | 175 |
1 files changed, 94 insertions, 81 deletions
diff --git a/plugins/check_disk.c b/plugins/check_disk.c index 851d800d..f8897647 100644 --- a/plugins/check_disk.c +++ b/plugins/check_disk.c | |||
@@ -122,6 +122,8 @@ void print_help (void); | |||
122 | void print_usage (void); | 122 | void print_usage (void); |
123 | double calculate_percent(uintmax_t, uintmax_t); | 123 | double calculate_percent(uintmax_t, uintmax_t); |
124 | void stat_path (struct parameter_list *p); | 124 | void stat_path (struct parameter_list *p); |
125 | void get_stats (struct parameter_list *p, struct fs_usage *fsp); | ||
126 | void get_path_stats (struct parameter_list *p, struct fs_usage *fsp); | ||
125 | 127 | ||
126 | double w_dfp = -1.0; | 128 | double w_dfp = -1.0; |
127 | double c_dfp = -1.0; | 129 | double c_dfp = -1.0; |
@@ -148,6 +150,7 @@ char *crit_freeinodes_percent = NULL; | |||
148 | int path_selected = FALSE; | 150 | int path_selected = FALSE; |
149 | char *group = NULL; | 151 | char *group = NULL; |
150 | struct stat *stat_buf; | 152 | struct stat *stat_buf; |
153 | struct name_list *seen = NULL; | ||
151 | 154 | ||
152 | 155 | ||
153 | int | 156 | int |
@@ -160,10 +163,6 @@ main (int argc, char **argv) | |||
160 | char *perf; | 163 | char *perf; |
161 | char *preamble; | 164 | char *preamble; |
162 | double inode_space_pct; | 165 | double inode_space_pct; |
163 | uintmax_t total, available, available_to_root, used; | ||
164 | double dfree_pct = -1, dused_pct = -1; | ||
165 | double dused_units, dfree_units, dtotal_units; | ||
166 | double dused_inodes_percent, dfree_inodes_percent; | ||
167 | double warning_high_tide; | 166 | double warning_high_tide; |
168 | double critical_high_tide; | 167 | double critical_high_tide; |
169 | int temp_result; | 168 | int temp_result; |
@@ -171,7 +170,6 @@ main (int argc, char **argv) | |||
171 | struct mount_entry *me; | 170 | struct mount_entry *me; |
172 | struct fs_usage fsp, tmpfsp; | 171 | struct fs_usage fsp, tmpfsp; |
173 | struct parameter_list *temp_list, *path; | 172 | struct parameter_list *temp_list, *path; |
174 | struct name_list *seen = NULL; | ||
175 | 173 | ||
176 | preamble = strdup (" - free space:"); | 174 | preamble = strdup (" - free space:"); |
177 | output = strdup (""); | 175 | output = strdup (""); |
@@ -237,45 +235,8 @@ main (int argc, char **argv) | |||
237 | /* Remove filesystems already seen */ | 235 | /* Remove filesystems already seen */ |
238 | if (np_seen_name(seen, me->me_mountdir)) { | 236 | if (np_seen_name(seen, me->me_mountdir)) { |
239 | continue; | 237 | continue; |
240 | } else { | 238 | } |
241 | if (path->group != NULL) { | 239 | np_add_name(&seen, me->me_mountdir); |
242 | /* find all group members */ | ||
243 | fsp.fsu_blocksize = 0; | ||
244 | fsp.fsu_blocks = 0; | ||
245 | fsp.fsu_bfree = 0; | ||
246 | fsp.fsu_bavail = 0; | ||
247 | fsp.fsu_files = 0; | ||
248 | fsp.fsu_ffree = 0; | ||
249 | |||
250 | |||
251 | for (temp_list = path_select_list; temp_list; temp_list=temp_list->name_next) { | ||
252 | if (temp_list->group && ! (strcmp(temp_list->group, path->group))) { | ||
253 | |||
254 | stat_path(path); | ||
255 | get_fs_usage (temp_list->best_match->me_mountdir, temp_list->best_match->me_devname, &tmpfsp); | ||
256 | |||
257 | /* possibly differing blocksizes if disks are grouped. Calculating average */ | ||
258 | fsp.fsu_blocksize = (fsp.fsu_blocksize * fsp.fsu_blocks + tmpfsp.fsu_blocksize * tmpfsp.fsu_blocks) / \ | ||
259 | (fsp.fsu_blocks + tmpfsp.fsu_blocks); /* Size of a block. */ | ||
260 | fsp.fsu_blocks += tmpfsp.fsu_blocks; /* Total blocks. */ | ||
261 | fsp.fsu_bfree += tmpfsp.fsu_bfree; /* Free blocks available to superuser. */ | ||
262 | /* Gnulib workaround - see comment about it a few lines below */ | ||
263 | fsp.fsu_bavail += (tmpfsp.fsu_bavail > tmpfsp.fsu_bfree ? 0 : tmpfsp.fsu_bavail); /* Free blocks available to non-superuser. */ | ||
264 | fsp.fsu_files += tmpfsp.fsu_files; /* Total file nodes. */ | ||
265 | fsp.fsu_ffree += tmpfsp.fsu_ffree; /* Free file nodes. */ | ||
266 | |||
267 | if (verbose >= 3) | ||
268 | printf("Group %s: add %llu blocks (%s) \n", path->group, tmpfsp.fsu_bavail, temp_list->name); | ||
269 | /* printf("Group %s: add %u blocks (%s)\n", temp_list->name); *//* path->group, tmpfsp.fsu_bavail, temp_list->name); */ | ||
270 | |||
271 | np_add_name(&seen, temp_list->best_match->me_mountdir); | ||
272 | } | ||
273 | } | ||
274 | /* modify devname and mountdir for output */ | ||
275 | me->me_mountdir = me->me_devname = path->group; | ||
276 | } else | ||
277 | np_add_name(&seen, me->me_mountdir); | ||
278 | } | ||
279 | 240 | ||
280 | if (path->group == NULL) { | 241 | if (path->group == NULL) { |
281 | /* Skip remote filesystems if we're not interested in them */ | 242 | /* Skip remote filesystems if we're not interested in them */ |
@@ -301,55 +262,36 @@ main (int argc, char **argv) | |||
301 | } | 262 | } |
302 | 263 | ||
303 | if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { | 264 | if (fsp.fsu_blocks && strcmp ("none", me->me_mountdir)) { |
304 | total = fsp.fsu_blocks; | 265 | get_stats (path, &fsp); |
305 | /* 2007-12-08 - Workaround for Gnulib reporting insanely high available | ||
306 | * space on BSD (the actual value should be negative but fsp.fsu_bavail | ||
307 | * is unsigned) */ | ||
308 | available = fsp.fsu_bavail > fsp.fsu_bfree ? 0 : fsp.fsu_bavail; | ||
309 | available_to_root = fsp.fsu_bfree; | ||
310 | used = total - available_to_root; | ||
311 | |||
312 | if (verbose >= 3) | ||
313 | printf ("For %s, total=%llu, available=%llu, available_to_root=%llu, used=%llu, fsp.fsu_files=%llu, fsp.fsu_ffree=%llu\n", | ||
314 | me->me_mountdir, total, available, available_to_root, used, fsp.fsu_files, fsp.fsu_ffree); | ||
315 | |||
316 | dused_pct = calculate_percent( used, used + available ); /* used + available can never be > uintmax */ | ||
317 | |||
318 | dfree_pct = 100 - dused_pct; | ||
319 | dused_units = used*fsp.fsu_blocksize/mult; | ||
320 | dfree_units = available*fsp.fsu_blocksize/mult; | ||
321 | dtotal_units = total*fsp.fsu_blocksize/mult; | ||
322 | dused_inodes_percent = calculate_percent(fsp.fsu_files - fsp.fsu_ffree, fsp.fsu_files); | ||
323 | dfree_inodes_percent = 100 - dused_inodes_percent; | ||
324 | 266 | ||
325 | if (verbose >= 3) { | 267 | if (verbose >= 3) { |
326 | printf ("For %s, used_pct=%g free_pct=%g used_units=%g free_units=%g total_units=%g used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%llu mult=%llu\n", | 268 | printf ("For %s, used_pct=%g free_pct=%g used_units=%g free_units=%g total_units=%g used_inodes_pct=%g free_inodes_pct=%g fsp.fsu_blocksize=%llu mult=%llu\n", |
327 | me->me_mountdir, dused_pct, dfree_pct, dused_units, dfree_units, dtotal_units, dused_inodes_percent, dfree_inodes_percent, fsp.fsu_blocksize, mult); | 269 | me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units, path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult); |
328 | } | 270 | } |
329 | 271 | ||
330 | /* Threshold comparisons */ | 272 | /* Threshold comparisons */ |
331 | 273 | ||
332 | temp_result = get_status(dfree_units, path->freespace_units); | 274 | temp_result = get_status(path->dfree_units, path->freespace_units); |
333 | if (verbose >=3) printf("Freespace_units result=%d\n", temp_result); | 275 | if (verbose >=3) printf("Freespace_units result=%d\n", temp_result); |
334 | disk_result = max_state( disk_result, temp_result ); | 276 | disk_result = max_state( disk_result, temp_result ); |
335 | 277 | ||
336 | temp_result = get_status(dfree_pct, path->freespace_percent); | 278 | temp_result = get_status(path->dfree_pct, path->freespace_percent); |
337 | if (verbose >=3) printf("Freespace%% result=%d\n", temp_result); | 279 | if (verbose >=3) printf("Freespace%% result=%d\n", temp_result); |
338 | disk_result = max_state( disk_result, temp_result ); | 280 | disk_result = max_state( disk_result, temp_result ); |
339 | 281 | ||
340 | temp_result = get_status(dused_units, path->usedspace_units); | 282 | temp_result = get_status(path->dused_units, path->usedspace_units); |
341 | if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result); | 283 | if (verbose >=3) printf("Usedspace_units result=%d\n", temp_result); |
342 | disk_result = max_state( disk_result, temp_result ); | 284 | disk_result = max_state( disk_result, temp_result ); |
343 | 285 | ||
344 | temp_result = get_status(dused_pct, path->usedspace_percent); | 286 | temp_result = get_status(path->dused_pct, path->usedspace_percent); |
345 | if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result); | 287 | if (verbose >=3) printf("Usedspace_percent result=%d\n", temp_result); |
346 | disk_result = max_state( disk_result, temp_result ); | 288 | disk_result = max_state( disk_result, temp_result ); |
347 | 289 | ||
348 | temp_result = get_status(dused_inodes_percent, path->usedinodes_percent); | 290 | temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent); |
349 | if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result); | 291 | if (verbose >=3) printf("Usedinodes_percent result=%d\n", temp_result); |
350 | disk_result = max_state( disk_result, temp_result ); | 292 | disk_result = max_state( disk_result, temp_result ); |
351 | 293 | ||
352 | temp_result = get_status(dfree_inodes_percent, path->freeinodes_percent); | 294 | temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent); |
353 | if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result); | 295 | if (verbose >=3) printf("Freeinodes_percent result=%d\n", temp_result); |
354 | disk_result = max_state( disk_result, temp_result ); | 296 | disk_result = max_state( disk_result, temp_result ); |
355 | 297 | ||
@@ -365,26 +307,26 @@ main (int argc, char **argv) | |||
365 | critical_high_tide = UINT_MAX; | 307 | critical_high_tide = UINT_MAX; |
366 | 308 | ||
367 | if (path->freespace_units->warning != NULL) { | 309 | if (path->freespace_units->warning != NULL) { |
368 | warning_high_tide = dtotal_units - path->freespace_units->warning->end; | 310 | warning_high_tide = path->dtotal_units - path->freespace_units->warning->end; |
369 | } | 311 | } |
370 | if (path->freespace_percent->warning != NULL) { | 312 | if (path->freespace_percent->warning != NULL) { |
371 | warning_high_tide = abs( min( (double) warning_high_tide, (double) (1.0 - path->freespace_percent->warning->end/100)*dtotal_units )); | 313 | warning_high_tide = abs( min( (double) warning_high_tide, (double) (1.0 - path->freespace_percent->warning->end/100)*path->dtotal_units )); |
372 | } | 314 | } |
373 | if (path->freespace_units->critical != NULL) { | 315 | if (path->freespace_units->critical != NULL) { |
374 | critical_high_tide = dtotal_units - path->freespace_units->critical->end; | 316 | critical_high_tide = path->dtotal_units - path->freespace_units->critical->end; |
375 | } | 317 | } |
376 | if (path->freespace_percent->critical != NULL) { | 318 | if (path->freespace_percent->critical != NULL) { |
377 | critical_high_tide = abs( min( (double) critical_high_tide, (double) (1.0 - path->freespace_percent->critical->end/100)*dtotal_units )); | 319 | critical_high_tide = abs( min( (double) critical_high_tide, (double) (1.0 - path->freespace_percent->critical->end/100)*path->dtotal_units )); |
378 | } | 320 | } |
379 | 321 | ||
380 | /* Nb: *_high_tide are unset when == UINT_MAX */ | 322 | /* Nb: *_high_tide are unset when == UINT_MAX */ |
381 | asprintf (&perf, "%s %s", perf, | 323 | asprintf (&perf, "%s %s", perf, |
382 | perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, | 324 | perfdata ((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, |
383 | dused_units, units, | 325 | path->dused_units, units, |
384 | (warning_high_tide != UINT_MAX ? TRUE : FALSE), warning_high_tide, | 326 | (warning_high_tide != UINT_MAX ? TRUE : FALSE), warning_high_tide, |
385 | (critical_high_tide != UINT_MAX ? TRUE : FALSE), critical_high_tide, | 327 | (critical_high_tide != UINT_MAX ? TRUE : FALSE), critical_high_tide, |
386 | TRUE, 0, | 328 | TRUE, 0, |
387 | TRUE, dtotal_units)); | 329 | TRUE, path->dtotal_units)); |
388 | 330 | ||
389 | if (disk_result==STATE_OK && erronly && !verbose) | 331 | if (disk_result==STATE_OK && erronly && !verbose) |
390 | continue; | 332 | continue; |
@@ -392,13 +334,13 @@ main (int argc, char **argv) | |||
392 | asprintf (&output, "%s %s %.0f %s (%.0f%%", | 334 | asprintf (&output, "%s %s %.0f %s (%.0f%%", |
393 | output, | 335 | output, |
394 | (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, | 336 | (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, |
395 | dfree_units, | 337 | path->dfree_units, |
396 | units, | 338 | units, |
397 | dfree_pct); | 339 | path->dfree_pct); |
398 | if (dused_inodes_percent < 0) { | 340 | if (path->dused_inodes_percent < 0) { |
399 | asprintf(&output, "%s inode=-);", output); | 341 | asprintf(&output, "%s inode=-);", output); |
400 | } else { | 342 | } else { |
401 | asprintf(&output, "%s inode=%.0f%%);", output, dfree_inodes_percent ); | 343 | asprintf(&output, "%s inode=%.0f%%);", output, path->dfree_inodes_percent ); |
402 | } | 344 | } |
403 | 345 | ||
404 | /* TODO: Need to do a similar debug line | 346 | /* TODO: Need to do a similar debug line |
@@ -996,3 +938,74 @@ stat_path (struct parameter_list *p) | |||
996 | die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno)); | 938 | die (STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno)); |
997 | } | 939 | } |
998 | } | 940 | } |
941 | |||
942 | |||
943 | void | ||
944 | get_stats (struct parameter_list *p, struct fs_usage *fsp) { | ||
945 | struct parameter_list *p_list; | ||
946 | struct fs_usage tmpfsp; | ||
947 | int first = 1; | ||
948 | |||
949 | if (p->group == NULL) { | ||
950 | get_path_stats(p,fsp); | ||
951 | } else { | ||
952 | /* find all group members */ | ||
953 | for (p_list = path_select_list; p_list; p_list=p_list->name_next) { | ||
954 | if (p_list->group && ! (strcmp(p_list->group, p->group))) { | ||
955 | stat_path(p_list); | ||
956 | get_fs_usage (p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp); | ||
957 | get_path_stats(p_list, &tmpfsp); | ||
958 | if (verbose >= 3) | ||
959 | printf("Group %s: adding %llu blocks sized %llu, (%s) used_units=%g free_units=%g total_units=%g fsu_blocksize=%llu mult=%llu\n", | ||
960 | p_list->group, tmpfsp.fsu_bavail, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units, p_list->dfree_units, | ||
961 | p_list->dtotal_units, mult); | ||
962 | |||
963 | /* prevent counting the first FS of a group twice since its parameter_list entry | ||
964 | * is used to carry the information of all file systems of the entire group */ | ||
965 | if (! first) { | ||
966 | p->total += p_list->total; | ||
967 | p->available += p_list->available; | ||
968 | p->available_to_root += p_list->available_to_root; | ||
969 | p->used += p_list->used; | ||
970 | |||
971 | p->dused_units += p_list->dused_units; | ||
972 | p->dfree_units += p_list->dfree_units; | ||
973 | p->dtotal_units += p_list->dtotal_units; | ||
974 | p->inodes_total += p_list->inodes_total; | ||
975 | p->inodes_free += p_list->inodes_free; | ||
976 | } | ||
977 | first = 0; | ||
978 | } | ||
979 | if (verbose >= 3) | ||
980 | printf("Group %s now has: used_units=%g free_units=%g total_units=%g fsu_blocksize=%llu mult=%llu\n", | ||
981 | p->group, tmpfsp.fsu_bavail, tmpfsp.fsu_blocksize, p->best_match->me_mountdir, p->dused_units, | ||
982 | p->dfree_units, p->dtotal_units, mult); | ||
983 | } | ||
984 | /* modify devname and mountdir for output */ | ||
985 | p->best_match->me_mountdir = p->best_match->me_devname = p->group; | ||
986 | } | ||
987 | /* finally calculate percentages for either plain FS or summed up group */ | ||
988 | p->dused_pct = calculate_percent( p->used, p->used + p->available ); /* used + available can never be > uintmax */ | ||
989 | p->dfree_pct = 100 - p->dused_pct; | ||
990 | p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total); | ||
991 | p->dfree_inodes_percent = 100 - p->dused_inodes_percent; | ||
992 | |||
993 | } | ||
994 | |||
995 | void | ||
996 | get_path_stats (struct parameter_list *p, struct fs_usage *fsp) { | ||
997 | p->total = fsp->fsu_blocks; | ||
998 | /* 2007-12-08 - Workaround for Gnulib reporting insanely high available | ||
999 | * space on BSD (the actual value should be negative but fsp->fsu_bavail | ||
1000 | * is unsigned) */ | ||
1001 | p->available = fsp->fsu_bavail > fsp->fsu_bfree ? 0 : fsp->fsu_bavail; | ||
1002 | p->available_to_root = fsp->fsu_bfree; | ||
1003 | p->used = p->total - p->available_to_root; | ||
1004 | |||
1005 | p->dused_units = p->used*fsp->fsu_blocksize/mult; | ||
1006 | p->dfree_units = p->available*fsp->fsu_blocksize/mult; | ||
1007 | p->dtotal_units = p->total*fsp->fsu_blocksize/mult; | ||
1008 | p->inodes_total = fsp->fsu_files; /* Total file nodes. */ | ||
1009 | p->inodes_free = fsp->fsu_ffree; /* Free file nodes. */ | ||
1010 | np_add_name(&seen, p->best_match->me_mountdir); | ||
1011 | } | ||