Module Name:    src
Committed By:   jdolecek
Date:           Wed Aug  3 21:53:03 UTC 2016

Modified Files:
        src/sys/ufs/ext2fs: ext2fs.h ext2fs_alloc.c ext2fs_bswap.c
            ext2fs_dinode.h ext2fs_inode.c ext2fs_vfsops.c ext2fs_vnops.c

Log Message:
support arbitrary ext3/ext4 inode size, add all the new ext4 fields 
ext2fs_dinode, and add support for loading the extra inode data


To generate a diff of this commit:
cvs rdiff -u -r1.38 -r1.39 src/sys/ufs/ext2fs/ext2fs.h
cvs rdiff -u -r1.46 -r1.47 src/sys/ufs/ext2fs/ext2fs_alloc.c
cvs rdiff -u -r1.20 -r1.21 src/sys/ufs/ext2fs/ext2fs_bswap.c
cvs rdiff -u -r1.27 -r1.28 src/sys/ufs/ext2fs/ext2fs_dinode.h
cvs rdiff -u -r1.82 -r1.83 src/sys/ufs/ext2fs/ext2fs_inode.c
cvs rdiff -u -r1.193 -r1.194 src/sys/ufs/ext2fs/ext2fs_vfsops.c
cvs rdiff -u -r1.117 -r1.118 src/sys/ufs/ext2fs/ext2fs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/ext2fs/ext2fs.h
diff -u src/sys/ufs/ext2fs/ext2fs.h:1.38 src/sys/ufs/ext2fs/ext2fs.h:1.39
--- src/sys/ufs/ext2fs/ext2fs.h:1.38	Fri Jun 24 17:21:30 2016
+++ src/sys/ufs/ext2fs/ext2fs.h	Wed Aug  3 21:53:02 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs.h,v 1.38 2016/06/24 17:21:30 christos Exp $	*/
+/*	$NetBSD: ext2fs.h,v 1.39 2016/08/03 21:53:02 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -327,7 +327,8 @@ struct m_ext2fs {
 #define EXT2F_COMPAT_SUPP		0x0000
 #define EXT2F_ROCOMPAT_SUPP		(EXT2F_ROCOMPAT_SPARSESUPER \
 					 | EXT2F_ROCOMPAT_LARGEFILE \
-					 | EXT2F_ROCOMPAT_HUGE_FILE)
+					 | EXT2F_ROCOMPAT_HUGE_FILE \
+					 | EXT2F_ROCOMPAT_EXTRA_ISIZE)
 #define EXT2F_INCOMPAT_SUPP		(EXT2F_INCOMPAT_FTYPE \
 					 | EXT2F_INCOMPAT_EXTENTS)
 

Index: src/sys/ufs/ext2fs/ext2fs_alloc.c
diff -u src/sys/ufs/ext2fs/ext2fs_alloc.c:1.46 src/sys/ufs/ext2fs/ext2fs_alloc.c:1.47
--- src/sys/ufs/ext2fs/ext2fs_alloc.c:1.46	Sat Mar 28 19:24:04 2015
+++ src/sys/ufs/ext2fs/ext2fs_alloc.c	Wed Aug  3 21:53:02 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_alloc.c,v 1.46 2015/03/28 19:24:04 maxv Exp $	*/
+/*	$NetBSD: ext2fs_alloc.c,v 1.47 2016/08/03 21:53:02 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.46 2015/03/28 19:24:04 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.47 2016/08/03 21:53:02 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -198,7 +198,7 @@ ext2fs_valloc(struct vnode *pvp, int mod
 		panic("ext2fs_valloc: dup alloc");
 	}
 
-	memset(ip->i_din.e2fs_din, 0, sizeof(struct ext2fs_dinode));
+	memset(ip->i_din.e2fs_din, 0, EXT2_DINODE_SIZE(fs));
 
 	/*
 	 * Set up a new generation number for this inode.

Index: src/sys/ufs/ext2fs/ext2fs_bswap.c
diff -u src/sys/ufs/ext2fs/ext2fs_bswap.c:1.20 src/sys/ufs/ext2fs/ext2fs_bswap.c:1.21
--- src/sys/ufs/ext2fs/ext2fs_bswap.c:1.20	Tue Aug  2 17:24:24 2016
+++ src/sys/ufs/ext2fs/ext2fs_bswap.c	Wed Aug  3 21:53:02 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_bswap.c,v 1.20 2016/08/02 17:24:24 jdolecek Exp $	*/
+/*	$NetBSD: ext2fs_bswap.c,v 1.21 2016/08/03 21:53:02 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1997 Manuel Bouyer.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_bswap.c,v 1.20 2016/08/02 17:24:24 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_bswap.c,v 1.21 2016/08/03 21:53:02 jdolecek Exp $");
 
 #include <sys/types.h>
 #include <ufs/ext2fs/ext2fs.h>
@@ -81,7 +81,8 @@ e2fs_sb_bswap(struct ext2fs *old, struct
 	new->e2fs_reserved_ngdb	=	bswap16(old->e2fs_reserved_ngdb);
 }
 
-void e2fs_cg_bswap(struct ext2_gd *old, struct ext2_gd *new, int size)
+void
+e2fs_cg_bswap(struct ext2_gd *old, struct ext2_gd *new, int size)
 {
 	int i;
 
@@ -95,9 +96,13 @@ void e2fs_cg_bswap(struct ext2_gd *old, 
 	}
 }
 
-void e2fs_i_bswap(struct ext2fs_dinode *old, struct ext2fs_dinode *new)
+void
+e2fs_i_bswap(struct ext2fs_dinode *old, struct ext2fs_dinode *new, size_t isize)
 {
+	/* preserve non-swapped and unused fields */ 
+	memcpy(new, old, isize);
 
