diff options
-rw-r--r-- | Documentation/filesystems/ext4.txt | 7 | ||||
-rw-r--r-- | fs/ext4/super.c | 47 |
2 files changed, 48 insertions, 6 deletions
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index f7cbf574a875..b91cfaaf6a0f 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt | |||
@@ -144,11 +144,12 @@ journal_async_commit Commit block can be written to disk without waiting | |||
144 | mount the device. This will enable 'journal_checksum' | 144 | mount the device. This will enable 'journal_checksum' |
145 | internally. | 145 | internally. |
146 | 146 | ||
147 | journal_path=path | ||
147 | journal_dev=devnum When the external journal device's major/minor numbers | 148 | journal_dev=devnum When the external journal device's major/minor numbers |
148 | have changed, this option allows the user to specify | 149 | have changed, these options allow the user to specify |
149 | the new journal location. The journal device is | 150 | the new journal location. The journal device is |
150 | identified through its new major/minor numbers encoded | 151 | identified through either its new major/minor numbers |
151 | in devnum. | 152 | encoded in devnum, or via a path to the device. |
152 | 153 | ||
153 | norecovery Don't load the journal on mounting. Note that | 154 | norecovery Don't load the journal on mounting. Note that |
154 | noload if the filesystem was not unmounted cleanly, | 155 | noload if the filesystem was not unmounted cleanly, |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b59373b625e9..42337141e79f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -1134,8 +1134,8 @@ enum { | |||
1134 | Opt_nouid32, Opt_debug, Opt_removed, | 1134 | Opt_nouid32, Opt_debug, Opt_removed, |
1135 | Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, | 1135 | Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, |
1136 | Opt_auto_da_alloc, Opt_noauto_da_alloc, Opt_noload, | 1136 | Opt_auto_da_alloc, Opt_noauto_da_alloc, Opt_noload, |
1137 | Opt_commit, Opt_min_batch_time, Opt_max_batch_time, | 1137 | Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev, |
1138 | Opt_journal_dev, Opt_journal_checksum, Opt_journal_async_commit, | 1138 | Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit, |
1139 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 1139 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
1140 | Opt_data_err_abort, Opt_data_err_ignore, | 1140 | Opt_data_err_abort, Opt_data_err_ignore, |
1141 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 1141 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
@@ -1179,6 +1179,7 @@ static const match_table_t tokens = { | |||
1179 | {Opt_min_batch_time, "min_batch_time=%u"}, | 1179 | {Opt_min_batch_time, "min_batch_time=%u"}, |
1180 | {Opt_max_batch_time, "max_batch_time=%u"}, | 1180 | {Opt_max_batch_time, "max_batch_time=%u"}, |
1181 | {Opt_journal_dev, "journal_dev=%u"}, | 1181 | {Opt_journal_dev, "journal_dev=%u"}, |
1182 | {Opt_journal_path, "journal_path=%s"}, | ||
1182 | {Opt_journal_checksum, "journal_checksum"}, | 1183 | {Opt_journal_checksum, "journal_checksum"}, |
1183 | {Opt_journal_async_commit, "journal_async_commit"}, | 1184 | {Opt_journal_async_commit, "journal_async_commit"}, |
1184 | {Opt_abort, "abort"}, | 1185 | {Opt_abort, "abort"}, |
@@ -1338,6 +1339,7 @@ static int clear_qf_name(struct super_block *sb, int qtype) | |||
1338 | #define MOPT_NO_EXT2 0x0100 | 1339 | #define MOPT_NO_EXT2 0x0100 |
1339 | #define MOPT_NO_EXT3 0x0200 | 1340 | #define MOPT_NO_EXT3 0x0200 |
1340 | #define MOPT_EXT4_ONLY (MOPT_NO_EXT2 | MOPT_NO_EXT3) | 1341 | #define MOPT_EXT4_ONLY (MOPT_NO_EXT2 | MOPT_NO_EXT3) |
1342 | #define MOPT_STRING 0x0400 | ||
1341 | 1343 | ||
1342 | static const struct mount_opts { | 1344 | static const struct mount_opts { |
1343 | int token; | 1345 | int token; |
@@ -1387,6 +1389,7 @@ static const struct mount_opts { | |||
1387 | {Opt_resuid, 0, MOPT_GTE0}, | 1389 | {Opt_resuid, 0, MOPT_GTE0}, |
1388 | {Opt_resgid, 0, MOPT_GTE0}, | 1390 | {Opt_resgid, 0, MOPT_GTE0}, |
1389 | {Opt_journal_dev, 0, MOPT_GTE0}, | 1391 | {Opt_journal_dev, 0, MOPT_GTE0}, |
1392 | {Opt_journal_path, 0, MOPT_STRING}, | ||
1390 | {Opt_journal_ioprio, 0, MOPT_GTE0}, | 1393 | {Opt_journal_ioprio, 0, MOPT_GTE0}, |
1391 | {Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_NO_EXT2 | MOPT_DATAJ}, | 1394 | {Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_NO_EXT2 | MOPT_DATAJ}, |
1392 | {Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ}, | 1395 | {Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ}, |
@@ -1480,7 +1483,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
1480 | return -1; | 1483 | return -1; |
1481 | } | 1484 | } |
1482 | 1485 | ||
1483 | if (args->from && match_int(args, &arg)) | 1486 | if (args->from && !(m->flags & MOPT_STRING) && match_int(args, &arg)) |
1484 | return -1; | 1487 | return -1; |
1485 | if (args->from && (m->flags & MOPT_GTE0) && (arg < 0)) | 1488 | if (args->from && (m->flags & MOPT_GTE0) && (arg < 0)) |
1486 | return -1; | 1489 | return -1; |
@@ -1544,6 +1547,44 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, | |||
1544 | return -1; | 1547 | return -1; |
1545 | } | 1548 | } |
1546 | *journal_devnum = arg; | 1549 | *journal_devnum = arg; |
1550 | } else if (token == Opt_journal_path) { | ||
1551 | char *journal_path; | ||
1552 | struct inode *journal_inode; | ||
1553 | struct path path; | ||
1554 | int error; | ||
1555 | |||
1556 | if (is_remount) { | ||
1557 | ext4_msg(sb, KERN_ERR, | ||
1558 | "Cannot specify journal on remount"); | ||
1559 | return -1; | ||
1560 | } | ||
1561 | journal_path = match_strdup(&args[0]); | ||
1562 | if (!journal_path) { | ||
1563 | ext4_msg(sb, KERN_ERR, "error: could not dup " | ||
1564 | "journal device string"); | ||
1565 | return -1; | ||
1566 | } | ||
1567 | |||
1568 | error = kern_path(journal_path, LOOKUP_FOLLOW, &path); | ||
1569 | if (error) { | ||
1570 | ext4_msg(sb, KERN_ERR, "error: could not find " | ||
1571 | "journal device path: error %d", error); | ||
1572 | kfree(journal_path); | ||
1573 | return -1; | ||
1574 | } | ||
1575 | |||
1576 | journal_inode = path.dentry->d_inode; | ||
1577 | if (!S_ISBLK(journal_inode->i_mode)) { | ||
1578 | ext4_msg(sb, KERN_ERR, "error: journal path %s " | ||
1579 | "is not a block device", journal_path); | ||
1580 | path_put(&path); | ||
1581 | kfree(journal_path); | ||
1582 | return -1; | ||
1583 | } | ||
1584 | |||
1585 | *journal_devnum = new_encode_dev(journal_inode->i_rdev); | ||
1586 | path_put(&path); | ||
1587 | kfree(journal_path); | ||
1547 | } else if (token == Opt_journal_ioprio) { | 1588 | } else if (token == Opt_journal_ioprio) { |
1548 | if (arg > 7) { | 1589 | if (arg > 7) { |
1549 | ext4_msg(sb, KERN_ERR, "Invalid journal IO priority" | 1590 | ext4_msg(sb, KERN_ERR, "Invalid journal IO priority" |