diff --git a/misc/ChangeLog b/misc/ChangeLog index 29415a8c..4db73645 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,4 +1,22 @@ -1999-07-08 +1999-07-18 + + * mke2fs.c (PRS, set_fs_defaults): Add new option -T which allows + the user to specify the how the filesystem is to be used. + Mke2fs now chooses the filesystem parameters automatically + based on the size of the filesystem and the intended use + of the filesystem. Add new option -n which simply goes + through the calculations to determine the parameters of + the filesystem the system would make. + +1999-07-18 + + * fsck.c, fsck.h: Add support for new option -C. This option will + automatically manage e2fsck processes so that they will + print completion/progress bars. If multiple filesystems + are being checked, arrange to make sure that only one + e2fsck process is displaying a progress bar at a time. + +1999-07-08 * badblocks.c (do_test): Don't complain if the write error occurs on a non-block boundary. This is perfectly common when diff --git a/misc/fsck.8.in b/misc/fsck.8.in index 806f378d..66dda966 100644 --- a/misc/fsck.8.in +++ b/misc/fsck.8.in @@ -8,32 +8,26 @@ fsck \- check and repair a Linux file system .SH SYNOPSIS .B fsck [ -.B \-AVRTNP -] -[ -.B \-s +.B \-sACVRTNP ] [ .B \-t .I fstype -] -[ -.B fs-options +] -- [ +.B fsck-options ] .I filesys [ ... ] .SH DESCRIPTION .B fsck -is used to check and optionally repair a Linux file system. +is used to check and optionally repair a one or more Linux file systems. .I filesys -is either the device name (e.g. /dev/hda1, /dev/sdb2) or the mount point -(e.g. /, /usr, /home) for the file system. If this invocation of +can be a device name (e.g. /dev/hda1, /dev/sdb2), a +mount point (e.g. /, /usr, /home), or an ext2 label or UUID specifier +(e.g., UUID=8868abf6-88c5-4a83-98b8-bfc24057f7bd or LABEL=root). +The .B fsck -has several filesystems on different physical disk drives to check, then -.B fsck -will try to run them in parallel. This reduces the total amount time it -takes to check all of the filesystems, since -.B fsck -takes advantage of the parallelism of multiple disk spindles. +program will try to run filesystems on different physical disk drives +in parallel to reduce total amount time to check all of the filesystems. .PP The exit code returned by .B fsck @@ -68,6 +62,48 @@ variable. Please see the file system-specific checker manual pages for further details. .SH OPTIONS .TP +.B -s +Serialize +.B fsck +operations. This is a good idea if you checking multiple +filesystems and the checkers are in an interactive mode. (Note: +.BR e2fsck (8) +runs in an interactive mode by default. To make +.BR e2fsck (8) +run in a non-interactive mode, you must either specify the +.B -p +or +.B -a +option, if you wish for errors to be corrected automatically, or +the +.B -n +option if you do not.) +.TP +.BI -t \ fstype +Specifies the type of file system to be checked. When the +.B \-A +flag is specified, only filesystems that match +.I fstype +are checked. If +.I fstype +is prefixed with +.B no +then only filesystems whose type does not match +.I fstype +are checked. +.sp +Normally, the filesystem type is deduced by searching for +.I filesys +in the +.I /etc/fstab +file and using the corresponding entry. +If the type can not be deduced, +.B fsck +will use the type specified by the +.B \-t +option if it specifies a unique filesystem type. If this type is not +available, then the default file system type (currently ext2) is used. +.TP .B -A Walk through the .I /etc/fstab @@ -103,13 +139,10 @@ checks running in parallel for some reason --- for example, if the machine in question is short on memory so that excessive paging is a concern. .TP -.B -R -When checking all file systems with the -.B \-A -flag, skip the root file system (in case it's already mounted read-write). -.TP -.B -T -Don't show the title on startup. +.B -C +Display completion/progress bars for those filesystems checkers (currently +only for ext2) which support them. Fsck will manage the filesystem checkers +so that only one of them will display a progress bar at a time. .TP .B -N Don't execute, just show what would be done. @@ -125,53 +158,19 @@ executable might be corrupted! This option is mainly provided for those sysadmins who don't want to repartition the root filesystem to be small and compact (which is really the right solution). .TP -.B -s -Serialize -.B fsck -operations. This is a good idea if you checking multiple -filesystems and the checkers are in an interactive mode. (Note: -.BR e2fsck (8) -runs in an interactive mode by default. To make -.BR e2fsck (8) -run in a non-interactive mode, you must either specify the -.B -p -or -.B -a -option, if you wish for errors to be corrected automatically, or -the -.B -n -option if you do not.) +.B -R +When checking all file systems with the +.B \-A +flag, skip the root file system (in case it's already mounted read-write). +.TP +.B -T +Don't show the title on startup. .TP .B -V Produce verbose output, including all file system-specific commands that are executed. .TP -.BI -t \ fstype -Specifies the type of file system to be checked. When the -.B \-A -flag is specified, only filesystems that match -.I fstype -are checked. If -.I fstype -is prefixed with -.B no -then only filesystems whose type does not match -.I fstype -are checked. -.sp -Normally, the filesystem type is deduced by searching for -.I filesys -in the -.I /etc/fstab -file and using the corresponding entry. -If the type can not be deduced, -.B fsck -will use the type specified by the -.B \-t -option if it specifies a unique filesystem type. If this type is not -available, then the default file system type (currently ext2) is used. -.TP -.B fs-options +.B fsck-options Any options which are not understood by .BR fsck , or which follow the diff --git a/misc/fsck.c b/misc/fsck.c index db86f562..bea2995a 100644 --- a/misc/fsck.c +++ b/misc/fsck.c @@ -8,7 +8,7 @@ * * Written by Theodore Ts'o, * - * Usage: fsck [-AVRNTM] [-s] [-t fstype] [fs-options] device + * Usage: fsck [-ACVRNTM] [-s] [-t fstype] [fs-options] device * * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994: * o Changed -t fstype to behave like with mount when -A (all file @@ -18,7 +18,7 @@ * can be added without changing this front-end. * o -R flag skip root file system. * - * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. * * %Begin-Header% * This file may be redistributed under the terms of the GNU Public @@ -130,6 +130,7 @@ int skip_root = 0; int like_mount = 0; int notitle = 0; int parallel_root = 0; +int progress = 0; char *progname; char *fstype = NULL; struct fs_info *filesys_info; @@ -355,23 +356,49 @@ static char *find_fsck(char *type) return(s ? prog : NULL); } +static int progress_active() +{ + struct fsck_instance *inst; + + for (inst = instance_list; inst; inst = inst->next) { + if (inst->flags & FLAG_DONE) + continue; + if (inst->flags & FLAG_PROGRESS) + return 1; + } + return 0; +} + /* * Execute a particular fsck program, and link it into the list of * child processes we are waiting for. */ -static int execute(char *prog, char *device, char *mntpt, int interactive) +static int execute(char *type, char *device, char *mntpt, int interactive) { - char *s, *argv[80]; + char *s, *argv[80], prog[80]; int argc, i; struct fsck_instance *inst; pid_t pid; + inst = malloc(sizeof(struct fsck_instance)); + if (!inst) + return ENOMEM; + memset(inst, 0, sizeof(struct fsck_instance)); + + sprintf(prog, "fsck.%s", type); argv[0] = string_copy(prog); argc = 1; for (i=0; i flags |= FLAG_PROGRESS; + } + } + argv[argc++] = string_copy(device); argv[argc] = 0; @@ -401,12 +428,10 @@ static int execute(char *prog, char *device, char *mntpt, int interactive) perror(argv[0]); exit(EXIT_ERROR); } - inst = malloc(sizeof(struct fsck_instance)); - if (!inst) - return ENOMEM; - memset(inst, 0, sizeof(struct fsck_instance)); + inst->pid = pid; inst->prog = string_copy(prog); + inst->type = string_copy(type); inst->device = string_copy(device); inst->next = instance_list; instance_list = inst; @@ -422,7 +447,7 @@ static struct fsck_instance *wait_one(NOARGS) { int status; int sig; - struct fsck_instance *inst, *prev; + struct fsck_instance *inst, *inst2, *prev; pid_t pid; if (!instance_list) @@ -482,6 +507,17 @@ retry: 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) { + if (inst2->flags & FLAG_DONE) + continue; + if (strcmp(inst2->type, "ext2")) + continue; + kill(inst2->pid, SIGUSR1); + break; + } + } return inst; } @@ -516,10 +552,9 @@ static int wait_all(NOARGS) */ static void fsck_device(char *device, int interactive) { - const char *type = 0; + char *type = 0; struct fs_info *fsent; int retval; - char prog[80]; if (fstype && strncmp(fstype, "no", 2) && !strchr(fstype, ',')) type = fstype; @@ -532,12 +567,11 @@ static void fsck_device(char *device, int interactive) if (!type) type = DEFAULT_FSTYPE; - sprintf(prog, "fsck.%s", type); - retval = execute(prog, device, fsent ? fsent->mountpt : 0, + retval = execute(type, device, fsent ? fsent->mountpt : 0, interactive); if (retval) { - fprintf(stderr, "%s: Error %d while executing %s for %s\n", - progname, retval, prog, device); + fprintf(stderr, "%s: Error %d while executing fsck.%s " + "for %s\n", progname, retval, type, device); } } @@ -632,15 +666,12 @@ static const char *base_device(char *device) static int device_already_active(char *device) { struct fsck_instance *inst; - const char *base; - - base = base_device(device); + const char *base = base_device(device); for (inst = instance_list; inst; inst = inst->next) { if (!strcmp(base, base_device(inst->device))) return 1; } - return 0; } @@ -742,7 +773,7 @@ static int check_all(NOARGS) static void usage(NOARGS) { fprintf(stderr, - "Usage: fsck [-AV] [-t fstype] [fs-options] filesys\n"); + "Usage: fsck [-ACNPRTV] [-t fstype] [fs-options] filesys\n"); exit(EXIT_USAGE); } @@ -794,6 +825,9 @@ static void PRS(int argc, char *argv[]) case 'A': doall++; break; + case 'C': + progress++; + break; case 'V': verbose++; break; diff --git a/misc/fsck.h b/misc/fsck.h index 3e13e9c9..3efd9541 100644 --- a/misc/fsck.h +++ b/misc/fsck.h @@ -40,6 +40,7 @@ struct fs_info { }; #define FLAG_DONE 1 +#define FLAG_PROGRESS 2 /* * Structure to allow exit codes to be stored @@ -49,6 +50,7 @@ struct fsck_instance { int flags; int exit_status; char * prog; + char * type; char * device; struct fsck_instance *next; }; diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in index 57423d2a..4e0a3d9b 100644 --- a/misc/mke2fs.8.in +++ b/misc/mke2fs.8.in @@ -70,6 +70,10 @@ mke2fs \- create a Linux second extended file system .B \-S ] [ +.B \-T +.I filesystem-type +] +[ .B \-V ] .I device @@ -105,9 +109,13 @@ Specify the bytes/inode ratio. .B mke2fs creates an inode for every .I bytes-per-inode -bytes of space on the disk. This value defaults to 4096 bytes. -.I bytes-per-inode -must be at least 1024. +bytes of space on the disk. +The larger the bytes-per-inode ratio, the fewer inodes will be created. +This value generally shouldn't be smaller than +the blocksize of the filesystem, since then too many inodes will be made. +Be warned that is not possible to expand the number of inodes on a +filesystem after it is created, so be careful decided the correct +value for this parameter. .TP .I -N number-of-inodes overrides the default calculation of the number of inodes that should be @@ -189,8 +197,13 @@ and the block and inode bitmaps. The program should be run immediately after this option is used, and there is no guarantee that any data will be salvageable. .TP +.I -T fs-type +Specify how the filesystem is going to be used, so that mke2fs can +automatically determine the optimal filesystem parameters. The only +filesystem type which is currently supported is "news". +.TP .I -V -print the version number of +Print the version number of .B mke2fs and exit. .SH AUTHOR diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 1eb7a6e7..d5529936 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -74,6 +74,7 @@ int verbose = 0; int quiet = 0; int super_only = 0; int force = 0; +int noaction = 0; char *bad_blocks_filename = 0; __u32 fs_stride = 0; @@ -186,6 +187,59 @@ static void check_mount(NOARGS) } } +/* + * This function sets the default parameters for a filesystem + * + * The type is specified by the user. The size is minimum size for + * which a set of parameters applies, with a size of zero meaning that + * it is the default parameter for the type. Note that order is + * important in the table below. + */ +static char default_str[] = "default"; +struct mke2fs_defaults { + char *type; + int size; + int blocksize; + int inode_ratio; +} settings[] = { + { default_str, 0, 4096, 8192 }, + { default_str, 512, 1024, 4096 }, + { default_str, 3, 1024, 8192 }, + { "news", 0, 4096, 4096 }, + { 0, 0, 0, 0}, +}; + +static void set_fs_defaults(char *fs_type, struct ext2fs_sb *param, + int blocksize, int *inode_ratio) +{ + int megs; + int ratio = 0; + struct mke2fs_defaults *p; + + megs = (param->s_blocks_count * (EXT2_BLOCK_SIZE(param) / 1024) / + 1024); + if (inode_ratio) + ratio = *inode_ratio; + if (!fs_type) + fs_type = default_str; + for (p = settings; p->type; p++) { + if ((strcmp(p->type, fs_type) != 0) && + (strcmp(p->type, default_str) != 0)) + continue; + if ((p->size != 0) && + (megs > p->size)) + continue; + if (ratio == 0) + *inode_ratio = p->inode_ratio; + if (blocksize == 0) { + param->s_log_frag_size = param->s_log_block_size = + log2(p->blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); + } + } + if (blocksize == 0) + param->s_blocks_count /= EXT2_BLOCK_SIZE(param) / 1024; +} + /* * Helper function for read_bb_file and test_disk */ @@ -420,6 +474,7 @@ static void create_lost_and_found(ext2_filsys fs) ino_t ino; const char *name = "lost+found"; int i; + int lpf_size = 0; retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name); if (retval) { @@ -434,6 +489,8 @@ static void create_lost_and_found(ext2_filsys fs) } for (i=1; i < EXT2_NDIR_BLOCKS; i++) { + if ((lpf_size += fs->blocksize) >= 16*1024) + break; retval = ext2fs_expand_dir(fs, ino); if (retval) { com_err("ext2fs_expand_dir", retval, @@ -499,27 +556,28 @@ static void show_stats(ext2_filsys fs) if (param.s_blocks_count != s->s_blocks_count) printf("warning: %d blocks unused.\n\n", param.s_blocks_count - s->s_blocks_count); - + + memset(buf, 0, sizeof(buf)); + strncpy(buf, s->s_volume_name, sizeof(s->s_volume_name)); + printf("Filesystem label=%s\n", buf); + printf("OS type: "); switch (fs->super->s_creator_os) { case EXT2_OS_LINUX: printf ("Linux"); break; case EXT2_OS_HURD: printf ("GNU/hurd"); break; case EXT2_OS_MASIX: printf ("Masix"); break; default: printf ("(unknown os)"); } - printf (" ext2 filesystem format\n"); - memset(buf, 0, sizeof(buf)); - strncpy(buf, s->s_volume_name, sizeof(s->s_volume_name)); - printf("Filesystem label=%s\n", buf); + printf("\n"); + printf("Block size=%u (log=%u)\n", fs->blocksize, + s->s_log_block_size); + printf("Fragment size=%u (log=%u)\n", fs->fragsize, + s->s_log_frag_size); printf("%u inodes, %u blocks\n", s->s_inodes_count, s->s_blocks_count); printf("%u blocks (%2.2f%%) reserved for the super user\n", s->s_r_blocks_count, 100.0 * s->s_r_blocks_count / s->s_blocks_count); printf("First data block=%u\n", s->s_first_data_block); - printf("Block size=%u (log=%u)\n", fs->blocksize, - s->s_log_block_size); - printf("Fragment size=%u (log=%u)\n", fs->fragsize, - s->s_log_frag_size); printf("%lu block group%s\n", fs->group_desc_count, (fs->group_desc_count > 1) ? "s" : ""); printf("%u blocks per group, %u fragments per group\n", @@ -647,14 +705,16 @@ static void PRS(int argc, char *argv[]) int size; char * tmp; blk_t max = 8192; - int inode_ratio = 4096; + int blocksize = 0; + int inode_ratio = 0; int reserved_ratio = 5; ino_t num_inodes = 0; errcode_t retval; - int sparse_option = -1; + int sparse_option = 1; char *oldpath = getenv("PATH"); struct ext2fs_sb *param_ext2 = (struct ext2fs_sb *) ¶m; char *raid_opts = 0; + char *fs_type = 0; blk_t dev_size; /* Update our PATH to include /sbin */ @@ -673,6 +733,7 @@ static void PRS(int argc, char *argv[]) setbuf(stderr, NULL); initialize_ext2_error_table(); memset(¶m, 0, sizeof(struct ext2_super_block)); + param.s_rev_level = 1; /* Create revision 1 filesystems now */ fprintf (stderr, "mke2fs %s, %s for EXT2 FS %s, %s\n", E2FSPROGS_VERSION, E2FSPROGS_DATE, @@ -680,18 +741,18 @@ static void PRS(int argc, char *argv[]) if (argc && *argv) program_name = *argv; while ((c = getopt (argc, argv, - "b:cf:g:i:l:m:o:qr:R:s:tvI:SFL:M:N:V")) != EOF) + "b:cf:g:i:l:m:no:qr:R:s:tvI:ST:FL:M:N:V")) != EOF) switch (c) { case 'b': - size = strtoul(optarg, &tmp, 0); - if (size < 1024 || size > 4096 || *tmp) { + blocksize = strtoul(optarg, &tmp, 0); + if (blocksize < 1024 || blocksize > 4096 || *tmp) { com_err(program_name, 0, "bad block size - %s", optarg); exit(1); } param.s_log_block_size = - log2(size >> EXT2_MIN_BLOCK_LOG_SIZE); - max = size * 8; + log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); + max = blocksize * 8; break; case 'c': case 't': /* Check for bad blocks */ @@ -749,6 +810,9 @@ static void PRS(int argc, char *argv[]) exit(1); } break; + case 'n': + noaction++; + break; case 'o': creator_os = optarg; break; @@ -787,6 +851,9 @@ static void PRS(int argc, char *argv[]) case 'S': super_only = 1; break; + case 'T': + fs_type = optarg; + break; case 'V': /* Print version number and exit */ fprintf(stderr, "\tUsing %s\n", @@ -819,9 +886,13 @@ static void PRS(int argc, char *argv[]) param.s_log_frag_size = param.s_log_block_size; - retval = ext2fs_get_device_size(device_name, - EXT2_BLOCK_SIZE(¶m), - &dev_size); + if (noaction && param.s_blocks_count) { + dev_size = param.s_blocks_count; + retval = 0; + } else + retval = ext2fs_get_device_size(device_name, + EXT2_BLOCK_SIZE(¶m), + &dev_size); if (retval && (retval != EXT2_ET_UNIMPLEMENTED)) { com_err(program_name, retval, "while trying to determine filesystem size"); @@ -842,6 +913,8 @@ static void PRS(int argc, char *argv[]) proceed_question(); } + set_fs_defaults(fs_type, param_ext2, blocksize, &inode_ratio); + if (param.s_blocks_per_group) { if (param.s_blocks_per_group < 256 || param.s_blocks_per_group > max || *tmp) { @@ -929,9 +1002,12 @@ int main (int argc, char *argv[]) sizeof(s->s_last_mounted)); } - if (!quiet) + if (!quiet || noaction) show_stats(fs); + if (noaction) + exit(0); + if (bad_blocks_filename) read_bb_file(fs, &bb_list, bad_blocks_filename); if (cflag)