Signed-off-by: Johann Lombardi --- linux-2.6.12.orig/fs/ext3/super.c 2005-06-17 21:48:29.000000000 +0200 +++ linux-2.6.12/fs/ext3/super.c 2005-11-07 13:37:30.000000000 +0100 @@ -39,7 +39,8 @@ #include "xattr.h" #include "acl.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, @@ -586,7 +587,7 @@ enum { Opt_nouid32, Opt_check, 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, @@ -624,6 +625,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"}, @@ -663,8 +665,9 @@ static unsigned long get_sb_block(void * 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; @@ -805,6 +808,16 @@ static int parse_options (char * options 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; @@ -1250,6 +1263,7 @@ static int ext3_fill_super (struct super 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; @@ -1330,7 +1344,8 @@ static int ext3_fill_super (struct super 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) | @@ -1541,7 +1556,7 @@ static int ext3_fill_super (struct super */ 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)) @@ -1821,15 +1836,24 @@ out_bdev: 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); /* @@ -1888,6 +1912,16 @@ static int ext3_load_journal(struct supe 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; } @@ -2093,13 +2127,13 @@ static int ext3_remount (struct super_bl { struct ext3_super_block * es; struct ext3_sb_info *sbi = EXT3_SB(sb); - unsigned long tmp; + unsigned long tmp1, tmp2; unsigned long n_blocks_count = 0; /* * Allow the "check" option to be passed as a remount option. */ - if (!parse_options(data, sb, &tmp, &n_blocks_count, 1)) + if (!parse_options(data, sb, &tmp1, &tmp2, &n_blocks_count, 1)) return -EINVAL; if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)