+	/* swap what needs to be swapped */
 	new->e2di_mode		=	bswap16(old->e2di_mode);
 	new->e2di_uid		=	bswap16(old->e2di_uid);
 	new->e2di_gid		=	bswap16(old->e2di_gid);
@@ -117,7 +122,32 @@ void e2fs_i_bswap(struct ext2fs_dinode *
 	new->e2di_facl_high	=	bswap16(old->e2di_facl_high);
 	new->e2di_uid_high	=	bswap16(old->e2di_uid_high);
 	new->e2di_gid_high	=	bswap16(old->e2di_gid_high);
-	memcpy(&new->e2di_blocks[0], &old->e2di_blocks[0],
-	    (EXT2FS_NDADDR + EXT2FS_NIADDR) * sizeof(uint32_t));
+	new->e2di_checksum_low  = 	bswap16(old->e2di_checksum_low);
+
+	/*
+	 * Following fields are only supported for inode sizes bigger
+	 * than the old ext2 one
+	 */
+	if (isize == EXT2_REV0_DINODE_SIZE)
+		return;
+
+	new->e2di_extra_isize   = bswap16(old->e2di_extra_isize);
+	new->e2di_checksum_high = bswap16(old->e2di_checksum_high);
+
+	/* Following fields are ext4, might not be actually present */
+	if (EXT2_DINODE_FITS(new, e2di_ctime_extra, isize))
+		new->e2di_ctime_extra   = bswap32(old->e2di_ctime_extra);
+	if (EXT2_DINODE_FITS(new, e2di_mtime_extra, isize))
+		new->e2di_mtime_extra	= bswap32(old->e2di_mtime_extra);
+	if (EXT2_DINODE_FITS(new, e2di_atime_extra, isize))
+		new->e2di_atime_extra	= bswap32(old->e2di_atime_extra);
+	if (EXT2_DINODE_FITS(new, e2di_crtime, isize))
+		new->e2di_crtime	= bswap32(old->e2di_crtime);
+	if (EXT2_DINODE_FITS(new, e2di_crtime_extra, isize))
+		new->e2di_crtime_extra	= bswap32(old->e2di_crtime_extra);
+	if (EXT2_DINODE_FITS(new, e2di_version_high, isize))
+		new->e2di_version_high	= bswap32(old->e2di_version_high);
+	if (EXT2_DINODE_FITS(new, e2di_projid, isize))
+		new->e2di_projid	= bswap32(old->e2di_projid);
 }
 #endif

