-1999-07-08 <tytso@rsts-11.mit.edu>
+1999-07-18 <tytso@rsts-11.mit.edu>
+
+ * 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 <tytso@valinux.com>
+
+ * 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 <tytso@valinux.com>
* badblocks.c (do_test): Don't complain if the write error occurs
on a non-block boundary. This is perfectly common when
.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
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
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.
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
*
* Written by Theodore Ts'o, <tytso@mit.edu>
*
- * 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
* 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
int like_mount = 0;
int notitle = 0;
int parallel_root = 0;
+int progress = 0;
char *progname;
char *fstype = NULL;
struct fs_info *filesys_info;
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 <num_args; i++)
argv[argc++] = string_copy(args[i]);
+ if (progress & !progress_active()) {
+ if (strcmp(type, "ext2") == 0) {
+ argv[argc++] = "-C0";
+ inst->flags |= FLAG_PROGRESS;
+ }
+ }
+
argv[argc++] = string_copy(device);
argv[argc] = 0;
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;
{
int status;
int sig;
- struct fsck_instance *inst, *prev;
+ struct fsck_instance *inst, *inst2, *prev;
pid_t pid;
if (!instance_list)
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;
}
*/
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;
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);
}
}
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;
}
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);
}
case 'A':
doall++;
break;
+ case 'C':
+ progress++;
+ break;
case 'V':
verbose++;
break;
};
#define FLAG_DONE 1
+#define FLAG_PROGRESS 2
/*
* Structure to allow exit codes to be stored
int flags;
int exit_status;
char * prog;
+ char * type;
char * device;
struct fsck_instance *next;
};
.B \-S
]
[
+.B \-T
+.I filesystem-type
+]
+[
.B \-V
]
.I device
.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
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
int quiet = 0;
int super_only = 0;
int force = 0;
+int noaction = 0;
char *bad_blocks_filename = 0;
__u32 fs_stride = 0;
}
/*
+ * 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
*/
static void invalid_block(ext2_filsys fs, blk_t blk)
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) {
}
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,
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",
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 */
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,
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 */
exit(1);
}
break;
+ case 'n':
+ noaction++;
+ break;
case 'o':
creator_os = optarg;
break;
case 'S':
super_only = 1;
break;
+ case 'T':
+ fs_type = optarg;
+ break;
case 'V':
/* Print version number and exit */
fprintf(stderr, "\tUsing %s\n",
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");
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) {
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)