aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2009-08-18 00:20:23 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-08-18 00:20:23 -0400
commita13fb1a4533f26c1e2b0204d5283b696689645af (patch)
tree1f779dfe2057bef2a5985989f2a347ed32ca9179 /fs/ext4/super.c
parent38877f4e8dbbec12c6fde85ee1fce1dc27ef3290 (diff)
ext4: Add feature set check helper for mount & remount paths
A user reported that although his root ext4 filesystem was mounting fine, other filesystems would not mount, with the: "Filesystem with huge files cannot be mounted RDWR without CONFIG_LBDAF" error on his 32-bit box built without CONFIG_LBDAF. This is because the test at mount time for this situation was not being re-checked on remount, and the normal boot process makes an ro->rw transition, so this was being missed. Refactor to make a common helper function to test the filesystem features against the type of mount request (RO vs. RW) so that we stay consistent. Addresses Red-Hat-Bugzilla: #517650 Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c91
1 files changed, 49 insertions, 42 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index de67c3657b83..4037fe0b5a5c 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2254,6 +2254,49 @@ static struct kobj_type ext4_ktype = {
2254 .release = ext4_sb_release, 2254 .release = ext4_sb_release,
2255}; 2255};
2256 2256
2257/*
2258 * Check whether this filesystem can be mounted based on
2259 * the features present and the RDONLY/RDWR mount requested.
2260 * Returns 1 if this filesystem can be mounted as requested,
2261 * 0 if it cannot be.
2262 */
2263static int ext4_feature_set_ok(struct super_block *sb, int readonly)
2264{
2265 if (EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT4_FEATURE_INCOMPAT_SUPP)) {
2266 ext4_msg(sb, KERN_ERR,
2267 "Couldn't mount because of "
2268 "unsupported optional features (%x)",
2269 (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_incompat) &
2270 ~EXT4_FEATURE_INCOMPAT_SUPP));
2271 return 0;
2272 }
2273
2274 if (readonly)
2275 return 1;
2276
2277 /* Check that feature set is OK for a read-write mount */
2278 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP)) {
2279 ext4_msg(sb, KERN_ERR, "couldn't mount RDWR because of "
2280 "unsupported optional features (%x)",
2281 (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_ro_compat) &
2282 ~EXT4_FEATURE_RO_COMPAT_SUPP));
2283 return 0;
2284 }
2285 /*
2286 * Large file size enabled file system can only be mounted
2287 * read-write on 32-bit systems if kernel is built with CONFIG_LBDAF
2288 */
2289 if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
2290 if (sizeof(blkcnt_t) < sizeof(u64)) {
2291 ext4_msg(sb, KERN_ERR, "Filesystem with huge files "
2292 "cannot be mounted RDWR without "
2293 "CONFIG_LBDAF");
2294 return 0;
2295 }
2296 }
2297 return 1;
2298}
2299
2257static int ext4_fill_super(struct super_block *sb, void *data, int silent) 2300static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2258 __releases(kernel_lock) 2301 __releases(kernel_lock)
2259 __acquires(kernel_lock) 2302 __acquires(kernel_lock)
@@ -2275,7 +2318,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2275 unsigned int db_count; 2318 unsigned int db_count;
2276 unsigned int i; 2319 unsigned int i;
2277 int needs_recovery, has_huge_files; 2320 int needs_recovery, has_huge_files;
2278 int features;
2279 __u64 blocks_count; 2321 __u64 blocks_count;
2280 int err; 2322 int err;
2281 unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; 2323 unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
@@ -2402,39 +2444,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2402 * previously didn't change the revision level when setting the flags, 2444 * previously didn't change the revision level when setting the flags,
2403 * so there is a chance incompat flags are set on a rev 0 filesystem. 2445 * so there is a chance incompat flags are set on a rev 0 filesystem.
2404 */ 2446 */
2405 features = EXT4_HAS_INCOMPAT_FEATURE(sb, ~EXT4_FEATURE_INCOMPAT_SUPP); 2447 if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY)))
2406 if (features) {
2407 ext4_msg(sb, KERN_ERR,
2408 "Couldn't mount because of "
2409 "unsupported optional features (%x)",
2410 (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_incompat) &
2411 ~EXT4_FEATURE_INCOMPAT_SUPP));
2412 goto failed_mount;
2413 }
2414 features = EXT4_HAS_RO_COMPAT_FEATURE(sb, ~EXT4_FEATURE_RO_COMPAT_SUPP);
2415 if (!(sb->s_flags & MS_RDONLY) && features) {
2416 ext4_msg(sb, KERN_ERR,
2417 "Couldn't mount RDWR because of "
2418 "unsupported optional features (%x)",
2419 (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_ro_compat) &
2420 ~EXT4_FEATURE_RO_COMPAT_SUPP));
2421 goto failed_mount; 2448 goto failed_mount;
2422 } 2449
2423 has_huge_files = EXT4_HAS_RO_COMPAT_FEATURE(sb,
2424 EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
2425 if (has_huge_files) {
2426 /*
2427 * Large file size enabled file system can only be
2428 * mount if kernel is build with CONFIG_LBDAF
2429 */
2430 if (sizeof(root->i_blocks) < sizeof(u64) &&
2431 !(sb->s_flags & MS_RDONLY)) {
2432 ext4_msg(sb, KERN_ERR, "Filesystem with huge "
2433 "files cannot be mounted read-write "
2434 "without CONFIG_LBDAF");
2435 goto failed_mount;
2436 }
2437 }
2438 blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); 2450 blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
2439 2451
2440 if (blocksize < EXT4_MIN_BLOCK_SIZE || 2452 if (blocksize < EXT4_MIN_BLOCK_SIZE ||
@@ -2470,6 +2482,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
2470 } 2482 }
2471 } 2483 }
2472 2484
2485 has_huge_files = EXT4_HAS_RO_COMPAT_FEATURE(sb,
2486 EXT4_FEATURE_RO_COMPAT_HUGE_FILE);
2473 sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits, 2487 sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits,
2474 has_huge_files); 2488 has_huge_files);
2475 sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files); 2489 sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
@@ -3485,18 +3499,11 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
3485 if (sbi->s_journal) 3499 if (sbi->s_journal)
3486 ext4_mark_recovery_complete(sb, es); 3500 ext4_mark_recovery_complete(sb, es);
3487 } else { 3501 } else {
3488 int ret; 3502 /* Make sure we can mount this feature set readwrite */
3489 if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb, 3503 if (!ext4_feature_set_ok(sb, 0)) {
3490 ~EXT4_FEATURE_RO_COMPAT_SUPP))) {
3491 ext4_msg(sb, KERN_WARNING, "couldn't "
3492 "remount RDWR because of unsupported "
3493 "optional features (%x)",
3494 (le32_to_cpu(sbi->s_es->s_feature_ro_compat) &
3495 ~EXT4_FEATURE_RO_COMPAT_SUPP));
3496 err = -EROFS; 3504 err = -EROFS;
3497 goto restore_opts; 3505 goto restore_opts;
3498 } 3506 }
3499
3500 /* 3507 /*
3501 * Make sure the group descriptor checksums 3508 * Make sure the group descriptor checksums
3502 * are sane. If they aren't, refuse to remount r/w. 3509 * are sane. If they aren't, refuse to remount r/w.