aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2013-07-31 15:33:00 -0400
committerJan Kara <jack@suse.cz>2013-07-31 16:11:15 -0400
commitcf7eff4666629de006c5ed78de79e40f483c3b06 (patch)
tree83248c91e87f0716c967414cb110340baca1d7c1
parent75b9222556ede41b9bd9d2d0dcb998f668b49b5f (diff)
ext3: allow specifying external journal by pathname mount option
It's always been a hassle that if an external journal's device number changes, the filesystem won't mount. And since boot-time enumeration can change, device number changes aren't unusual. The current mechanism to update the journal location is by passing in a mount option w/ a new devnum, but that's a hassle; it's a manual approach, fixing things after the fact. Adding a mount option, "-o journal_path=/dev/$DEVICE" would help, since then we can do i.e. # mount -o journal_path=/dev/disk/by-label/$JOURNAL_LABEL ... and it'll mount even if the devnum has changed, as shown here: # losetup /dev/loop0 journalfile # mke2fs -L mylabel-journal -O journal_dev /dev/loop0 # mkfs.ext3 -L mylabel -J device=/dev/loop0 /dev/sdb1 Change the journal device number: # losetup -d /dev/loop0 # losetup /dev/loop1 journalfile And today it will fail: # mount /dev/sdb1 /mnt/test mount: wrong fs type, bad option, bad superblock on /dev/sdb1, missing codepage or helper program, or other error In some cases useful info is found in syslog - try dmesg | tail or so # dmesg | tail -n 1 [17343.240702] EXT3-fs (sdb1): error: couldn't read superblock of external journal But with this new mount option, we can specify the new path: # mount -o journal_path=/dev/loop1 /dev/sdb1 /mnt/test # (which does update the encoded device number, incidentally): # umount /dev/sdb1 # dumpe2fs -h /dev/sdb1 | grep "Journal device" dumpe2fs 1.41.12 (17-May-2010) Journal device: 0x0701 But best of all we can just always mount by journal-path, and it'll always work: # mount -o journal_path=/dev/disk/by-label/mylabel-journal /dev/sdb1 /mnt/test # So the journal_path option can be specified in fstab, and as long as the disk is available somewhere, and findable by label (or by UUID), we can mount. Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--Documentation/filesystems/ext3.txt7
-rw-r--r--fs/ext3/super.c43
2 files changed, 47 insertions, 3 deletions
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 293855e95000..7ed0d17d6721 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -26,11 +26,12 @@ journal=inum When a journal already exists, this option is ignored.
26 Otherwise, it specifies the number of the inode which 26 Otherwise, it specifies the number of the inode which
27 will represent the ext3 file system's journal file. 27 will represent the ext3 file system's journal file.
28 28
29journal_path=path
29journal_dev=devnum When the external journal device's major/minor numbers 30journal_dev=devnum When the external journal device's major/minor numbers
30 have changed, this option allows the user to specify 31 have changed, these options allow the user to specify
31 the new journal location. The journal device is 32 the new journal location. The journal device is
32 identified through its new major/minor numbers encoded 33 identified through either its new major/minor numbers
33 in devnum. 34 encoded in devnum, or via a path to the device.
34 35
35norecovery Don't load the journal on mounting. Note that this forces 36norecovery Don't load the journal on mounting. Note that this forces
36noload mount of inconsistent filesystem, which can lead to 37noload mount of inconsistent filesystem, which can lead to
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index c47f14750722..c50c76190373 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -27,6 +27,7 @@
27#include <linux/seq_file.h> 27#include <linux/seq_file.h>
28#include <linux/log2.h> 28#include <linux/log2.h>
29#include <linux/cleancache.h> 29#include <linux/cleancache.h>
30#include <linux/namei.h>
30 31
31#include <asm/uaccess.h> 32#include <asm/uaccess.h>
32 33
@@ -819,6 +820,7 @@ enum {
819 Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, 820 Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
820 Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, 821 Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
821 Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, 822 Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
823 Opt_journal_path,
822 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, 824 Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
823 Opt_data_err_abort, Opt_data_err_ignore, 825 Opt_data_err_abort, Opt_data_err_ignore,
824 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, 826 Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
@@ -860,6 +862,7 @@ static const match_table_t tokens = {
860 {Opt_journal_update, "journal=update"}, 862 {Opt_journal_update, "journal=update"},
861 {Opt_journal_inum, "journal=%u"}, 863 {Opt_journal_inum, "journal=%u"},
862 {Opt_journal_dev, "journal_dev=%u"}, 864 {Opt_journal_dev, "journal_dev=%u"},
865 {Opt_journal_path, "journal_path=%s"},
863 {Opt_abort, "abort"}, 866 {Opt_abort, "abort"},
864 {Opt_data_journal, "data=journal"}, 867 {Opt_data_journal, "data=journal"},
865 {Opt_data_ordered, "data=ordered"}, 868 {Opt_data_ordered, "data=ordered"},
@@ -975,6 +978,11 @@ static int parse_options (char *options, struct super_block *sb,
975 int option; 978 int option;
976 kuid_t uid; 979 kuid_t uid;
977 kgid_t gid; 980 kgid_t gid;
981 char *journal_path;
982 struct inode *journal_inode;
983 struct path path;
984 int error;
985
978#ifdef CONFIG_QUOTA 986#ifdef CONFIG_QUOTA
979 int qfmt; 987 int qfmt;
980#endif 988#endif
@@ -1129,6 +1137,41 @@ static int parse_options (char *options, struct super_block *sb,
1129 return 0; 1137 return 0;
1130 *journal_devnum = option; 1138 *journal_devnum = option;
1131 break; 1139 break;
1140 case Opt_journal_path:
1141 if (is_remount) {
1142 ext3_msg(sb, KERN_ERR, "error: cannot specify "
1143 "journal on remount");
1144 return 0;
1145 }
1146
1147 journal_path = match_strdup(&args[0]);
1148 if (!journal_path) {
1149 ext3_msg(sb, KERN_ERR, "error: could not dup "
1150 "journal device string");
1151 return 0;
1152 }
1153
1154 error = kern_path(journal_path, LOOKUP_FOLLOW, &path);
1155 if (error) {
1156 ext3_msg(sb, KERN_ERR, "error: could not find "
1157 "journal device path: error %d", error);
1158 kfree(journal_path);
1159 return 0;
1160 }
1161
1162 journal_inode = path.dentry->d_inode;
1163 if (!S_ISBLK(journal_inode->i_mode)) {
1164 ext3_msg(sb, KERN_ERR, "error: journal path %s "
1165 "is not a block device", journal_path);
1166 path_put(&path);
1167 kfree(journal_path);
1168 return 0;
1169 }
1170
1171 *journal_devnum = new_encode_dev(journal_inode->i_rdev);
1172 path_put(&path);
1173 kfree(journal_path);
1174 break;
1132 case Opt_noload: 1175 case Opt_noload:
1133 set_opt (sbi->s_mount_opt, NOLOAD); 1176 set_opt (sbi->s_mount_opt, NOLOAD);
1134 break; 1177 break;