diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-07-21 14:22:20 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-07-22 21:02:16 -0400 |
commit | c5ca48aabe8b11674bf1102abe52d17ecc053f9c (patch) | |
tree | 18c7647b42981d457c59cd4a842ca342a239770d /fs | |
parent | 1a80a1763fb760b3a84a28df87515f7cdc07a4f4 (diff) |
nilfs2: reject incompatible filesystem
This forces nilfs to check compatibility of feature flags so as to
reject a filesystem with unknown features when it mounts or remounts
the filesystem.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nilfs2/nilfs.h | 2 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 39 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 20 |
3 files changed, 61 insertions, 0 deletions
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index cfedc48d78d9..0842d775b3e0 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
@@ -275,6 +275,8 @@ extern struct nilfs_super_block * | |||
275 | nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); | 275 | nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); |
276 | extern int nilfs_store_magic_and_option(struct super_block *, | 276 | extern int nilfs_store_magic_and_option(struct super_block *, |
277 | struct nilfs_super_block *, char *); | 277 | struct nilfs_super_block *, char *); |
278 | extern int nilfs_check_feature_compatibility(struct super_block *, | ||
279 | struct nilfs_super_block *); | ||
278 | extern void nilfs_set_log_cursor(struct nilfs_super_block *, | 280 | extern void nilfs_set_log_cursor(struct nilfs_super_block *, |
279 | struct the_nilfs *); | 281 | struct the_nilfs *); |
280 | extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, | 282 | extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 164457316df1..26078b3407c9 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -790,6 +790,30 @@ int nilfs_store_magic_and_option(struct super_block *sb, | |||
790 | return !parse_options(data, sb, 0) ? -EINVAL : 0 ; | 790 | return !parse_options(data, sb, 0) ? -EINVAL : 0 ; |
791 | } | 791 | } |
792 | 792 | ||
793 | int nilfs_check_feature_compatibility(struct super_block *sb, | ||
794 | struct nilfs_super_block *sbp) | ||
795 | { | ||
796 | __u64 features; | ||
797 | |||
798 | features = le64_to_cpu(sbp->s_feature_incompat) & | ||
799 | ~NILFS_FEATURE_INCOMPAT_SUPP; | ||
800 | if (features) { | ||
801 | printk(KERN_ERR "NILFS: couldn't mount because of unsupported " | ||
802 | "optional features (%llx)\n", | ||
803 | (unsigned long long)features); | ||
804 | return -EINVAL; | ||
805 | } | ||
806 | features = le64_to_cpu(sbp->s_feature_compat_ro) & | ||
807 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
808 | if (!(sb->s_flags & MS_RDONLY) && features) { | ||
809 | printk(KERN_ERR "NILFS: couldn't mount RDWR because of " | ||
810 | "unsupported optional features (%llx)\n", | ||
811 | (unsigned long long)features); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | return 0; | ||
815 | } | ||
816 | |||
793 | /** | 817 | /** |
794 | * nilfs_fill_super() - initialize a super block instance | 818 | * nilfs_fill_super() - initialize a super block instance |
795 | * @sb: super_block | 819 | * @sb: super_block |
@@ -984,11 +1008,26 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
984 | nilfs_cleanup_super(sbi); | 1008 | nilfs_cleanup_super(sbi); |
985 | up_write(&nilfs->ns_sem); | 1009 | up_write(&nilfs->ns_sem); |
986 | } else { | 1010 | } else { |
1011 | __u64 features; | ||
1012 | |||
987 | /* | 1013 | /* |
988 | * Mounting a RDONLY partition read-write, so reread and | 1014 | * Mounting a RDONLY partition read-write, so reread and |
989 | * store the current valid flag. (It may have been changed | 1015 | * store the current valid flag. (It may have been changed |
990 | * by fsck since we originally mounted the partition.) | 1016 | * by fsck since we originally mounted the partition.) |
991 | */ | 1017 | */ |
1018 | down_read(&nilfs->ns_sem); | ||
1019 | features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & | ||
1020 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
1021 | up_read(&nilfs->ns_sem); | ||
1022 | if (features) { | ||
1023 | printk(KERN_WARNING "NILFS (device %s): couldn't " | ||
1024 | "remount RDWR because of unsupported optional " | ||
1025 | "features (%llx)\n", | ||
1026 | sb->s_id, (unsigned long long)features); | ||
1027 | err = -EROFS; | ||
1028 | goto restore_opts; | ||
1029 | } | ||
1030 | |||
992 | sb->s_flags &= ~MS_RDONLY; | 1031 | sb->s_flags &= ~MS_RDONLY; |
993 | 1032 | ||
994 | err = nilfs_attach_segment_constructor(sbi); | 1033 | err = nilfs_attach_segment_constructor(sbi); |
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index f2efc8c5be7f..da67b560f3c3 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -385,11 +385,23 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
385 | goto skip_recovery; | 385 | goto skip_recovery; |
386 | 386 | ||
387 | if (s_flags & MS_RDONLY) { | 387 | if (s_flags & MS_RDONLY) { |
388 | __u64 features; | ||
389 | |||
388 | if (nilfs_test_opt(sbi, NORECOVERY)) { | 390 | if (nilfs_test_opt(sbi, NORECOVERY)) { |
389 | printk(KERN_INFO "NILFS: norecovery option specified. " | 391 | printk(KERN_INFO "NILFS: norecovery option specified. " |
390 | "skipping roll-forward recovery\n"); | 392 | "skipping roll-forward recovery\n"); |
391 | goto skip_recovery; | 393 | goto skip_recovery; |
392 | } | 394 | } |
395 | features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & | ||
396 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
397 | if (features) { | ||
398 | printk(KERN_ERR "NILFS: couldn't proceed with " | ||
399 | "recovery because of unsupported optional " | ||
400 | "features (%llx)\n", | ||
401 | (unsigned long long)features); | ||
402 | err = -EROFS; | ||
403 | goto failed_unload; | ||
404 | } | ||
393 | if (really_read_only) { | 405 | if (really_read_only) { |
394 | printk(KERN_ERR "NILFS: write access " | 406 | printk(KERN_ERR "NILFS: write access " |
395 | "unavailable, cannot proceed.\n"); | 407 | "unavailable, cannot proceed.\n"); |
@@ -644,6 +656,10 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
644 | if (err) | 656 | if (err) |
645 | goto out; | 657 | goto out; |
646 | 658 | ||
659 | err = nilfs_check_feature_compatibility(sb, sbp); | ||
660 | if (err) | ||
661 | goto out; | ||
662 | |||
647 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); | 663 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
648 | if (sb->s_blocksize != blocksize && | 664 | if (sb->s_blocksize != blocksize && |
649 | !sb_set_blocksize(sb, blocksize)) { | 665 | !sb_set_blocksize(sb, blocksize)) { |
@@ -669,6 +685,10 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
669 | if (err) | 685 | if (err) |
670 | goto failed_sbh; | 686 | goto failed_sbh; |
671 | 687 | ||
688 | err = nilfs_check_feature_compatibility(sb, sbp); | ||
689 | if (err) | ||
690 | goto failed_sbh; | ||
691 | |||
672 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); | 692 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
673 | if (sb->s_blocksize != blocksize) { | 693 | if (sb->s_blocksize != blocksize) { |
674 | int hw_blocksize = bdev_logical_block_size(sb->s_bdev); | 694 | int hw_blocksize = bdev_logical_block_size(sb->s_bdev); |