Imported Upstream version 20091031
[ltp-debian.git] / tools / genload / genload.c
blob0b8676016c15a3edf2adb2e1d3f9d7603ce39eba
1 /* A program to put stress on a POSIX system (stress).
3 * Copyright (C) 2001, 2002 Amos Waterland <awaterl@yahoo.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc., 59
17 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <ctype.h>
21 #include <errno.h>
22 #include <libgen.h>
23 #include <math.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <signal.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <sys/wait.h>
32 /* By default, print all messages of severity info and above. */
33 static int global_debug = 2;
35 /* By default, just print warning for non-critical errors. */
36 static int global_ignore = 1;
38 /* By default, retry on non-critical errors every 50ms. */
39 static int global_retry = 50000;
41 /* By default, use this as backoff coefficient for good fork throughput. */
42 static int global_backoff = 3000;
44 /* By default, do not timeout. */
45 static int global_timeout = 0;
47 /* Name of this program */
48 static char *global_progname = PACKAGE;
50 /* By default, do not hang after allocating memory. */
51 static int global_vmhang = 0;
53 /* Implemention of runtime-selectable severity message printing. */
54 #define dbg if (global_debug >= 3) \
55 fprintf (stdout, "%s: debug: (%d) ", global_progname, __LINE__), \
56 fprintf
57 #define out if (global_debug >= 2) \
58 fprintf (stdout, "%s: info: ", global_progname), \
59 fprintf
60 #define wrn if (global_debug >= 1) \
61 fprintf (stderr, "%s: warn: (%d) ", global_progname, __LINE__), \
62 fprintf
63 #define err if (global_debug >= 0) \
64 fprintf (stderr, "%s: error: (%d) ", global_progname, __LINE__), \
65 fprintf
67 /* Implementation of check for option argument correctness. */
68 #define assert_arg(A) \
69 if (++i == argc || ((arg = argv[i])[0] == '-' && \
70 !isdigit ((int)arg[1]) )) \
71 { \
72 err (stderr, "missing argument to option '%s'\n", A); \
73 exit (1); \
76 /* Prototypes for utility functions. */
77 int usage (int status);
78 int version (int status);
79 long long atoll_s (const char *nptr);
80 long long atoll_b (const char *nptr);
82 /* Prototypes for the worker functions. */
83 int hogcpu (long long forks);
84 int hogio (long long forks);
85 int hogvm (long long forks, long long chunks, long long bytes);
86 int hoghdd (long long forks, int clean, long long files, long long bytes);
88 int
89 main (int argc, char **argv)
91 int i, pid, children = 0, retval = 0;
92 long starttime, stoptime, runtime;
94 /* Variables that indicate which options have been selected. */
95 int do_dryrun = 0;
96 int do_timeout = 0;
97 int do_cpu = 0; /* Default to 1 fork. */
98 long long do_cpu_forks = 1;
99 int do_io = 0; /* Default to 1 fork. */
100 long long do_io_forks = 1;
101 int do_vm = 0; /* Default to 1 fork, 1 chunk of 256MB. */
102 long long do_vm_forks = 1;
103 long long do_vm_chunks = 1;
104 long long do_vm_bytes = 256 * 1024 * 1024;
105 int do_hdd = 0; /* Default to 1 fork, clean, 1 file of 1GB. */
106 long long do_hdd_forks = 1;
107 int do_hdd_clean = 0;
108 long long do_hdd_files = 1;
109 long long do_hdd_bytes = 1024 * 1024 * 1024;
111 /* Record our start time. */
112 if ((starttime = time (NULL)) == -1)
114 err (stderr, "failed to acquire current time\n");
115 exit (1);
118 /* SuSv3 does not define any error conditions for this function. */
119 global_progname = basename (argv[0]);
121 /* For portability, parse command line options without getopt_long. */
122 for (i = 1; i < argc; i++)
124 char *arg = argv[i];
126 if (strcmp (arg, "--help") == 0 || strcmp (arg, "-?") == 0)
128 usage (0);
130 else if (strcmp (arg, "--version") == 0)
132 version (0);
134 else if (strcmp (arg, "--verbose") == 0 || strcmp (arg, "-v") == 0)
136 global_debug = 3;
138 else if (strcmp (arg, "--quiet") == 0 || strcmp (arg, "-q") == 0)
140 global_debug = 0;
142 else if (strcmp (arg, "--dry-run") == 0 || strcmp (arg, "-n") == 0)
144 do_dryrun = 1;
146 else if (strcmp (arg, "--no-retry") == 0)
148 global_ignore = 0;
149 dbg (stdout, "turning off ignore of non-critical errors");
151 else if (strcmp (arg, "--retry-delay") == 0)
153 assert_arg ("--retry-delay");
154 global_retry = atoll (arg);
155 dbg (stdout, "setting retry delay to %dus\n", global_retry);
157 else if (strcmp (arg, "--backoff") == 0)
159 assert_arg ("--backoff");
160 global_backoff = atoll (arg);
161 if (global_backoff < 0)
163 err (stderr, "invalid backoff factor: %i\n", global_backoff);
164 exit (1);
166 dbg (stdout, "setting backoff coeffient to %dus\n", global_backoff);
168 else if (strcmp (arg, "--timeout") == 0 || strcmp (arg, "-t") == 0)
170 do_timeout = 1;
171 assert_arg ("--timeout");
172 global_timeout = atoll_s (arg);
173 dbg (stdout, "setting timeout to %ds\n", global_timeout);
175 else if (strcmp (arg, "--cpu") == 0 || strcmp (arg, "-c") == 0)
177 do_cpu = 1;
178 assert_arg ("--cpu");
179 do_cpu_forks = atoll_b (arg);
181 else if (strcmp (arg, "--io") == 0 || strcmp (arg, "-i") == 0)
183 do_io = 1;
184 assert_arg ("--io");
185 do_io_forks = atoll_b (arg);
187 else if (strcmp (arg, "--vm") == 0 || strcmp (arg, "-m") == 0)
189 do_vm = 1;
190 assert_arg ("--vm");
191 do_vm_forks = atoll_b (arg);
193 else if (strcmp (arg, "--vm-chunks") == 0)
195 assert_arg ("--vm-chunks");
196 do_vm_chunks = atoll_b (arg);
198 else if (strcmp (arg, "--vm-bytes") == 0)
200 assert_arg ("--vm-bytes");
201 do_vm_bytes = atoll_b (arg);
203 else if (strcmp (arg, "--vm-hang") == 0)
205 global_vmhang = 1;
207 else if (strcmp (arg, "--hdd") == 0 || strcmp (arg, "-d") == 0)
209 do_hdd = 1;
210 assert_arg ("--hdd");
211 do_hdd_forks = atoll_b (arg);
213 else if (strcmp (arg, "--hdd-noclean") == 0)
215 do_hdd_clean = 2;
217 else if (strcmp (arg, "--hdd-files") == 0)
219 assert_arg ("--hdd-files");
220 do_hdd_files = atoll_b (arg);
222 else if (strcmp (arg, "--hdd-bytes") == 0)
224 assert_arg ("--hdd-bytes");
225 do_hdd_bytes = atoll_b (arg);
227 else
229 err (stderr, "unrecognized option: %s\n", arg);
230 exit (1);
234 /* Hog CPU option. */
235 if (do_cpu)
237 out (stdout, "dispatching %lli hogcpu forks\n", do_cpu_forks);
239 switch (pid = fork ())
241 case 0: /* child */
242 if (do_dryrun)
243 exit (0);
244 exit (hogcpu (do_cpu_forks));
245 case -1: /* error */
246 err (stderr, "hogcpu dispatcher fork failed\n");
247 exit (1);
248 default: /* parent */
249 children++;
250 dbg (stdout, "--> hogcpu dispatcher forked (%i)\n", pid);
254 /* Hog I/O option. */
255 if (do_io)
257 out (stdout, "dispatching %lli hogio forks\n", do_io_forks);
259 switch (pid = fork ())
261 case 0: /* child */
262 if (do_dryrun)
263 exit (0);
264 exit (hogio (do_io_forks));
265 case -1: /* error */
266 err (stderr, "hogio dispatcher fork failed\n");
267 exit (1);
268 default: /* parent */
269 children++;
270 dbg (stdout, "--> hogio dispatcher forked (%i)\n", pid);
274 /* Hog VM option. */
275 if (do_vm)
277 out (stdout,
278 "dispatching %lli hogvm forks, each %lli chunks of %lli bytes\n",
279 do_vm_forks, do_vm_chunks, do_vm_bytes);
281 switch (pid = fork ())
283 case 0: /* child */
284 if (do_dryrun)
285 exit (0);
286 exit (hogvm (do_vm_forks, do_vm_chunks, do_vm_bytes));
287 case -1: /* error */
288 err (stderr, "hogvm dispatcher fork failed\n");
289 exit (1);
290 default: /* parent */
291 children++;
292 dbg (stdout, "--> hogvm dispatcher forked (%i)\n", pid);
296 /* Hog HDD option. */
297 if (do_hdd)
299 out (stdout, "dispatching %lli hoghdd forks, each %lli files of "
300 "%lli bytes\n", do_hdd_forks, do_hdd_files, do_hdd_bytes);
302 switch (pid = fork ())
304 case 0: /* child */
305 if (do_dryrun)
306 exit (0);
307 exit (hoghdd
308 (do_hdd_forks, do_hdd_clean, do_hdd_files, do_hdd_bytes));
309 case -1: /* error */
310 err (stderr, "hoghdd dispatcher fork failed\n");
311 exit (1);
312 default: /* parent */
313 children++;
314 dbg (stdout, "--> hoghdd dispatcher forked (%i)\n", pid);
318 /* We have no work to do, so bail out. */
319 if (children == 0)
320 usage (0);
322 /* Wait for our children to exit. */
323 while (children)
325 int status, ret;
327 if ((pid = wait (&status)) > 0)
329 if ((WIFEXITED (status)) != 0)
331 if ((ret = WEXITSTATUS (status)) != 0)
333 err (stderr, "dispatcher %i returned error %i\n", pid, ret);
334 retval += ret;
336 else
338 dbg (stdout, "<-- dispatcher return (%i)\n", pid);
341 else
343 err (stderr, "dispatcher did not exit normally\n");
344 ++retval;
347 --children;
349 else
351 dbg (stdout, "wait() returned error: %s\n", strerror (errno));
352 err (stderr, "detected missing dispatcher children\n");
353 ++retval;
354 break;
358 /* Record our stop time. */
359 if ((stoptime = time (NULL)) == -1)
361 err (stderr, "failed to acquire current time\n");
362 exit (1);
365 /* Calculate our runtime. */
366 runtime = stoptime - starttime;
368 /* Print final status message. */
369 if (retval)
371 err (stderr, "failed run completed in %lis\n", runtime);
373 else
375 out (stdout, "successful run completed in %lis\n", runtime);
378 exit (retval);
382 usage (int status)
384 char *mesg =
385 "`%s' imposes certain types of compute stress on your system\n\n"
386 "Usage: %s [OPTION [ARG]] ...\n\n"
387 " -?, --help show this help statement\n"
388 " --version show version statement\n"
389 " -v, --verbose be verbose\n"
390 " -q, --quiet be quiet\n"
391 " -n, --dry-run show what would have been done\n"
392 " --no-retry exit rather than retry non-critical errors\n"
393 " --retry-delay n wait n us before continuing past error\n"
394 " -t, --timeout n timeout after n seconds\n"
395 " --backoff n wait for factor of n us before starting work\n"
396 " -c, --cpu n spawn n procs spinning on sqrt()\n"
397 " -i, --io n spawn n procs spinning on sync()\n"
398 " -m, --vm n spawn n procs spinning on malloc()\n"
399 " --vm-chunks c malloc c chunks (default is 1)\n"
400 " --vm-bytes b malloc chunks of b bytes (default is 256MB)\n"
401 " --vm-hang hang in a sleep loop after memory allocated\n"
402 " -d, --hdd n spawn n procs spinning on write()\n"
403 " --hdd-noclean do not unlink file to which random data written\n"
404 " --hdd-files f write to f files (default is 1)\n"
405 " --hdd-bytes b write b bytes (default is 1GB)\n\n"
406 "Infinity is denoted with 0. For -m, -d: n=0 means infinite redo,\n"
407 "n<0 means redo abs(n) times. Valid suffixes are m,h,d,y for time;\n"
408 "k,m,g for size.\n\n";
410 fprintf (stdout, mesg, global_progname, global_progname);
412 if (status <= 0)
413 exit (-1 * status);
415 return 0;
419 version (int status)
421 char *mesg = "%s %s\n";
423 fprintf (stdout, mesg, global_progname, VERSION);
425 if (status <= 0)
426 exit (-1 * status);
428 return 0;
431 /* Convert a string representation of a number with an optional size suffix
432 * to a long long.
434 long long
435 atoll_b (const char *nptr)
437 int pos;
438 char suffix;
439 long long factor = 1;
441 if ((pos = strlen (nptr) - 1) < 0)
443 err (stderr, "invalid string\n");
444 exit (1);
447 switch (suffix = nptr[pos])
449 case 'k':
450 case 'K':
451 factor = 1024;
452 break;
453 case 'm':
454 case 'M':
455 factor = 1024 * 1024;
456 break;
457 case 'g':
458 case 'G':
459 factor = 1024 * 1024 * 1024;
460 break;
461 default:
462 if (suffix < '0' || suffix > '9')
464 err (stderr, "unrecognized suffix: %c\n", suffix);
465 exit (1);
469 factor = atoll (nptr) * factor;
471 return factor;
474 /* Convert a string representation of a number with an optional time suffix
475 * to a long long.
477 long long
478 atoll_s (const char *nptr)
480 int pos;
481 char suffix;
482 long long factor = 1;
484 if ((pos = strlen (nptr) - 1) < 0)
486 err (stderr, "invalid string\n");
487 exit (1);
490 switch (suffix = nptr[pos])
492 case 's':
493 case 'S':
494 factor = 1;
495 break;
496 case 'm':
497 case 'M':
498 factor = 60;
499 break;
500 case 'h':
501 case 'H':
502 factor = 60 * 60;
503 break;
504 case 'd':
505 case 'D':
506 factor = 60 * 60 * 24;
507 break;
508 case 'y':
509 case 'Y':
510 factor = 60 * 60 * 24 * 360;
511 break;
512 default:
513 if (suffix < '0' || suffix > '9')
515 err (stderr, "unrecognized suffix: %c\n", suffix);
516 exit (1);
520 factor = atoll (nptr) * factor;
522 return factor;
526 hogcpu (long long forks)
528 long long i;
529 double d;
530 int pid, retval = 0;
532 /* Make local copies of global variables. */
533 int ignore = global_ignore;
534 int retry = global_retry;
535 int timeout = global_timeout;
536 long backoff = global_backoff * forks;
538 dbg (stdout, "using backoff sleep of %lius for hogcpu\n", backoff);
540 for (i = 0; forks == 0 || i < forks; i++)
542 switch (pid = fork ())
544 case 0: /* child */
545 alarm (timeout);
547 /* Use a backoff sleep to ensure we get good fork throughput. */
548 usleep (backoff);
550 while (1)
551 d = sqrt (rand ());
553 /* This case never falls through; alarm signal can cause exit. */
554 case -1: /* error */
555 if (ignore)
557 ++retval;
558 wrn (stderr, "hogcpu worker fork failed, continuing\n");
559 usleep (retry);
560 continue;
563 err (stderr, "hogcpu worker fork failed\n");
564 return 1;
565 default: /* parent */
566 dbg (stdout, "--> hogcpu worker forked (%i)\n", pid);
570 /* Wait for our children to exit. */
571 while (i)
573 int status, ret;
575 if ((pid = wait (&status)) > 0)
577 if ((WIFEXITED (status)) != 0)
579 if ((ret = WEXITSTATUS (status)) != 0)
581 err (stderr, "hogcpu worker %i exited %i\n", pid, ret);
582 retval += ret;
584 else
586 dbg (stdout, "<-- hogcpu worker exited (%i)\n", pid);
589 else
591 dbg (stdout, "<-- hogcpu worker signalled (%i)\n", pid);
594 --i;
596 else
598 dbg (stdout, "wait() returned error: %s\n", strerror (errno));
599 err (stderr, "detected missing hogcpu worker children\n");
600 ++retval;
601 break;
605 return retval;
609 hogio (long long forks)
611 long long i;
612 int pid, retval = 0;
614 /* Make local copies of global variables. */
615 int ignore = global_ignore;
616 int retry = global_retry;
617 int timeout = global_timeout;
618 long backoff = global_backoff * forks;
620 dbg (stdout, "using backoff sleep of %lius for hogio\n", backoff);
622 for (i = 0; forks == 0 || i < forks; i++)
624 switch (pid = fork ())
626 case 0: /* child */
627 alarm (timeout);
629 /* Use a backoff sleep to ensure we get good fork throughput. */
630 usleep (backoff);
632 while (1)
633 sync ();
635 /* This case never falls through; alarm signal can cause exit. */
636 case -1: /* error */
637 if (ignore)
639 ++retval;
640 wrn (stderr, "hogio worker fork failed, continuing\n");
641 usleep (retry);
642 continue;
645 err (stderr, "hogio worker fork failed\n");
646 return 1;
647 default: /* parent */
648 dbg (stdout, "--> hogio worker forked (%i)\n", pid);
652 /* Wait for our children to exit. */
653 while (i)
655 int status, ret;
657 if ((pid = wait (&status)) > 0)
659 if ((WIFEXITED (status)) != 0)
661 if ((ret = WEXITSTATUS (status)) != 0)
663 err (stderr, "hogio worker %i exited %i\n", pid, ret);
664 retval += ret;
666 else
668 dbg (stdout, "<-- hogio worker exited (%i)\n", pid);
671 else
673 dbg (stdout, "<-- hogio worker signalled (%i)\n", pid);
676 --i;
678 else
680 dbg (stdout, "wait() returned error: %s\n", strerror (errno));
681 err (stderr, "detected missing hogio worker children\n");
682 ++retval;
683 break;
687 return retval;
691 hogvm (long long forks, long long chunks, long long bytes)
693 long long i, j, k;
694 int pid, retval = 0;
695 char **ptr;
697 /* Make local copies of global variables. */
698 int ignore = global_ignore;
699 int retry = global_retry;
700 int timeout = global_timeout;
701 long backoff = global_backoff * forks;
703 dbg (stdout, "using backoff sleep of %lius for hogvm\n", backoff);
705 if (bytes == 0)
707 /* 512MB is guess at the largest value can than be malloced at once. */
708 bytes = 512 * 1024 * 1024;
711 for (i = 0; forks == 0 || i < forks; i++)
713 switch (pid = fork ())
715 case 0: /* child */
716 alarm (timeout);
718 /* Use a backoff sleep to ensure we get good fork throughput. */
719 usleep (backoff);
721 while (1)
723 ptr = (char **) malloc ( chunks * 2);
724 for (j = 0; chunks == 0 || j < chunks; j++)
726 if ((ptr[j] = (char *) malloc (bytes * sizeof (char))))
728 for (k = 0; k < bytes; k++)
729 ptr[j][k] = 'Z'; /* Ensure that COW happens. */
730 dbg (stdout, "hogvm worker malloced %lli bytes\n", k);
732 else if (ignore)
734 ++retval;
735 wrn (stderr, "hogvm malloc failed, continuing\n");
736 usleep (retry);
737 continue;
739 else
741 ++retval;
742 err (stderr, "hogvm malloc failed\n");
743 break;
746 if (global_vmhang && retval == 0)
748 dbg (stdout, "sleeping forever with allocated memory\n");
749 while (1)
750 sleep (1024);
752 if (retval == 0)
754 dbg (stdout,
755 "hogvm worker freeing memory and starting over\n");
756 for (j = 0; chunks == 0 || j < chunks; j++) {
757 free (ptr[j]);
759 free(ptr);
760 continue;
763 exit (retval);
766 /* This case never falls through; alarm signal can cause exit. */
767 case -1: /* error */
768 if (ignore)
770 ++retval;
771 wrn (stderr, "hogvm worker fork failed, continuing\n");
772 usleep (retry);
773 continue;
776 err (stderr, "hogvm worker fork failed\n");
777 return 1;
778 default: /* parent */
779 dbg (stdout, "--> hogvm worker forked (%i)\n", pid);
783 /* Wait for our children to exit. */
784 while (i)
786 int status, ret;
788 if ((pid = wait (&status)) > 0)
790 if ((WIFEXITED (status)) != 0)
792 if ((ret = WEXITSTATUS (status)) != 0)
794 err (stderr, "hogvm worker %i exited %i\n", pid, ret);
795 retval += ret;
797 else
799 dbg (stdout, "<-- hogvm worker exited (%i)\n", pid);
802 else
804 dbg (stdout, "<-- hogvm worker signalled (%i)\n", pid);
807 --i;
809 else
811 dbg (stdout, "wait() returned error: %s\n", strerror (errno));
812 err (stderr, "detected missing hogvm worker children\n");
813 ++retval;
814 break;
818 return retval;
822 hoghdd (long long forks, int clean, long long files, long long bytes)
824 long long i, j;
825 int fd, pid, retval = 0;
826 int chunk = (1024 * 1024) - 1; /* Minimize slow writing. */
827 char buff[chunk];
829 /* Make local copies of global variables. */
830 int ignore = global_ignore;
831 int retry = global_retry;
832 int timeout = global_timeout;
833 long backoff = global_backoff * forks;
835 /* Initialize buffer with some random ASCII data. */
836 dbg (stdout, "seeding buffer with random data\n");
837 for (i = 0; i < chunk - 1; i++)
839 j = rand ();
840 j = (j < 0) ? -j : j;
841 j %= 95;
842 j += 32;
843 buff[i] = j;
845 buff[i] = '\n';
847 dbg (stdout, "using backoff sleep of %lius for hoghdd\n", backoff);
849 for (i = 0; forks == 0 || i < forks; i++)
851 switch (pid = fork ())
853 case 0: /* child */
854 alarm (timeout);
856 /* Use a backoff sleep to ensure we get good fork throughput. */
857 usleep (backoff);
859 while (1)
861 for (i = 0; i < files; i++)
863 char name[] = "./stress.XXXXXX";
865 if ((fd = mkstemp (name)) < 0)
867 perror ("mkstemp");
868 err (stderr, "mkstemp failed\n");
869 exit (1);
872 if (clean == 0)
874 dbg (stdout, "unlinking %s\n", name);
875 if (unlink (name))
877 err (stderr, "unlink failed\n");
878 exit (1);
882 dbg (stdout, "fast writing to %s\n", name);
883 for (j = 0; bytes == 0 || j + chunk < bytes; j += chunk)
885 if (write (fd, buff, chunk) != chunk)
887 err (stderr, "write failed\n");
888 exit (1);
892 dbg (stdout, "slow writing to %s\n", name);
893 for (; bytes == 0 || j < bytes - 1; j++)
895 if (write (fd, "Z", 1) != 1)
897 err (stderr, "write failed\n");
898 exit (1);
901 if (write (fd, "\n", 1) != 1)
903 err (stderr, "write failed\n");
904 exit (1);
906 ++j;
908 dbg (stdout, "closing %s after writing %lli bytes\n", name,
910 close (fd);
912 if (clean == 1)
914 if (unlink (name))
916 err (stderr, "unlink failed\n");
917 exit (1);
921 if (retval == 0)
923 dbg (stdout, "hoghdd worker starting over\n");
924 continue;
927 exit (retval);
930 /* This case never falls through; alarm signal can cause exit. */
931 case -1: /* error */
932 if (ignore)
934 ++retval;
935 wrn (stderr, "hoghdd worker fork failed, continuing\n");
936 usleep (retry);
937 continue;
940 err (stderr, "hoghdd worker fork failed\n");
941 return 1;
942 default: /* parent */
943 dbg (stdout, "--> hoghdd worker forked (%i)\n", pid);
947 /* Wait for our children to exit. */
948 while (i)
950 int status, ret;
952 if ((pid = wait (&status)) > 0)
954 if ((WIFEXITED (status)) != 0)
956 if ((ret = WEXITSTATUS (status)) != 0)
958 err (stderr, "hoghdd worker %i exited %i\n", pid, ret);
959 retval += ret;
961 else
963 dbg (stdout, "<-- hoghdd worker exited (%i)\n", pid);
966 else
968 dbg (stdout, "<-- hoghdd worker signalled (%i)\n", pid);
971 --i;
973 else
975 dbg (stdout, "wait() returned error: %s\n", strerror (errno));
976 err (stderr, "detected missing hoghdd worker children\n");
977 ++retval;
978 break;
982 return retval;