Index: src/sys/ufs/ext2fs/ext2fs_dinode.h
diff -u src/sys/ufs/ext2fs/ext2fs_dinode.h:1.27 src/sys/ufs/ext2fs/ext2fs_dinode.h:1.28
--- src/sys/ufs/ext2fs/ext2fs_dinode.h:1.27	Tue Aug  2 17:36:02 2016
+++ src/sys/ufs/ext2fs/ext2fs_dinode.h	Wed Aug  3 21:53:02 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_dinode.h,v 1.27 2016/08/02 17:36:02 jdolecek Exp $	*/
+/*	$NetBSD: ext2fs_dinode.h,v 1.28 2016/08/03 21:53:02 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1982, 1989, 1993
@@ -125,11 +125,19 @@ struct ext2fs_dinode {
 	uint16_t	e2di_facl_high; /* 118: file ACL bits 47:32 (ext4) */
 	uint16_t	e2di_uid_high;	/* 120: Owner UID top 16 bits (ext4) */
 	uint16_t	e2di_gid_high;	/* 122: Owner GID top 16 bits (ext4) */
-	uint16_t	e2di_extra_isize; /* 124: inode extra size (over 128) actually used (ext4) */
-	uint16_t	e2di_checksum_high; /* 126: crc (not implemented) (ext4) */
+	uint16_t 	e2di_checksum_low;  /* 124: crc LE (not implemented) (ext4) */
+	uint16_t 	e2di_reserved;      /* 126: reserved */
+	uint16_t	e2di_extra_isize;   /* 128: inode extra size (over 128) actually used (ext4) */
+	uint16_t	e2di_checksum_high; /* 130: crc BE (not implemented) (ext4) */
+	uint32_t	e2di_ctime_extra;   /* 132: ctime (nsec << 2 | high epoch) (ext4) */
+	uint32_t	e2di_mtime_extra;   /* 136: mtime (nsec << 2 | high epoch) (ext4) */
+	uint32_t	e2di_atime_extra;   /* 140: atime (nsec << 2 | high epoch) (ext4) */
+	uint32_t	e2di_crtime;        /* 144: creation time (epoch) (ext4) */
+	uint32_t	e2di_crtime_extra;  /* 148: creation time (nsec << 2 | high epoch) (ext4) */
+	uint32_t	e2di_version_high;  /* 152: version high (ext4) */
+	uint32_t	e2di_projid;        /* 156: project id (not implemented) (ext4) */
 };
 
-
 /* XXX how does this differ from EXT2_MAXSYMLINKLEN above? */
 #define	E2MAXSYMLINKLEN	((EXT2FS_NDADDR + EXT2FS_NIADDR) * sizeof(uint32_t))
 
@@ -171,10 +179,14 @@ struct ext2fs_dinode {
 #define EXT2_EOFBLOCKS		0x00400000 /* Blocks allocated beyond EOF */
 
 /* Size of on-disk inode. */
-#define EXT2_REV0_DINODE_SIZE	sizeof(struct ext2fs_dinode)
+#define EXT2_REV0_DINODE_SIZE	128
 #define EXT2_DINODE_SIZE(fs)	((fs)->e2fs.e2fs_rev > E2FS_REV0 ?	\
 				    (fs)->e2fs.e2fs_inode_size :	\
 				    EXT2_REV0_DINODE_SIZE)
+#define EXT2_DINODE_FITS(dinode, field, isize) (\
+	(isize > EXT2_REV0_DINODE_SIZE) \
+	&& ((EXT2_REV0_DINODE_SIZE + (dinode)->e2di_extra_isize)  >= offsetof(struct ext2fs_dinode, field) + sizeof((dinode)->field)) \
+	)
 
 /*
  * The e2di_blocks fields may be overlaid with other information for
@@ -189,14 +201,14 @@ struct ext2fs_dinode {
 
 /* e2fs needs byte swapping on big-endian systems */
 #if BYTE_ORDER == LITTLE_ENDIAN
