diff options
| -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); |
