diff options
Diffstat (limited to 'fs/ext3/super.c')
-rw-r--r-- | fs/ext3/super.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 4e6730622d90..7c45acf94589 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -43,7 +43,8 @@ | |||
43 | #include "acl.h" | 43 | #include "acl.h" |
44 | #include "namei.h" | 44 | #include "namei.h" |
45 | 45 | ||
46 | static int ext3_load_journal(struct super_block *, struct ext3_super_block *); | 46 | static int ext3_load_journal(struct super_block *, struct ext3_super_block *, |
47 | unsigned long journal_devnum); | ||
47 | static int ext3_create_journal(struct super_block *, struct ext3_super_block *, | 48 | static int ext3_create_journal(struct super_block *, struct ext3_super_block *, |
48 | int); | 49 | int); |
49 | static void ext3_commit_super (struct super_block * sb, | 50 | static void ext3_commit_super (struct super_block * sb, |
@@ -628,7 +629,7 @@ enum { | |||
628 | Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, | 629 | Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, |
629 | Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, | 630 | Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, |
630 | Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, | 631 | Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, |
631 | Opt_commit, Opt_journal_update, Opt_journal_inum, | 632 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, |
632 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 633 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
633 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 634 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
634 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, | 635 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, |
@@ -666,6 +667,7 @@ static match_table_t tokens = { | |||
666 | {Opt_commit, "commit=%u"}, | 667 | {Opt_commit, "commit=%u"}, |
667 | {Opt_journal_update, "journal=update"}, | 668 | {Opt_journal_update, "journal=update"}, |
668 | {Opt_journal_inum, "journal=%u"}, | 669 | {Opt_journal_inum, "journal=%u"}, |
670 | {Opt_journal_dev, "journal_dev=%u"}, | ||
669 | {Opt_abort, "abort"}, | 671 | {Opt_abort, "abort"}, |
670 | {Opt_data_journal, "data=journal"}, | 672 | {Opt_data_journal, "data=journal"}, |
671 | {Opt_data_ordered, "data=ordered"}, | 673 | {Opt_data_ordered, "data=ordered"}, |
@@ -705,8 +707,9 @@ static unsigned long get_sb_block(void **data) | |||
705 | return sb_block; | 707 | return sb_block; |
706 | } | 708 | } |
707 | 709 | ||
708 | static int parse_options (char * options, struct super_block *sb, | 710 | static int parse_options (char *options, struct super_block *sb, |
709 | unsigned long * inum, unsigned long *n_blocks_count, int is_remount) | 711 | unsigned long *inum, unsigned long *journal_devnum, |
712 | unsigned long *n_blocks_count, int is_remount) | ||
710 | { | 713 | { |
711 | struct ext3_sb_info *sbi = EXT3_SB(sb); | 714 | struct ext3_sb_info *sbi = EXT3_SB(sb); |
712 | char * p; | 715 | char * p; |
@@ -839,6 +842,16 @@ static int parse_options (char * options, struct super_block *sb, | |||
839 | return 0; | 842 | return 0; |
840 | *inum = option; | 843 | *inum = option; |
841 | break; | 844 | break; |
845 | case Opt_journal_dev: | ||
846 | if (is_remount) { | ||
847 | printk(KERN_ERR "EXT3-fs: cannot specify " | ||
848 | "journal on remount\n"); | ||
849 | return 0; | ||
850 | } | ||
851 | if (match_int(&args[0], &option)) | ||
852 | return 0; | ||
853 | *journal_devnum = option; | ||
854 | break; | ||
842 | case Opt_noload: | 855 | case Opt_noload: |
843 | set_opt (sbi->s_mount_opt, NOLOAD); | 856 | set_opt (sbi->s_mount_opt, NOLOAD); |
844 | break; | 857 | break; |
@@ -1331,6 +1344,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1331 | unsigned long logic_sb_block; | 1344 | unsigned long logic_sb_block; |
1332 | unsigned long offset = 0; | 1345 | unsigned long offset = 0; |
1333 | unsigned long journal_inum = 0; | 1346 | unsigned long journal_inum = 0; |
1347 | unsigned long journal_devnum = 0; | ||
1334 | unsigned long def_mount_opts; | 1348 | unsigned long def_mount_opts; |
1335 | struct inode *root; | 1349 | struct inode *root; |
1336 | int blocksize; | 1350 | int blocksize; |
@@ -1411,7 +1425,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1411 | 1425 | ||
1412 | set_opt(sbi->s_mount_opt, RESERVATION); | 1426 | set_opt(sbi->s_mount_opt, RESERVATION); |
1413 | 1427 | ||
1414 | if (!parse_options ((char *) data, sb, &journal_inum, NULL, 0)) | 1428 | if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum, |
1429 | NULL, 0)) | ||
1415 | goto failed_mount; | 1430 | goto failed_mount; |
1416 | 1431 | ||
1417 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | | 1432 | 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 | */ | 1637 | */ |
1623 | if (!test_opt(sb, NOLOAD) && | 1638 | if (!test_opt(sb, NOLOAD) && |
1624 | EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { | 1639 | EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { |
1625 | if (ext3_load_journal(sb, es)) | 1640 | if (ext3_load_journal(sb, es, journal_devnum)) |
1626 | goto failed_mount2; | 1641 | goto failed_mount2; |
1627 | } else if (journal_inum) { | 1642 | } else if (journal_inum) { |
1628 | if (ext3_create_journal(sb, es, journal_inum)) | 1643 | if (ext3_create_journal(sb, es, journal_inum)) |
@@ -1902,15 +1917,24 @@ out_bdev: | |||
1902 | return NULL; | 1917 | return NULL; |
1903 | } | 1918 | } |
1904 | 1919 | ||
1905 | static int ext3_load_journal(struct super_block * sb, | 1920 | static int ext3_load_journal(struct super_block *sb, |
1906 | struct ext3_super_block * es) | 1921 | struct ext3_super_block *es, |
1922 | unsigned long journal_devnum) | ||
1907 | { | 1923 | { |
1908 | journal_t *journal; | 1924 | journal_t *journal; |
1909 | int journal_inum = le32_to_cpu(es->s_journal_inum); | 1925 | int journal_inum = le32_to_cpu(es->s_journal_inum); |
1910 | dev_t journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev)); | 1926 | dev_t journal_dev; |
1911 | int err = 0; | 1927 | int err = 0; |
1912 | int really_read_only; | 1928 | int really_read_only; |
1913 | 1929 | ||
1930 | if (journal_devnum && | ||
1931 | journal_devnum != le32_to_cpu(es->s_journal_dev)) { | ||
1932 | printk(KERN_INFO "EXT3-fs: external journal device major/minor " | ||
1933 | "numbers have changed\n"); | ||
1934 | journal_dev = new_decode_dev(journal_devnum); | ||
1935 | } else | ||
1936 | journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev)); | ||
1937 | |||
1914 | really_read_only = bdev_read_only(sb->s_bdev); | 1938 | really_read_only = bdev_read_only(sb->s_bdev); |
1915 | 1939 | ||
1916 | /* | 1940 | /* |
@@ -1969,6 +1993,16 @@ static int ext3_load_journal(struct super_block * sb, | |||
1969 | 1993 | ||
1970 | EXT3_SB(sb)->s_journal = journal; | 1994 | EXT3_SB(sb)->s_journal = journal; |
1971 | ext3_clear_journal_err(sb, es); | 1995 | ext3_clear_journal_err(sb, es); |
1996 | |||
1997 | if (journal_devnum && | ||
1998 | journal_devnum != le32_to_cpu(es->s_journal_dev)) { | ||
1999 | es->s_journal_dev = cpu_to_le32(journal_devnum); | ||
2000 | sb->s_dirt = 1; | ||
2001 | |||
2002 | /* Make sure we flush the recovery flag to disk. */ | ||
2003 | ext3_commit_super(sb, es, 1); | ||
2004 | } | ||
2005 | |||
1972 | return 0; | 2006 | return 0; |
1973 | } | 2007 | } |
1974 | 2008 | ||
@@ -2197,7 +2231,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
2197 | /* | 2231 | /* |
2198 | * Allow the "check" option to be passed as a remount option. | 2232 | * Allow the "check" option to be passed as a remount option. |
2199 | */ | 2233 | */ |
2200 | if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) { | 2234 | if (!parse_options(data, sb, NULL, NULL, &n_blocks_count, 1)) { |
2201 | err = -EINVAL; | 2235 | err = -EINVAL; |
2202 | goto restore_opts; | 2236 | goto restore_opts; |
2203 | } | 2237 | } |