Commit c5ca48aabe8b11674bf1102abe52d17ecc053f9c
1 parent
1a80a1763f
Exists in
master
and in
4 other branches
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>
Showing 3 changed files with 61 additions and 0 deletions Side-by-side Diff
fs/nilfs2/nilfs.h
... | ... | @@ -275,6 +275,8 @@ |
275 | 275 | nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); |
276 | 276 | extern int nilfs_store_magic_and_option(struct super_block *, |
277 | 277 | struct nilfs_super_block *, char *); |
278 | +extern int nilfs_check_feature_compatibility(struct super_block *, | |
279 | + struct nilfs_super_block *); | |
278 | 280 | extern void nilfs_set_log_cursor(struct nilfs_super_block *, |
279 | 281 | struct the_nilfs *); |
280 | 282 | extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, |
fs/nilfs2/super.c
... | ... | @@ -790,6 +790,30 @@ |
790 | 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 | 818 | * nilfs_fill_super() - initialize a super block instance |
795 | 819 | * @sb: super_block |
796 | 820 | |
... | ... | @@ -984,11 +1008,26 @@ |
984 | 1008 | nilfs_cleanup_super(sbi); |
985 | 1009 | up_write(&nilfs->ns_sem); |
986 | 1010 | } else { |
1011 | + __u64 features; | |
1012 | + | |
987 | 1013 | /* |
988 | 1014 | * Mounting a RDONLY partition read-write, so reread and |
989 | 1015 | * store the current valid flag. (It may have been changed |
990 | 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 | 1031 | sb->s_flags &= ~MS_RDONLY; |
993 | 1032 | |
994 | 1033 | err = nilfs_attach_segment_constructor(sbi); |
fs/nilfs2/the_nilfs.c
... | ... | @@ -385,11 +385,23 @@ |
385 | 385 | goto skip_recovery; |
386 | 386 | |
387 | 387 | if (s_flags & MS_RDONLY) { |
388 | + __u64 features; | |
389 | + | |
388 | 390 | if (nilfs_test_opt(sbi, NORECOVERY)) { |
389 | 391 | printk(KERN_INFO "NILFS: norecovery option specified. " |
390 | 392 | "skipping roll-forward recovery\n"); |
391 | 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 | 405 | if (really_read_only) { |
394 | 406 | printk(KERN_ERR "NILFS: write access " |
395 | 407 | "unavailable, cannot proceed.\n"); |
... | ... | @@ -644,6 +656,10 @@ |
644 | 656 | if (err) |
645 | 657 | goto out; |
646 | 658 | |
659 | + err = nilfs_check_feature_compatibility(sb, sbp); | |
660 | + if (err) | |
661 | + goto out; | |
662 | + | |
647 | 663 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
648 | 664 | if (sb->s_blocksize != blocksize && |
649 | 665 | !sb_set_blocksize(sb, blocksize)) { |
... | ... | @@ -666,6 +682,10 @@ |
666 | 682 | goto out; |
667 | 683 | |
668 | 684 | err = nilfs_store_magic_and_option(sb, sbp, data); |
685 | + if (err) | |
686 | + goto failed_sbh; | |
687 | + | |
688 | + err = nilfs_check_feature_compatibility(sb, sbp); | |
669 | 689 | if (err) |
670 | 690 | goto failed_sbh; |
671 | 691 |