From: Theodore Ts'o Date: Tue, 29 Jan 2002 17:49:14 +0000 (-0500) Subject: fsck.c: Allow the number of outstanding processes fs-specific X-Git-Tag: E2FSPROGS-1_26~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a1069118d438851e69c3dd6e38211fc4adfc7048;p=thirdparty%2Fe2fsprogs.git fsck.c: Allow the number of outstanding processes fs-specific fsck programs to be capped via the FSCK_MAX_INST envrionment variable. fsck.8.in: Document all of the environment variables used by fsck. --- diff --git a/misc/ChangeLog b/misc/ChangeLog index 0f3c5bb4a..77de737ae 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,3 +1,11 @@ +2002-01-29 Theodore Tso + + * fsck.c: Allow the number of outstanding processes fs-specific + fsck programs to be capped via the FSCK_MAX_INST + envrionment variable. + + * fsck.8.in: Document all of the environment variables used by fsck. + 2002-01-27 Theodore Tso * tune2fs.8.in: Document the -f flag to tune2fs. diff --git a/misc/fsck.8.in b/misc/fsck.8.in index 51e5f52e4..f97f54520 100644 --- a/misc/fsck.8.in +++ b/misc/fsck.8.in @@ -280,14 +280,55 @@ default behavior; it supports this option for backwards compatibility reasons only. .SH AUTHOR Theodore Ts'o (tytso@mit.edu) -.PP -The manual page was shamelessly adapted from David Engel and Fred van -Kempen's generic -.B fsck -front end program, which was in turn shamelessly -adapted from Remy Card's version for the ext2 file system. .SH FILES .IR /etc/fstab . +.SH ENVIRONMENT VARIABLES +The +.B fsck +program's behavior is affected by the following environment variables: +.TP +.B FSCK_FORCE_ALL_PARALLEL +If this environment variable is set, +.B fsck +will attempt to run all of the specified filesystems in parallel, +regardless of whether the filesystems appear to be on the same +device. (This is useful for RAID systems or high-end storage systems +such as those sold by companies such as IBM or EMC.) +.TP +.B FSCK_MAX_INST +This environment variable will limit the maximum number of file system +checkers that can be running at one time. This allows configurations +which have a large number of disks to avoid +.B fsck +starting too many file system checkers at once, which might overload +CPU and memory resources available on the system. If this value is +zero, then an unlimited number of processes can be spawned. This is +currently the default, but future versions of +.B fsck +may attempt to automatically determine how many file system checks can +be run based on gathering accounting data from the operating system. +.TP +.B PATH +The +.B PATH +environment variable is used to find file system checkers. A set of +system directories are searched first: +.BR /sbin , +.BR /sbin/fs.d , +.BR /sbin/fs , +.BR /etc/fs , +and +.BR /etc . +Then the set of directories found in the +.B PATH +environment are searched. +.TP +.B FSTAB_FILE +This environment variable allows the system administrator +to override the standard location of the +.B /etc/fstab +file. It is also use for developers who are testing +.BR fsck . .SH SEE ALSO .BR fstab (5), .BR mkfs (8), diff --git a/misc/fsck.c b/misc/fsck.c index 83751bd8a..743200bb6 100644 --- a/misc/fsck.c +++ b/misc/fsck.c @@ -98,6 +98,8 @@ int notitle = 0; int parallel_root = 0; int progress = 0; int force_all_parallel = 0; +int num_running = 0; +int max_running = 0; char *progname; char *fstype = NULL; struct fs_info *filesys_info; @@ -419,7 +421,8 @@ static int execute(const char *type, char *device, char *mntpt, } if (verbose || noexecute) { - printf("[%s -- %s] ", s, mntpt ? mntpt : device); + printf("[%s (%d) -- %s] ", s, num_running, + mntpt ? mntpt : device); for (i=0; i < argc; i++) printf("%s ", argv[i]); printf("\n"); @@ -467,7 +470,7 @@ static int execute(const char *type, char *device, char *mntpt, * Wait for one child process to exit; when it does, unlink it from * the list of executing child processes, and return it. */ -static struct fsck_instance *wait_one(NOARGS) +static struct fsck_instance *wait_one(int flags) { int status; int sig; @@ -479,9 +482,15 @@ static struct fsck_instance *wait_one(NOARGS) if (noexecute) { inst = instance_list; - instance_list = inst->next; + prev = 0; +#ifdef RANDOM_DEBUG + while (inst->next && (random() & 1)) { + prev = inst; + inst = inst->next; + } +#endif inst->exit_status = 0; - return(inst); + goto ret_inst; } /* @@ -491,7 +500,9 @@ static struct fsck_instance *wait_one(NOARGS) inst = prev = NULL; do { - pid = wait(&status); + pid = waitpid(-1, &status, flags); + if ((pid == 0) && (flags & WNOHANG)) + return NULL; if (pid < 0) { if ((errno == EINTR) || (errno == EAGAIN)) continue; @@ -530,10 +541,6 @@ static struct fsck_instance *wait_one(NOARGS) status = EXIT_ERROR; } inst->exit_status = status; - if (prev) - prev->next = inst->next; - else - instance_list = inst->next; if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { for (inst2 = instance_list; inst2; inst2 = inst2->next) { @@ -559,6 +566,15 @@ static struct fsck_instance *wait_one(NOARGS) break; } } +ret_inst: + if (prev) + prev->next = inst->next; + else + instance_list = inst->next; + if (verbose > 1) + printf(_("Finished with %s (exit status %d)\n"), + inst->device, inst->exit_status); + num_running--; return inst; } @@ -566,17 +582,18 @@ static struct fsck_instance *wait_one(NOARGS) * Wait until all executing child processes have exited; return the * logical OR of all of their exit code values. */ -static int wait_all(NOARGS) +static int wait_all(int flags) { struct fsck_instance *inst; int global_status = 0; - while (instance_list) { - inst = wait_one(); - if (!inst) - break; + while ((inst = wait_one(flags))) { global_status |= inst->exit_status; free_instance(inst); +#ifdef RANDOM_DEBUG + if (noexecute && (flags & WNOHANG) && !(random() % 3)) + break; +#endif } return global_status; } @@ -611,11 +628,13 @@ static void fsck_device(char *device, int interactive) if (!type) type = DEFAULT_FSTYPE; + num_running++; retval = execute(type, device, fsent ? fsent->mountpt : 0, interactive); if (retval) { fprintf(stderr, _("%s: Error %d while executing fsck.%s " "for %s\n"), progname, retval, type, device); + num_running--; } } @@ -875,7 +894,7 @@ static int check_all(NOARGS) if (fs) { if (!skip_root && !ignore(fs)) { fsck_device(fs->device, 1); - status |= wait_all(); + status |= wait_all(0); if (status > EXIT_NONDESTRUCT) return status; } @@ -914,27 +933,28 @@ static int check_all(NOARGS) fsck_device(fs->device, serialize); fs->flags |= FLAG_DONE; - if (serialize) { + /* + * Only do one filesystem at a time, or if we + * have a limit on the number of fsck's extant + * at one time, apply that limit. + */ + if (serialize || + (max_running && (num_running >= max_running))) { pass_done = 0; - break; /* Only do one filesystem at a time */ + break; } } if (verbose > 1) printf(_("--waiting-- (pass %d)\n"), passno); - inst = wait_one(); - if (inst) { - status |= inst->exit_status; - free_instance(inst); - } + status |= wait_all(pass_done ? 0 : WNOHANG); if (pass_done) { - status |= wait_all(); if (verbose > 1) printf("----------------------------------\n"); passno++; } else not_done_yet++; } - status |= wait_all(); + status |= wait_all(0); return status; } @@ -948,7 +968,7 @@ static void usage(NOARGS) static void PRS(int argc, char *argv[]) { int i, j; - char *arg; + char *arg, *tmp; char options[128]; int opt = 0; int opts_for_fsck = 0; @@ -1018,19 +1038,17 @@ static void PRS(int argc, char *argv[]) serialize++; break; case 't': - if (arg[j+1]) { - fstype = string_copy(arg+j+1); - compile_fs_type(fstype, &fs_type_compiled); - goto next_arg; - } - if ((i+1) < argc) { - i++; - fstype = string_copy(argv[i]); - compile_fs_type(fstype, &fs_type_compiled); - goto next_arg; - } - usage(); - break; + if (fstype) + usage(); + if (arg[j+1]) + tmp = arg+j+1; + else if ((i+1) < argc) + tmp = argv[++i]; + else + usage(); + fstype = string_copy(tmp); + compile_fs_type(fstype, &fs_type_compiled); + goto next_arg; case '-': opts_for_fsck++; break; @@ -1058,6 +1076,8 @@ static void PRS(int argc, char *argv[]) } if (getenv("FSCK_FORCE_ALL_PARALLEL")) force_all_parallel++; + if ((tmp = getenv("FSCK_MAX_INST"))) + max_running = atoi(tmp); } int main(int argc, char *argv[]) @@ -1107,17 +1127,17 @@ int main(int argc, char *argv[]) } for (i = 0 ; i < num_devices; i++) { fsck_device(devices[i], interactive); - if (serialize) { + if (serialize || (num_running >= max_running)) { struct fsck_instance *inst; - inst = wait_one(); + inst = wait_one(0); if (inst) { status |= inst->exit_status; free_instance(inst); } } } - status |= wait_all(); + status |= wait_all(0); free(fsck_path); return status; }