summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorMatthias Eble <psychotrahe@users.sourceforge.net>2010-11-15 23:59:35 +0100
committerMatthias Eble <psychotrahe@users.sourceforge.net>2010-11-15 23:59:35 +0100
commit77f2c84d2f599d86a60586494169dcab17853e3a (patch)
treee964e05b70aff5f5b9ee7ff457b7c165db5f66aa /plugins
parent896962a1ad1b7d7c75d42c565b06cc799feb0a7c (diff)
downloadmonitoring-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.c175
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);
122void print_usage (void); 122void print_usage (void);
123double calculate_percent(uintmax_t, uintmax_t); 123double calculate_percent(uintmax_t, uintmax_t);
124void stat_path (struct parameter_list *p); 124void stat_path (struct parameter_list *p);
125void get_stats (struct parameter_list *p, struct fs_usage *fsp);
126void get_path_stats (struct parameter_list *p, struct fs_usage *fsp);
125 127
126double w_dfp = -1.0; 128double w_dfp = -1.0;
127double c_dfp = -1.0; 129double c_dfp = -1.0;
@@ -148,6 +150,7 @@ char *crit_freeinodes_percent = NULL;
148int path_selected = FALSE; 150int path_selected = FALSE;
149char *group = NULL; 151char *group = NULL;
150struct stat *stat_buf; 152struct stat *stat_buf;
153struct name_list *seen = NULL;
151 154
152 155
153int 156int
@@ -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
943void
944get_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
995void
996get_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}