-#	define e2fs_iload(old, new)	\
-		memcpy((new),(old),sizeof(struct ext2fs_dinode))
-#	define e2fs_isave(old, new)	\
-		memcpy((new),(old),sizeof(struct ext2fs_dinode))
+#	define e2fs_iload(old, new, isize)	\
+		memcpy((new),(old),(isize))
+#	define e2fs_isave(old, new, isize)	\
+		memcpy((new),(old),(isize))
 #else
-void e2fs_i_bswap(struct ext2fs_dinode *, struct ext2fs_dinode *);
-#	define e2fs_iload(old, new) e2fs_i_bswap((old), (new))
-#	define e2fs_isave(old, new) e2fs_i_bswap((old), (new))
+void e2fs_i_bswap(struct ext2fs_dinode *, struct ext2fs_dinode *, size_t);
+#	define e2fs_iload(old, new, isize) e2fs_i_bswap((old), (new))
+#	define e2fs_isave(old, new, isize) e2fs_i_bswap((old), (new))
 #endif
 
 #endif /* !_UFS_EXT2FS_EXT2FS_DINODE_H_ */

Index: src/sys/ufs/ext2fs/ext2fs_inode.c
diff -u src/sys/ufs/ext2fs/ext2fs_inode.c:1.82 src/sys/ufs/ext2fs/ext2fs_inode.c:1.83
--- src/sys/ufs/ext2fs/ext2fs_inode.c:1.82	Sat Mar 28 19:24:04 2015
+++ src/sys/ufs/ext2fs/ext2fs_inode.c	Wed Aug  3 21:53:02 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_inode.c,v 1.82 2015/03/28 19:24:04 maxv Exp $	*/
+/*	$NetBSD: ext2fs_inode.c,v 1.83 2016/08/03 21:53:02 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.82 2015/03/28 19:24:04 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_inode.c,v 1.83 2016/08/03 21:53:02 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -269,7 +269,7 @@ ext2fs_update(struct vnode *vp, const st
 	ip->i_flag &= ~(IN_MODIFIED | IN_ACCESSED);
 	cp = (char *)bp->b_data +
 	    (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE(fs));
-	e2fs_isave(ip->i_din.e2fs_din, (struct ext2fs_dinode *)cp);
+	e2fs_isave(ip->i_din.e2fs_din, (struct ext2fs_dinode *)cp, EXT2_DINODE_SIZE(fs));
 	if ((updflags & (UPDATE_WAIT|UPDATE_DIROP)) != 0 &&
 	    (flags & IN_MODIFIED) != 0 &&
 	    (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)

Index: src/sys/ufs/ext2fs/ext2fs_vfsops.c
diff -u src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.193 src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.194
--- src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.193	Sat Mar 28 19:24:04 2015
+++ src/sys/ufs/ext2fs/ext2fs_vfsops.c	Wed Aug  3 21:53:02 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_vfsops.c,v 1.193 2015/03/28 19:24:04 maxv Exp $	*/
+/*	$NetBSD: ext2fs_vfsops.c,v 1.194 2016/08/03 21:53:02 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1989, 1991, 1993, 1994
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.193 2015/03/28 19:24:04 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.194 2016/08/03 21:53:02 jdolecek Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -213,7 +213,6 @@ ext2fs_modcmd(modcmd_t cmd, void *arg)
  * XXX Same structure as FFS inodes?  Should we share a common pool?
  */
 struct pool ext2fs_inode_pool;
-struct pool ext2fs_dinode_pool;
 
 extern u_long ext2gennumber;
 
@@ -223,8 +222,6 @@ ext2fs_init(void)
 
 	pool_init(&ext2fs_inode_pool, sizeof(struct inode), 0, 0, 0,
 	    "ext2fsinopl", &pool_allocator_nointr, IPL_NONE);
-	pool_init(&ext2fs_dinode_pool, sizeof(struct ext2fs_dinode), 0, 0, 0,
-	    "ext2dinopl", &pool_allocator_nointr, IPL_NONE);
 	ufs_init();
 }
 
