nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **);
 extern int nilfs_store_magic_and_option(struct super_block *,
                                        struct nilfs_super_block *, char *);
+extern int nilfs_check_feature_compatibility(struct super_block *,
+                                            struct nilfs_super_block *);
 extern void nilfs_set_log_cursor(struct nilfs_super_block *,
                                 struct the_nilfs *);
 extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *,
 
        return !parse_options(data, sb, 0) ? -EINVAL : 0 ;
 }
 
+int nilfs_check_feature_compatibility(struct super_block *sb,
+                                     struct nilfs_super_block *sbp)
+{
+       __u64 features;
+
+       features = le64_to_cpu(sbp->s_feature_incompat) &
+               ~NILFS_FEATURE_INCOMPAT_SUPP;
+       if (features) {
+               printk(KERN_ERR "NILFS: couldn't mount because of unsupported "
+                      "optional features (%llx)\n",
+                      (unsigned long long)features);
+               return -EINVAL;
+       }
+       features = le64_to_cpu(sbp->s_feature_compat_ro) &
+               ~NILFS_FEATURE_COMPAT_RO_SUPP;
+       if (!(sb->s_flags & MS_RDONLY) && features) {
+               printk(KERN_ERR "NILFS: couldn't mount RDWR because of "
+                      "unsupported optional features (%llx)\n",
+                      (unsigned long long)features);
+               return -EINVAL;
+       }
+       return 0;
+}
+
 /**
  * nilfs_fill_super() - initialize a super block instance
  * @sb: super_block
                nilfs_cleanup_super(sbi);
                up_write(&nilfs->ns_sem);
        } else {
+               __u64 features;
+
                /*
                 * Mounting a RDONLY partition read-write, so reread and
                 * store the current valid flag.  (It may have been changed
                 * by fsck since we originally mounted the partition.)
                 */
+               down_read(&nilfs->ns_sem);
+               features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) &
+                       ~NILFS_FEATURE_COMPAT_RO_SUPP;
+               up_read(&nilfs->ns_sem);
+               if (features) {
+                       printk(KERN_WARNING "NILFS (device %s): couldn't "
+                              "remount RDWR because of unsupported optional "
+                              "features (%llx)\n",
+                              sb->s_id, (unsigned long long)features);
+                       err = -EROFS;
+                       goto restore_opts;
+               }
+
                sb->s_flags &= ~MS_RDONLY;
 
                err = nilfs_attach_segment_constructor(sbi);
 
                goto skip_recovery;
 
        if (s_flags & MS_RDONLY) {
+               __u64 features;
+
                if (nilfs_test_opt(sbi, NORECOVERY)) {
                        printk(KERN_INFO "NILFS: norecovery option specified. "
                               "skipping roll-forward recovery\n");
                        goto skip_recovery;
                }
+               features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) &
+                       ~NILFS_FEATURE_COMPAT_RO_SUPP;
+               if (features) {
+                       printk(KERN_ERR "NILFS: couldn't proceed with "
+                              "recovery because of unsupported optional "
+                              "features (%llx)\n",
+                              (unsigned long long)features);
+                       err = -EROFS;
+                       goto failed_unload;
+               }
                if (really_read_only) {
                        printk(KERN_ERR "NILFS: write access "
                               "unavailable, cannot proceed.\n");
                if (err)
                        goto out;
 
+               err = nilfs_check_feature_compatibility(sb, sbp);
+               if (err)
+                       goto out;
+
                blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size);
                if (sb->s_blocksize != blocksize &&
                    !sb_set_blocksize(sb, blocksize)) {
        if (err)
                goto failed_sbh;
 
+       err = nilfs_check_feature_compatibility(sb, sbp);
+       if (err)
+               goto failed_sbh;
+
        blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size);
        if (sb->s_blocksize != blocksize) {
                int hw_blocksize = bdev_logical_block_size(sb->s_bdev);