2001-01-17 Theodore Ts'o <tytso@valinux.com>
+ * tune2fs.c, mke2fs.c, tune2fs.8.in, mke2fs.8.in: Change user
+ interface so that -J is used to specify journal options,
+ and -j is used to request creation of a journal using
+ default values. (This is a UI change, but we haven't done
+ a formal release, and it makes things much more consistent
+ with the rest of the options out there.)
+
+ * tune2fs.c: Add support for removing a filesystem from an
+ external journal; we correctly remove the filesystem UUID
+ from the external journal's filesystem list.
+
* util.h, util.c (journal_default_size): New function from Andreas
Dilger to calculate an appropriate default journal size
given a filesystem size.
]
[
.B \-j
+]
+[
+.B \-J
.I journal-options
]
[
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
+filesystem after it is created, so be careful deciding the correct
value for this parameter.
-.TP
-.BI \-j " journal options"
+.TP
+.B -j
Build the ext2 filesystem with the ext3 journaling feature enabled.
+If the
+.B \-J
+option is not specified, the default journal parameters will used will create
+an appropriately sized journal (given the size of the filesystem)
+stored internally in the filesystem.
+.TP
+.BI \-J " journal options"
+Create the ext3 journal using options specified on the command-line.
Journal options are comma
separated, and may take an argument using the equals ('=') sign.
-Currently two options are supported,
+Currently two (mutually exclusive) options are supported,
.I size
and
.IR device .
-One these two options must be specified when
-building the journal.
-The
-.I size
-option takes a numerical argument which specifies the size of the
-journal in MB (1024*1024 bytes). Any size between 4MB and 100MB may be used.
-Use of this option implies that the journal will be stored in the
-filesystem, so it must be small enough to fit into the filesystem.
-The
-.I device
-option takes a filename which specifies a block device (external
-to the filesystem) which will contain the external journal.
+.TP
+.BI "\-J size=" journal-size
+Create a journal stored in the filesystem of size
+.IR journal-size .
+The size of the journal must be between 1MB and 100MB and it must fit within
+the newly created filesystem.
+.TP
+.BI "\-J device=" external-journal
+Add an external journal found on a block device
+named by
+.I external-journal
+to the filesystem.
+The external
+journal must have been already created using the command
+.B mke2fs -O journal_dev
+.IR journal-device.
.TP
.B \-n
causes mke2fs to not actually create a filesystem, but display what it
static void usage(void)
{
fprintf(stderr, _("Usage: %s [-c|-t|-l filename] [-b block-size] "
- "[-f fragment-size]\n\t[-i bytes-per-inode] [-j journal-options]"
+ "[-f fragment-size]\n\t[-i bytes-per-inode] [-j] [-J journal-options]"
" [-N number-of-inodes]\n\t[-m reserved-blocks-percentage] "
"[-o creator-os] [-g blocks-per-group]\n\t[-L volume-label] "
"[-M last-mounted-directory] [-O feature[,...]]\n\t"
{ default_str, 0, 4096, 8192 },
{ default_str, 512, 1024, 4096 },
{ default_str, 3, 1024, 8192 },
+ { "journal", 0, 4096, 8192 },
{ "news", 0, 4096, 4096 },
{ "largefile", 0, 4096, 1024 * 1024 },
{ "largefile4", 0, 4096, 4096 * 1024 },
struct progress_struct progress;
errcode_t retval;
char *buf;
+ blk_t blk;
+ int count;
if (quiet)
memset(&progress, 0, sizeof(progress));
progress_init(&progress, _("Zeroing journal device: "),
fs->super->s_blocks_count);
-#if 0
retval = zero_blocks(fs, 0, fs->super->s_blocks_count,
&progress, &blk, &count);
if (retval) {
blk, count);
exit(1);
}
- zero_blocks(0, 0, 0, 0, 0);
-#endif
+ zero_blocks(0, 0, 0, 0, 0, 0);
+
retval = ext2fs_create_journal_superblock(fs,
fs->super->s_blocks_count, 0, &buf);
if (retval) {
_("while initialization journal superblock"));
exit(1);
}
- retval = io_channel_write_blk(fs->io, 1, 1, buf);
+ retval = io_channel_write_blk(fs->io,
+ fs->super->s_first_data_block+1,
+ 1, buf);
if (retval) {
com_err("create_journal_dev", retval,
_("while writing journal superblock"));
}
static __u32 ok_features[3] = {
- 0, /* Compat */
+ EXT3_FEATURE_COMPAT_HAS_JOURNAL, /* Compat */
EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */
errcode_t retval;
int sparse_option = 1;
char * oldpath = getenv("PATH");
- struct ext2_super_block *param_ext2 = ¶m;
char * raid_opts = 0;
- char * journal_opts = 0;
char * fs_type = 0;
const char * feature_set = "filetype";
blk_t dev_size;
if (argc && *argv)
program_name = *argv;
while ((c = getopt (argc, argv,
- "b:cf:g:i:j:l:m:no:qr:R:s:tvI:ST:FL:M:N:O:V")) != EOF)
+ "b:cf:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF)
switch (c) {
case 'b':
blocksize = strtoul(optarg, &tmp, 0);
exit(1);
}
break;
+ case 'J':
+ parse_journal_opts(optarg);
+ break;
case 'j':
- journal_opts = optarg;
+ if (!journal_size)
+ journal_size = -1;
break;
case 'l':
bad_blocks_filename = malloc(strlen(optarg)+1);
if (raid_opts)
parse_raid_opts(raid_opts);
- if (journal_opts)
- parse_journal_opts(journal_opts);
-
+ /* Parse the user-supplied feature_set, if any. */
+ if (feature_set && !strncasecmp(feature_set, "none", 4))
+ feature_set = NULL;
+ if (feature_set && e2p_edit_feature(feature_set,
+ ¶m.s_feature_compat,
+ ok_features)) {
+ fprintf(stderr, _("Invalid filesystem option set: %s\n"),
+ feature_set);
+ exit(1);
+ }
+
if (!force)
check_plausibility(device_name);
check_mount(device_name, force, _("filesystem"));
proceed_question();
}
- set_fs_defaults(fs_type, param_ext2, blocksize, &inode_ratio);
+ /*
+ * If the user asked for HAS_JOURNAL, then make sure a journal
+ * gets created.
+ */
+ if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+ !journal_size)
+ journal_size = -1;
+ if (!fs_type &&
+ (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
+ fs_type = "journal";
+ set_fs_defaults(fs_type, ¶m, blocksize, &inode_ratio);
if (param.s_blocks_per_group) {
if (param.s_blocks_per_group < 256 ||
feature_set = NULL;
}
if (sparse_option)
- param_ext2->s_feature_ro_compat |=
+ param.s_feature_ro_compat |=
EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
- if (feature_set && !strncasecmp(feature_set, "none", 4))
- feature_set = NULL;
- if (feature_set && e2p_edit_feature(feature_set,
- ¶m_ext2->s_feature_compat,
- ok_features)) {
- fprintf(stderr, _("Invalid filesystem option set: %s\n"),
- feature_set);
- exit(1);
- }
}
int main (int argc, char *argv[])
#endif
}
- journal_blocks = journal_size * 1024 / (fs->blocksize / 1024);
if (journal_device) {
ext2_filsys jfs;
printf(_("done\n"));
ext2fs_close(jfs);
} else if (journal_size) {
+ if (journal_size < 0)
+ journal_blocks = journal_default_size(fs->super->s_blocks_count);
+ else
+ journal_blocks = journal_size * 1024 /
+ (fs->blocksize / 1024);
if (!quiet)
printf(_("Creating journal (%d blocks): "),
journal_blocks);
]
[
.B \-j
+]
+[
+.B \-J
.I journal-options
]
[
.B w
in weeks. A value of zero will disable the timedependent checking.
.TP
-.BR \-j " journal_options"
+.B -j
+Add an ext3 journal to the filesystem.
+If the
+.B \-J
+option is not specified, the default journal parameters will used will create
+an appropriately sized journal (given the size of the filesystem)
+stored within the filesystem.
+.TP
+.BR \-J " journal_options"
add a journal inode or device to the filesystem.
Journal options are comma
separated, and may take an argument using the equals ('=') sign.
-Currently two options are supported,
+Currently only two (mutually exclusive) options are supported,
.I size
and
.IR device .
-One these two options must be specified when
-building the journal.
-The
-.I size
-option takes a numerical argument which specifies the size of the
-journal in MB (1024*1024 bytes). Any size between 4MB and 100MB may be used.
-Use of this option implies that the journal will be stored in the
-filesystem, so it must be small enough to fit into the filesystem.
-The
-.I device
-option takes a filename which specifies a block device (external
-to the filesystem) which will contain the external journal.
+.TP
+.BI "\-J size=" journal-size
+Create a journal stored in the filesystem of size
+.IR journal-size .
+The size of the journal must be between 1MB and 100MB and there
+must be sufficient free space in the filesystem to create a journal of
+that size.
+.TP
+.BI "\-J device=" external-journal
+Add an external journal found on a block device
+named by
+.I external-journal
+to the filesystem.
+The external
+journal must have been already created using the command
+.B mke2fs -O journal_dev
+.IR journal-device.
.TP
.B \-l
list the contents of the filesystem superblock.
#include "et/com_err.h"
#include "uuid/uuid.h"
#include "e2p/e2p.h"
+#include "jfs_user.h"
#include "util.h"
#include "../version.h"
const char * program_name = "tune2fs";
char * device_name;
char * new_label, *new_last_mounted, *new_UUID;
-const char *journal_opts;
static int c_flag, C_flag, e_flag, g_flag, i_flag, l_flag, L_flag;
static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag;
static int print_label;
fprintf(stderr,
_("Usage: %s [-c max-mounts-count] [-e errors-behavior] "
"[-g group]\n"
- "\t[-i interval[d|m|w]] [-j journal-options]\n"
+ "\t[-i interval[d|m|w]] [-j] [-J journal-options]\n"
"\t[-l] [-s sparse-flag] [-m reserved-blocks-percent]\n"
"\t[-r reserved-blocks-count] [-u user] [-C mount-count]\n"
"\t[-L volume-label] [-M last-mounted-dir] [-U UUID]\n"
};
/*
+ * Remove an external journal from the filesystem
+ */
+static void remove_journal_device(ext2_filsys fs)
+{
+ char *journal_device;
+ ext2_filsys jfs;
+ char buf[1024];
+ journal_superblock_t *jsb;
+ int i, nr_users;
+ errcode_t retval;
+
+ journal_device = ext2fs_find_block_device(fs->super->s_journal_dev);
+ if (!journal_device)
+ return;
+
+ retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
+ EXT2_FLAG_JOURNAL_DEV_OK, 0,
+ fs->blocksize, unix_io_manager, &jfs);
+ if (retval) {
+ com_err(program_name, retval,
+ _("while trying to open external journal"));
+ exit(1);
+ }
+ if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+ fprintf(stderr, "%s is not a journal device.\n",
+ journal_device);
+ exit(1);
+ }
+
+ /* Get the journal superblock */
+ if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) {
+ com_err(program_name, retval,
+ _("while reading journal superblock"));
+ exit(1);
+ }
+
+ jsb = (journal_superblock_t *) buf;
+ if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
+ (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
+ fprintf(stderr, _("Journal superblock not found!\n"));
+ exit(1);
+ }
+
+ /* Find the filesystem UUID */
+ nr_users = ntohl(jsb->s_nr_users);
+ for (i=0; i < nr_users; i++) {
+ if (memcmp(fs->super->s_uuid,
+ &jsb->s_users[i*16], 16) == 0)
+ break;
+ }
+ if (i >= nr_users) {
+ fprintf(stderr, "Filesystem's UUID not found on journal device.\n");
+ exit(1);
+ }
+ nr_users--;
+ for (i=0; i < nr_users; i++)
+ memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16);
+ jsb->s_nr_users = htonl(nr_users);
+
+ /* Write back the journal superblock */
+ if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) {
+ com_err(program_name, retval,
+ "while writing journal superblock.");
+ exit(1);
+ }
+
+ fs->super->s_journal_dev = 0;
+ memset(fs->super->s_journal_uuid, 0,
+ sizeof(fs->super->s_journal_uuid));
+ ext2fs_mark_super_dirty(fs);
+}
+
+
+/*
* Update the feature set as provided by the user.
*/
static void update_feature_set(ext2_filsys fs, char *features)
exit(1);
}
}
+ if (sb->s_journal_dev)
+ remove_journal_device(fs);
}
if (journal && !old_journal) {
/*
* creating the journal. We supply a default size if
* necessary.
*/
- if (!journal_opts)
- journal_opts = "size=16";
+ if (!journal_size)
+ journal_size = -1;
sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
journal = old_journal;
}
-
+
if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
(sb->s_feature_compat || sb->s_feature_ro_compat ||
sb->s_feature_incompat))
fprintf(stderr, _("The filesystem already has a journal.\n"));
exit(1);
}
- parse_journal_opts(journal_opts);
- journal_blocks = journal_size * 1024 / (fs->blocksize / 1024);
if (journal_device) {
check_plausibility(journal_device);
check_mount(journal_device, 0, _("journal"));
} else if (journal_size) {
printf(_("Creating journal inode: "));
fflush(stdout);
+ if (journal_size < 0)
+ journal_blocks = journal_default_size(fs->super->s_blocks_count);
+ else
+ journal_blocks = journal_size * 1024 / (fs->blocksize / 1024);
retval = ext2fs_add_journal_inode(fs, journal_blocks,
journal_flags);
if (retval) {
fprintf (stderr, _("tune2fs %s, %s for EXT2 FS %s, %s\n"),
E2FSPROGS_VERSION, E2FSPROGS_DATE,
EXT2FS_VERSION, EXT2FS_DATE);
- while ((c = getopt (argc, argv, "c:e:g:i:j:lm:r:s:u:C:L:M:O:U:")) != EOF)
+ while ((c = getopt (argc, argv, "c:e:g:i:jlm:r:s:u:C:J:L:M:O:U:")) != EOF)
switch (c)
{
case 'c':
open_flag = EXT2_FLAG_RW;
break;
case 'j':
- journal_opts = optarg;
+ if (!journal_size)
+ journal_size = -1;
+ break;
+ case 'J':
+ parse_journal_opts(optarg);
open_flag = EXT2_FLAG_RW;
break;
case 'l':
}
if (features_cmd)
update_feature_set(fs, features_cmd);
- if (journal_opts)
+ if (journal_size || journal_device)
add_journal(fs);
if (U_flag) {