@@ -240,7 +237,6 @@ ext2fs_done(void)
 
 	ufs_done();
 	pool_destroy(&ext2fs_inode_pool);
-	pool_destroy(&ext2fs_dinode_pool);
 }
 
 /*
@@ -497,6 +493,43 @@ fail:
 }
 
 /*
+ *
+ */
+static int
+ext2fs_loadvnode_content(struct m_ext2fs *fs, ino_t ino, struct buf *bp, struct inode *ip)
+{
+	struct ext2fs_dinode *din;
+	void *cp;
+	int error = 0;
+
+	cp = (char *)bp->b_data + (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE(fs));
+	din = kmem_alloc(EXT2_DINODE_SIZE(fs), KM_SLEEP);
+	e2fs_iload((struct ext2fs_dinode *)cp, din, EXT2_DINODE_SIZE(fs));
+
+	/* sanity checks */
+	if (EXT2_DINODE_FITS(din, e2di_extra_isize, EXT2_DINODE_SIZE(fs))
+	    && (EXT2_DINODE_SIZE(fs) - EXT2_REV0_DINODE_SIZE) < din->e2di_extra_isize)
+	{
+		printf("ext2fs: inode %llu bad extra_isize %u",
+			ino, din->e2di_extra_isize);
+		error = EINVAL;
+		goto bad;
+	}
+
+	/* replace old dinode; assumes new dinode size is same as old one */
+	if (ip->i_din.e2fs_din)
+		kmem_free(ip->i_din.e2fs_din, EXT2_DINODE_SIZE(fs));
+	ip->i_din.e2fs_din = din;
+
+	ext2fs_set_inode_guid(ip);
+	return (error);
+
+    bad:
+	kmem_free(din, EXT2_DINODE_SIZE(fs));
+	return (error);
+}
+
+/*
  * Reload all incore data for a filesystem (used after running fsck on
  * the root filesystem and finding things to fix). The filesystem must
  * be mounted read-only.
@@ -518,7 +551,6 @@ ext2fs_reload(struct mount *mp, kauth_cr
 	struct m_ext2fs *fs;
 	struct ext2fs *newfs;
 	int i, error;
-	void *cp;
 	struct ufsmount *ump;
 	struct vnode_iterator *marker;
 
@@ -596,11 +628,13 @@ ext2fs_reload(struct mount *mp, kauth_cr
 			vput(vp);
 			break;
 		}
-		cp = (char *)bp->b_data +
-		    (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE(fs));
-		e2fs_iload((struct ext2fs_dinode *)cp, ip->i_din.e2fs_din);
-		ext2fs_set_inode_guid(ip);
+		error = ext2fs_loadvnode_content(fs, ip->i_number, bp, ip);
 		brelse(bp, 0);
+		if (error) {
+			vput(vp);
+			break;
+		}
+
 		vput(vp);
 	}
 	vfs_vnode_iterator_destroy(marker);
@@ -934,7 +968,6 @@ ext2fs_loadvnode(struct mount *mp, struc
 	struct buf *bp;
 	dev_t dev;
 	int error;
-	void *cp;
 
 	KASSERT(key_len == sizeof(ino));
 	memcpy(&ino, key, key_len);
@@ -966,11 +999,10 @@ ext2fs_loadvnode(struct mount *mp, struc
 	/* Initialize genfs node. */
 	genfs_node_init(vp, &ext2fs_genfsops);
 
-	cp = (char *)bp->b_data + (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE(fs));
-	ip->i_din.e2fs_din = pool_get(&ext2fs_dinode_pool, PR_WAITOK);
-	e2fs_iload((struct ext2fs_dinode *)cp, ip->i_din.e2fs_din);
-	ext2fs_set_inode_guid(ip);
+	error = ext2fs_loadvnode_content(fs, ino, bp, ip);
 	brelse(bp, 0);
