[PATCH] ext3: external journal device as a mount option

The patch below adds a new mount option to allow the external journal
device to be specified.

The syntax is as follows:
# mount -t ext3 -o journal_dev=0x0820 ...
where 0x0820 means major=8 and minor=32.

Signed-off-by: Johann Lombardi <johann.lombardi@bull.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Johann Lombardi 2006-01-08 01:03:20 -08:00 committed by Linus Torvalds
parent bf066c7db7
commit 71b9625744
2 changed files with 49 additions and 10 deletions

View file

@ -22,6 +22,11 @@ journal=inum When a journal already exists, this option is
the inode which will represent the ext3 file
system's journal file.
journal_dev=devnum When the external journal device's major/minor numbers
have changed, this option allows to specify the new
journal location. The journal device is identified
through its new major/minor numbers encoded in devnum.
noload Don't load the journal on mounting.
data=journal All data are committed into the journal prior

View file

@ -43,7 +43,8 @@
#include "acl.h"
#include "namei.h"
static int ext3_load_journal(struct super_block *, struct ext3_super_block *);
static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
unsigned long journal_devnum);
static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
int);
static void ext3_commit_super (struct super_block * sb,
@ -628,7 +629,7 @@ enum {
Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh,
Opt_commit, Opt_journal_update, Opt_journal_inum,
Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
@ -666,6 +667,7 @@ static match_table_t tokens = {
{Opt_commit, "commit=%u"},
{Opt_journal_update, "journal=update"},
{Opt_journal_inum, "journal=%u"},
{Opt_journal_dev, "journal_dev=%u"},
{Opt_abort, "abort"},
{Opt_data_journal, "data=journal"},
{Opt_data_ordered, "data=ordered"},
@ -705,8 +707,9 @@ static unsigned long get_sb_block(void **data)
return sb_block;
}
static int parse_options (char * options, struct super_block *sb,
unsigned long * inum, unsigned long *n_blocks_count, int is_remount)
static int parse_options (char *options, struct super_block *sb,
unsigned long *inum, unsigned long *journal_devnum,
unsigned long *n_blocks_count, int is_remount)
{
struct ext3_sb_info *sbi = EXT3_SB(sb);
char * p;
@ -839,6 +842,16 @@ static int parse_options (char * options, struct super_block *sb,
return 0;
*inum = option;
break;
case Opt_journal_dev:
if (is_remount) {
printk(KERN_ERR "EXT3-fs: cannot specify "
"journal on remount\n");
return 0;
}
if (match_int(&args[0], &option))
return 0;
*journal_devnum = option;
break;
case Opt_noload:
set_opt (sbi->s_mount_opt, NOLOAD);
break;
@ -1331,6 +1344,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
unsigned long logic_sb_block;
unsigned long offset = 0;
unsigned long journal_inum = 0;
unsigned long journal_devnum = 0;
unsigned long def_mount_opts;
struct inode *root;
int blocksize;
@ -1411,7 +1425,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
set_opt(sbi->s_mount_opt, RESERVATION);
if (!parse_options ((char *) data, sb, &journal_inum, NULL, 0))
if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
NULL, 0))
goto failed_mount;
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
@ -1622,7 +1637,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
*/
if (!test_opt(sb, NOLOAD) &&
EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
if (ext3_load_journal(sb, es))
if (ext3_load_journal(sb, es, journal_devnum))
goto failed_mount2;
} else if (journal_inum) {
if (ext3_create_journal(sb, es, journal_inum))
@ -1902,15 +1917,24 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
return NULL;
}
static int ext3_load_journal(struct super_block * sb,
struct ext3_super_block * es)
static int ext3_load_journal(struct super_block *sb,
struct ext3_super_block *es,
unsigned long journal_devnum)
{
journal_t *journal;
int journal_inum = le32_to_cpu(es->s_journal_inum);
dev_t journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
dev_t journal_dev;
int err = 0;
int really_read_only;
if (journal_devnum &&
journal_devnum != le32_to_cpu(es->s_journal_dev)) {
printk(KERN_INFO "EXT3-fs: external journal device major/minor "
"numbers have changed\n");
journal_dev = new_decode_dev(journal_devnum);
} else
journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
really_read_only = bdev_read_only(sb->s_bdev);
/*
@ -1969,6 +1993,16 @@ static int ext3_load_journal(struct super_block * sb,
EXT3_SB(sb)->s_journal = journal;
ext3_clear_journal_err(sb, es);
if (journal_devnum &&
journal_devnum != le32_to_cpu(es->s_journal_dev)) {
es->s_journal_dev = cpu_to_le32(journal_devnum);
sb->s_dirt = 1;
/* Make sure we flush the recovery flag to disk. */
ext3_commit_super(sb, es, 1);
}
return 0;
}
@ -2197,7 +2231,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
/*
* Allow the "check" option to be passed as a remount option.
*/
if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) {
if (!parse_options(data, sb, NULL, NULL, &n_blocks_count, 1)) {
err = -EINVAL;
goto restore_opts;
}