Commit c5ca48aabe8b11674bf1102abe52d17ecc053f9c

Authored by Ryusuke Konishi
1 parent 1a80a1763f

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

... ... @@ -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 *,
... ... @@ -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