Hi, It may be useful for users to know which ext2fs features are not supported. This patch adds more verbose messages mostly based on FreeBSD's r320578.
w/o patch: ext2fs: unsupported incompat features 0x2c2 w/ patch: ext2fs: unsupported incompat features: 64bit Index: sys/ufs/ext2fs/ext2fs.h =================================================================== RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs.h,v retrieving revision 1.23 diff -u -p -u -p -r1.23 ext2fs.h --- sys/ufs/ext2fs/ext2fs.h 27 Apr 2016 11:27:24 -0000 1.23 +++ sys/ufs/ext2fs/ext2fs.h 28 Jun 2019 05:36:15 -0000 @@ -195,15 +195,25 @@ e2fs_overflow(struct m_ext2fs *fs, off_t /* compatible/imcompatible features */ #define EXT2F_COMPAT_PREALLOC 0x0001 -#define EXT2F_COMPAT_HASJOURNAL 0x0004 +#define EXT2F_COMPAT_IMAGIC_INODES 0x0002 +#define EXT2F_COMPAT_HAS_JOURNAL 0x0004 +#define EXT2F_COMPAT_EXT_ATTR 0x0008 #define EXT2F_COMPAT_RESIZE 0x0010 -#define EXT2F_COMPAT_DIRHASHINDEX 0x0020 +#define EXT2F_COMPAT_DIR_INDEX 0x0020 +#define EXT2F_COMPAT_SPARSE_SUPER2 0x0200 - -#define EXT2F_ROCOMPAT_SPARSESUPER 0x0001 -#define EXT2F_ROCOMPAT_LARGEFILE 0x0002 +#define EXT2F_ROCOMPAT_SPARSE_SUPER 0x0001 +#define EXT2F_ROCOMPAT_LARGE_FILE 0x0002 #define EXT2F_ROCOMPAT_BTREE_DIR 0x0004 #define EXT2F_ROCOMPAT_HUGE_FILE 0x0008 +#define EXT2F_ROCOMPAT_GDT_CSUM 0x0010 +#define EXT2F_ROCOMPAT_DIR_NLINK 0x0020 +#define EXT2F_ROCOMPAT_EXTRA_ISIZE 0x0040 +#define EXT2F_ROCOMPAT_QUOTA 0x0100 +#define EXT2F_ROCOMPAT_BIGALLOC 0x0200 +#define EXT2F_ROCOMPAT_METADATA_CKSUM 0x0400 +#define EXT2F_ROCOMPAT_READONLY 0x1000 +#define EXT2F_ROCOMPAT_PROJECT 0x2000 #define EXT2F_INCOMPAT_COMP 0x0001 #define EXT2F_INCOMPAT_FTYPE 0x0002 @@ -211,12 +221,58 @@ e2fs_overflow(struct m_ext2fs *fs, off_t #define EXT2F_INCOMPAT_JOURNAL_DEV 0x0008 #define EXT2F_INCOMPAT_META_BG 0x0010 #define EXT2F_INCOMPAT_EXTENTS 0x0040 +#define EXT2F_INCOMPAT_64BIT 0x0080 +#define EXT2F_INCOMPAT_MMP 0x0100 #define EXT2F_INCOMPAT_FLEX_BG 0x0200 +#define EXT2F_INCOMPAT_EA_INODE 0x0400 +#define EXT2F_INCOMPAT_DIRDATA 0x1000 +#define EXT2F_INCOMPAT_CSUM_SEED 0x2000 +#define EXT2F_INCOMPAT_LARGEDIR 0x4000 +#define EXT2F_INCOMPAT_INLINE_DATA 0x8000 +#define EXT2F_INCOMPAT_ENCRYPT 0x10000 + +struct ext2_feature { + uint32_t mask; + const char *name; +}; + +static const struct ext2_feature ro_compat[] = { + { EXT2F_ROCOMPAT_SPARSE_SUPER, "sparse_super" }, + { EXT2F_ROCOMPAT_LARGE_FILE, "large_file" }, + { EXT2F_ROCOMPAT_BTREE_DIR, "btree_dir" }, + { EXT2F_ROCOMPAT_HUGE_FILE, "huge_file" }, + { EXT2F_ROCOMPAT_GDT_CSUM, "uninit_bg" }, + { EXT2F_ROCOMPAT_DIR_NLINK, "dir_nlink" }, + { EXT2F_ROCOMPAT_EXTRA_ISIZE, "extra_isize" }, + { EXT2F_ROCOMPAT_QUOTA, "quota" }, + { EXT2F_ROCOMPAT_BIGALLOC, "bigalloc" }, + { EXT2F_ROCOMPAT_METADATA_CKSUM, "metadata_csum" }, + { EXT2F_ROCOMPAT_READONLY, "read-only" }, + { EXT2F_ROCOMPAT_PROJECT, "project" } +}; + +static const struct ext2_feature incompat[] = { + { EXT2F_INCOMPAT_COMP, "compression" }, + { EXT2F_INCOMPAT_FTYPE, "filetype" }, + { EXT2F_INCOMPAT_RECOVER, "needs_recovery" }, + { EXT2F_INCOMPAT_JOURNAL_DEV, "journal_dev" }, + { EXT2F_INCOMPAT_META_BG, "meta_bg" }, + { EXT2F_INCOMPAT_EXTENTS, "extents" }, + { EXT2F_INCOMPAT_64BIT, "64bit" }, + { EXT2F_INCOMPAT_MMP, "mmp" }, + { EXT2F_INCOMPAT_FLEX_BG, "flex_bg" }, + { EXT2F_INCOMPAT_EA_INODE, "ea_inode" }, + { EXT2F_INCOMPAT_DIRDATA, "dirdata" }, + { EXT2F_INCOMPAT_CSUM_SEED, "metadata_csum_seed" }, + { EXT2F_INCOMPAT_LARGEDIR, "large_dir" }, + { EXT2F_INCOMPAT_INLINE_DATA, "inline_data" }, + { EXT2F_INCOMPAT_ENCRYPT, "encrypt" } +}; /* features supported in this implementation */ #define EXT2F_COMPAT_SUPP 0x0000 -#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSESUPER | \ - EXT2F_ROCOMPAT_LARGEFILE) +#define EXT2F_ROCOMPAT_SUPP (EXT2F_ROCOMPAT_SPARSE_SUPER | \ + EXT2F_ROCOMPAT_LARGE_FILE) #define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE) #define EXT4F_RO_INCOMPAT_SUPP (EXT2F_INCOMPAT_EXTENTS | \ EXT2F_INCOMPAT_FLEX_BG | \ @@ -258,7 +314,7 @@ struct ext2_gd { }; /* - * If the EXT2F_ROCOMPAT_SPARSESUPER flag is set, the cylinder group has a + * If the EXT2F_ROCOMPAT_SPARSE_SUPER flag is set, the cylinder group has a * copy of the super and cylinder group descriptors blocks only if it's * a power of 3, 5 or 7 */ Index: sys/ufs/ext2fs/ext2fs_inode.c =================================================================== RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_inode.c,v retrieving revision 1.59 diff -u -p -u -p -r1.59 ext2fs_inode.c --- sys/ufs/ext2fs/ext2fs_inode.c 28 Apr 2018 03:13:05 -0000 1.59 +++ sys/ufs/ext2fs/ext2fs_inode.c 28 Jun 2019 05:36:15 -0000 @@ -87,8 +87,8 @@ ext2fs_setsize(struct inode *ip, u_int64 if (fs->e2fs.e2fs_rev <= E2FS_REV0) return (EFBIG); - if ((fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE) == 0) { - fs->e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_LARGEFILE; + if (!(fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGE_FILE)) { + fs->e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_LARGE_FILE; fs->e2fs_fmod = 1; } return (EFBIG); Index: sys/ufs/ext2fs/ext2fs_vfsops.c =================================================================== RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v retrieving revision 1.110 diff -u -p -u -p -r1.110 ext2fs_vfsops.c --- sys/ufs/ext2fs/ext2fs_vfsops.c 26 Sep 2018 14:51:44 -0000 1.110 +++ sys/ufs/ext2fs/ext2fs_vfsops.c 28 Jun 2019 05:36:15 -0000 @@ -400,7 +400,7 @@ e2fs_sbfill(struct vnode *devvp, struct bp = NULL; } - if ((fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE) == 0 || + if (!(fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGE_FILE) || (fs->e2fs.e2fs_rev == E2FS_REV0)) fs->e2fs_maxfilesize = INT_MAX; else @@ -674,7 +674,7 @@ ext2fs_statfs(struct mount *mp, struct s overhead = fs->e2fs.e2fs_first_dblock + fs->e2fs_ncg * overhead_per_group; if (fs->e2fs.e2fs_rev > E2FS_REV0 && - fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) { + fs->e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSE_SUPER) { for (i = 0, ngroups = 0; i < fs->e2fs_ncg; i++) { if (cg_has_sb(i)) ngroups++; @@ -1072,7 +1072,8 @@ ext2fs_cgupdate(struct ufsmount *mp, int static int e2fs_sbcheck(struct ext2fs *fs, int ronly) { - u_int32_t tmp; + u_int32_t mask, tmp; + int i; tmp = letoh16(fs->e2fs_magic); if (tmp != E2FS_MAGIC) { @@ -1108,8 +1109,13 @@ e2fs_sbcheck(struct ext2fs *fs, int ronl } tmp = letoh32(fs->e2fs_features_incompat); - if (tmp & ~(EXT2F_INCOMPAT_SUPP | EXT4F_RO_INCOMPAT_SUPP)) { - printf("ext2fs: unsupported incompat features 0x%x\n", tmp); + mask = tmp & ~(EXT2F_INCOMPAT_SUPP | EXT4F_RO_INCOMPAT_SUPP); + if (mask) { + printf("ext2fs: unsupported incompat features: "); + for (i = 0; i < nitems(incompat); i++) + if (mask & incompat[i].mask) + printf("%s ", incompat[i].name); + printf("\n"); return (EINVAL); /* XXX needs translation */ } @@ -1124,9 +1130,13 @@ e2fs_sbcheck(struct ext2fs *fs, int ronl return (EROFS); /* XXX needs translation */ } - tmp = letoh32(fs->e2fs_features_rocompat); - if (!ronly && (tmp & ~EXT2F_ROCOMPAT_SUPP)) { - printf("ext2fs: unsupported R/O compat features 0x%x\n", tmp); + tmp = letoh32(fs->e2fs_features_rocompat) & ~EXT2F_ROCOMPAT_SUPP; + if (!ronly && tmp) { + printf("ext2fs: unsupported R/O compat features: "); + for (i = 0; i < nitems(ro_compat); i++) + if (tmp & ro_compat[i].mask) + printf("%s ", ro_compat[i].name); + printf("\n"); return (EROFS); /* XXX needs translation */ }