+	if (error)
+		return error;
 
 	/* If the inode was deleted, reset all fields */
 	if (ip->i_e2fs_dtime != 0) {
@@ -1159,34 +1191,6 @@ ext2fs_sbfill(struct m_ext2fs *m_fs, int
 	}
 
 	/*
-	 * Revision-specific checks
-	 */
-	if (fs->e2fs_rev > E2FS_REV0) {
-		char buf[256];
-		if (fs->e2fs_first_ino != EXT2_FIRSTINO) {
-			printf("ext2fs: unsupported first inode position\n");
-			return EINVAL;
-		}
-		u32 = fs->e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP;
-		if (u32) {
-			snprintb(buf, sizeof(buf), EXT2F_INCOMPAT_BITS, u32);
-			printf("ext2fs: unsupported incompat features: %s\n", buf);
-			return EINVAL;
-		}
-		u32 = fs->e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP;
-		if (!ronly && u32) {
-			snprintb(buf, sizeof(buf), EXT2F_ROCOMPAT_BITS, u32);
-			printf("ext2fs: unsupported ro-incompat features: %s\n",
-			    buf);
-			return EROFS;
-		}
-		if (fs->e2fs_inode_size == 0 || !powerof2(fs->e2fs_inode_size)) {
-			printf("ext2fs: bad inode size\n");
-			return EINVAL;
-		}
-	}
-
-	/*
 	 * Compute the fields of the superblock
 	 */
 	u32 = fs->e2fs_bcount - fs->e2fs_first_dblock; /* > 0 */
@@ -1221,5 +1225,33 @@ ext2fs_sbfill(struct m_ext2fs *m_fs, int
 
 	m_fs->e2fs_itpg = fs->e2fs_ipg / m_fs->e2fs_ipb;
 
+	/*
+	 * Revision-specific checks
+	 */
+	if (fs->e2fs_rev > E2FS_REV0) {
+		char buf[256];
+		if (fs->e2fs_first_ino != EXT2_FIRSTINO) {
+			printf("ext2fs: unsupported first inode position\n");
+			return EINVAL;
+		}
+		u32 = fs->e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP;
+		if (u32) {
+			snprintb(buf, sizeof(buf), EXT2F_INCOMPAT_BITS, u32);
+			printf("ext2fs: unsupported incompat features: %s\n", buf);
+			return EINVAL;
+		}
+		u32 = fs->e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP;
+		if (!ronly && u32) {
+			snprintb(buf, sizeof(buf), EXT2F_ROCOMPAT_BITS, u32);
+			printf("ext2fs: unsupported ro-incompat features: %s\n",
+			    buf);
+			return EROFS;
+		}
+		if (fs->e2fs_inode_size == 0 || !powerof2(fs->e2fs_inode_size) || fs->e2fs_inode_size > m_fs->e2fs_bsize) {
+			printf("ext2fs: bad inode size\n");
+			return EINVAL;
+		}
+	}
+
 	return 0;
 }

Index: src/sys/ufs/ext2fs/ext2fs_vnops.c
diff -u src/sys/ufs/ext2fs/ext2fs_vnops.c:1.117 src/sys/ufs/ext2fs/ext2fs_vnops.c:1.118
--- src/sys/ufs/ext2fs/ext2fs_vnops.c:1.117	Mon Apr 20 23:03:09 2015
+++ src/sys/ufs/ext2fs/ext2fs_vnops.c	Wed Aug  3 21:53:03 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_vnops.c,v 1.117 2015/04/20 23:03:09 riastradh Exp $	*/
+/*	$NetBSD: ext2fs_vnops.c,v 1.118 2016/08/03 21:53:03 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -65,7 +65,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.117 2015/04/20 23:03:09 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.118 2016/08/03 21:53:03 jdolecek Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1119,7 +1119,7 @@ ext2fs_reclaim(void *v)
 	if ((error = ufs_reclaim(vp)) != 0)
 		return (error);
 	if (ip->i_din.e2fs_din != NULL)
-		pool_put(&ext2fs_dinode_pool, ip->i_din.e2fs_din);
+		kmem_free(ip->i_din.e2fs_din, EXT2_DINODE_SIZE(ip->i_e2fs));
 	genfs_node_destroy(vp);
 	pool_put(&ext2fs_inode_pool, vp->v_data);
 	vp->v_data = NULL;

Reply via email to