Commit 71b96257 authored by Johann Lombardi's avatar Johann Lombardi Committed by Linus Torvalds

[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: default avatarJohann Lombardi <johann.lombardi@bull.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent bf066c7d
...@@ -22,6 +22,11 @@ journal=inum When a journal already exists, this option is ...@@ -22,6 +22,11 @@ journal=inum When a journal already exists, this option is
the inode which will represent the ext3 file the inode which will represent the ext3 file
system's journal 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. noload Don't load the journal on mounting.
data=journal All data are committed into the journal prior data=journal All data are committed into the journal prior
......
...@@ -43,7 +43,8 @@ ...@@ -43,7 +43,8 @@
#include "acl.h" #include "acl.h"
#include "namei.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 *, static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
int); int);
static void ext3_commit_super (struct super_block * sb, static void ext3_commit_super (struct super_block * sb,
...@@ -628,7 +629,7 @@ enum { ...@@ -628,7 +629,7 @@ enum {
Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, 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_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
...@@ -666,6 +667,7 @@ static match_table_t tokens = { ...@@ -666,6 +667,7 @@ static match_table_t tokens = {
{Opt_commit, "commit=%u"}, {Opt_commit, "commit=%u"},
{Opt_journal_update, "journal=update"}, {Opt_journal_update, "journal=update"},
{Opt_journal_inum, "journal=%u"}, {Opt_journal_inum, "journal=%u"},
{Opt_journal_dev, "journal_dev=%u"},
{Opt_abort, "abort"}, {Opt_abort, "abort"},
{Opt_data_journal, "data=journal"}, {Opt_data_journal, "data=journal"},
{Opt_data_ordered, "data=ordered"}, {Opt_data_ordered, "data=ordered"},
...@@ -705,8 +707,9 @@ static unsigned long get_sb_block(void **data) ...@@ -705,8 +707,9 @@ static unsigned long get_sb_block(void **data)
return sb_block; return sb_block;
} }
static int parse_options (char * options, struct super_block *sb, static int parse_options (char *options, struct super_block *sb,
unsigned long * inum, unsigned long *n_blocks_count, int is_remount) unsigned long *inum, unsigned long *journal_devnum,
unsigned long *n_blocks_count, int is_remount)
{ {
struct ext3_sb_info *sbi = EXT3_SB(sb); struct ext3_sb_info *sbi = EXT3_SB(sb);
char * p; char * p;
...@@ -839,6 +842,16 @@ static int parse_options (char * options, struct super_block *sb, ...@@ -839,6 +842,16 @@ static int parse_options (char * options, struct super_block *sb,
return 0; return 0;
*inum = option; *inum = option;
break; 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: case Opt_noload:
set_opt (sbi->s_mount_opt, NOLOAD); set_opt (sbi->s_mount_opt, NOLOAD);
break; break;
...@@ -1331,6 +1344,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1331,6 +1344,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
unsigned long logic_sb_block; unsigned long logic_sb_block;
unsigned long offset = 0; unsigned long offset = 0;
unsigned long journal_inum = 0; unsigned long journal_inum = 0;
unsigned long journal_devnum = 0;
unsigned long def_mount_opts; unsigned long def_mount_opts;
struct inode *root; struct inode *root;
int blocksize; int blocksize;
...@@ -1411,7 +1425,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) ...@@ -1411,7 +1425,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
set_opt(sbi->s_mount_opt, RESERVATION); 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; goto failed_mount;
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | 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) ...@@ -1622,7 +1637,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
*/ */
if (!test_opt(sb, NOLOAD) && if (!test_opt(sb, NOLOAD) &&
EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { 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; goto failed_mount2;
} else if (journal_inum) { } else if (journal_inum) {
if (ext3_create_journal(sb, es, 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, ...@@ -1902,15 +1917,24 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
return NULL; return NULL;
} }
static int ext3_load_journal(struct super_block * sb, static int ext3_load_journal(struct super_block *sb,
struct ext3_super_block * es) struct ext3_super_block *es,
unsigned long journal_devnum)
{ {
journal_t *journal; journal_t *journal;
int journal_inum = le32_to_cpu(es->s_journal_inum); 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 err = 0;
int really_read_only; 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); really_read_only = bdev_read_only(sb->s_bdev);
/* /*
...@@ -1969,6 +1993,16 @@ static int ext3_load_journal(struct super_block * sb, ...@@ -1969,6 +1993,16 @@ static int ext3_load_journal(struct super_block * sb,
EXT3_SB(sb)->s_journal = journal; EXT3_SB(sb)->s_journal = journal;
ext3_clear_journal_err(sb, es); 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; return 0;
} }
...@@ -2197,7 +2231,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) ...@@ -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. * 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; err = -EINVAL;
goto restore_opts; goto restore_opts;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment