Subject: kern/9088: Patch for NetBSD 1.4.1 to support ext2fs Rev. 1
To: None <gnats-bugs@gnats.netbsd.org>
From: None <sgoel@cyberdialogue.com>
List: netbsd-bugs
Date: 12/31/1999 10:51:58
>Number:         9088
>Category:       kern
>Synopsis:       Add support for ext2fs Rev. 1 to NetBSD 1.4.1
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Dec 31 10:50:59 1999
>Last-Modified:
>Originator:     Shantanu Goel
>Organization:
	
>Release:        NetBSD 1.4.1
>Environment:
	
System: NetBSD anupama.goel.com 1.4.1 NetBSD 1.4.1 (ANUPAMA) #4: Fri Dec 31 09:45:51 GMT 1999 root@anupama.goel.com:/usr/src/sys/arch/i386/compile/ANUPAMA i386


>Description:
	NetBSD 1.4.1 does not support ext2fs Rev. 1.  Newer versions
	of Linux (version 2.2.13 in my case) create a filesystem with
	this revision.  The attached patch adds support for this.
>How-To-Repeat:
	The kernel refuses to mount a Rev. 1 ext2fs filesystem because
	it only supports Rev. 0.
>Fix:
	Please see attached patch.

diff -cr ext2fs.orig/ext2fs.h ext2fs/ext2fs.h
*** ext2fs.orig/ext2fs.h	Wed Feb 17 13:09:43 1999
--- ext2fs/ext2fs.h	Thu Dec 30 12:48:27 1999
***************
*** 152,157 ****
--- 152,159 ----
  	int32_t	e2fs_ngdb;	/* number of group descriptor block */
  	int32_t	e2fs_ipb;	/* number of inodes per block */
  	int32_t	e2fs_itpg;	/* number of inode table per group */
+ 	u_int32_t e2fs_firstino;/* first non-reserved inode */
+ 	u_int32_t e2fs_isize;	/* inode size */
  	struct	ext2_gd *e2fs_gd; /* group descripors */
  };
  
***************
*** 160,167 ****
  /*
   * Filesystem identification
   */
! #define	E2FS_MAGIC	0xef53	/* the ext2fs magic number */
! #define E2FS_REV	0	/* revision level */
  
  /*
   * OS identification
--- 162,171 ----
  /*
   * Filesystem identification
   */
! #define	E2FS_MAGIC		0xef53	/* the ext2fs magic number */
! #define E2FS_OLD_REV		0	/* original version */
! #define E2FS_DYNAMIC_REV	1	/* V2 with dynamic inode sizes */
! #define E2FS_REV		E2FS_DYNAMIC_REV
  
  /*
   * OS identification
diff -cr ext2fs.orig/ext2fs_alloc.c ext2fs/ext2fs_alloc.c
*** ext2fs.orig/ext2fs_alloc.c	Wed Feb 10 13:14:09 1999
--- ext2fs/ext2fs_alloc.c	Thu Dec 30 13:00:37 1999
***************
*** 558,564 ****
  
  	pip = VTOI(ap->a_pvp);
  	fs = pip->i_e2fs;
! 	if ((u_int)ino >= fs->e2fs.e2fs_icount || (u_int)ino < EXT2_FIRSTINO)
  		panic("ifree: range: dev = 0x%x, ino = %d, fs = %s\n",
  			pip->i_dev, ino, fs->e2fs_fsmnt);
  	cg = ino_to_cg(fs, ino);
--- 558,565 ----
  
  	pip = VTOI(ap->a_pvp);
  	fs = pip->i_e2fs;
! 	if ((u_int)ino >= fs->e2fs.e2fs_icount ||
! 	    (u_int)ino < fs->e2fs_firstino)
  		panic("ifree: range: dev = 0x%x, ino = %d, fs = %s\n",
  			pip->i_dev, ino, fs->e2fs_fsmnt);
  	cg = ino_to_cg(fs, ino);
diff -cr ext2fs.orig/ext2fs_bswap.c ext2fs/ext2fs_bswap.c
*** ext2fs.orig/ext2fs_bswap.c	Sun Aug  9 20:15:38 1998
--- ext2fs/ext2fs_bswap.c	Thu Dec 30 12:38:33 1999
***************
*** 70,75 ****
--- 70,77 ----
  	new->e2fs_beh			=		bswap16(old->e2fs_beh);
  	new->e2fs_ruid			=		bswap16(old->e2fs_ruid);
  	new->e2fs_rgid			=		bswap16(old->e2fs_rgid);
+ 	new->e2fs_first_ino		=		bswap32(old->e2fs_first_ino;
+ 	new->e2fs_inode_size		=		bswap16(old->e2fs_inode_size;
  }
  
  void e2fs_cg_bswap(old, new, size)
diff -cr ext2fs.orig/ext2fs_inode.c ext2fs/ext2fs_inode.c
*** ext2fs.orig/ext2fs_inode.c	Wed Mar 24 05:51:30 1999
--- ext2fs/ext2fs_inode.c	Thu Dec 30 13:02:58 1999
***************
*** 155,161 ****
  		return (error);
  	}
  	cp = (caddr_t)bp->b_data +
! 	    (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE);
  	e2fs_isave(&ip->i_din.e2fs_din, (struct ext2fs_dinode *)cp);
  	if (ap->a_waitfor && (ap->a_vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
  		return (bwrite(bp));
--- 155,161 ----
  		return (error);
  	}
  	cp = (caddr_t)bp->b_data +
! 	    (ino_to_fsbo(fs, ip->i_number) * fs->e2fs_isize);
  	e2fs_isave(&ip->i_din.e2fs_din, (struct ext2fs_dinode *)cp);
  	if (ap->a_waitfor && (ap->a_vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
  		return (bwrite(bp));
diff -cr ext2fs.orig/ext2fs_vfsops.c ext2fs/ext2fs_vfsops.c
*** ext2fs.orig/ext2fs_vfsops.c	Mon Jun 21 23:03:07 1999
--- ext2fs/ext2fs_vfsops.c	Fri Dec 31 13:21:51 1999
***************
*** 369,375 ****
  		brelse(bp);
  		return (EIO);		/* XXX needs translation */
  	}
! 	if (fs2h32(newfs->e2fs_rev) != E2FS_REV) {
  #ifdef DIAGNOSTIC
  		printf("Ext2 fs: unsupported revision number: %x (expected %x)\n",
  					fs2h32(newfs->e2fs_rev), E2FS_REV);
--- 369,380 ----
  		brelse(bp);
  		return (EIO);		/* XXX needs translation */
  	}
! 
! #ifdef DEBUG_EXT2
! 	printf("rev: %x\n", fs2h32(newfs->e2fs_rev));
! #endif
! 
! 	if (fs2h32(newfs->e2fs_rev) > E2FS_REV) {
  #ifdef DIAGNOSTIC
  		printf("Ext2 fs: unsupported revision number: %x (expected %x)\n",
  					fs2h32(newfs->e2fs_rev), E2FS_REV);
***************
*** 386,397 ****
  		return (EIO);	   /* XXX needs translation */
  	}
  
- 
  	fs = VFSTOUFS(mountp)->um_e2fs;
  	/* 
  	 * copy in new superblock, and compute in-memory values
  	 */
  	e2fs_sbload(newfs, &fs->e2fs);
  	fs->e2fs_ncg =
  	    howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
  	    fs->e2fs.e2fs_bpg);
--- 391,402 ----
  		return (EIO);	   /* XXX needs translation */
  	}
  
  	fs = VFSTOUFS(mountp)->um_e2fs;
  	/* 
  	 * copy in new superblock, and compute in-memory values
  	 */
  	e2fs_sbload(newfs, &fs->e2fs);
+ 
  	fs->e2fs_ncg =
  	    howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock,
  	    fs->e2fs.e2fs_bpg);
***************
*** 403,409 ****
  	fs->e2fs_bmask = ~fs->e2fs_qbmask;
  	fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
  			fs->e2fs_bsize / sizeof(struct ext2_gd));
! 	fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE;
  	fs->e2fs_itpg = fs->e2fs.e2fs_ipg/fs->e2fs_ipb;
  
  	/*
--- 408,432 ----
  	fs->e2fs_bmask = ~fs->e2fs_qbmask;
  	fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
  			fs->e2fs_bsize / sizeof(struct ext2_gd));
! 	if (fs->e2fs.e2fs_rev == E2FS_OLD_REV) {
! 		fs->e2fs_isize = EXT2_DINODE_SIZE;
! 		fs->e2fs_firstino = EXT2_FIRSTINO;
! 	} else {
! 		fs->e2fs_isize = fs->e2fs.e2fs_inode_size;
! 		fs->e2fs_firstino = fs->e2fs.e2fs_first_ino;
! 	}
! 	/*
! 	 * Check the inode size.
! 	 */
! 	if (fs->e2fs_isize != EXT2_DINODE_SIZE) {
! #ifdef DIAGNOSTIC
! 		printf("Ext2 fs: unsupported inode size: %d (expected %d)\n",
! 		       fs->e2fs_isize, EXT2_DINODE_SIZE);
! #endif
! 		brelse(bp);
! 		return (EIO);	/* XXX needs translation */
! 	}
! 	fs->e2fs_ipb = fs->e2fs_bsize / fs->e2fs_isize;
  	fs->e2fs_itpg = fs->e2fs.e2fs_ipg/fs->e2fs_ipb;
  
  	/*
***************
*** 457,463 ****
  			return (error);
  		}
  		cp = (caddr_t)bp->b_data +
! 		    (ino_to_fsbo(fs, ip->i_number) * EXT2_DINODE_SIZE);
  		e2fs_iload((struct ext2fs_dinode *)cp, &ip->i_din.e2fs_din);
  		brelse(bp);
  		vput(vp);
--- 480,486 ----
  			return (error);
  		}
  		cp = (caddr_t)bp->b_data +
! 		    (ino_to_fsbo(fs, ip->i_number) * fs->e2fs_isize);
  		e2fs_iload((struct ext2fs_dinode *)cp, &ip->i_din.e2fs_din);
  		brelse(bp);
  		vput(vp);
***************
*** 514,531 ****
  	ump = NULL;
  
  #ifdef DEBUG_EXT2
! 	printf("sb size: %d ino size %d\n", sizeof(struct ext2fs),
! 	    EXT2_DINODE_SIZE);
  #endif
  	error = bread(devvp, (SBOFF / DEV_BSIZE), SBSIZE, cred, &bp);
  	if (error)
  		goto out;
  	fs = (struct ext2fs *)bp->b_data;
  	if (fs2h16(fs->e2fs_magic) != E2FS_MAGIC) {
  		error = EINVAL;		/* XXX needs translation */
  		goto out;
  	}
! 	if (fs2h32(fs->e2fs_rev) != E2FS_REV) {
  #ifdef DIAGNOSTIC
  		printf("Ext2 fs: unsupported revision number: %x (expected %x)\n",
  					fs2h32(fs->e2fs_rev), E2FS_REV);
--- 537,562 ----
  	ump = NULL;
  
  #ifdef DEBUG_EXT2
! 	printf("sb size: %d\n", sizeof(struct ext2fs));
  #endif
  	error = bread(devvp, (SBOFF / DEV_BSIZE), SBSIZE, cred, &bp);
  	if (error)
  		goto out;
  	fs = (struct ext2fs *)bp->b_data;
  	if (fs2h16(fs->e2fs_magic) != E2FS_MAGIC) {
+ #ifdef DEBUG_EXT2
+ 		printf("bad magic: %x (expected %x)\n",
+ 		       fs2h16(fs->e2fs_magic), E2FS_MAGIC);
+ #endif
  		error = EINVAL;		/* XXX needs translation */
  		goto out;
  	}
! 
! #ifdef DEBUG_EXT2
! 	printf("rev: %x\n", fs2h32(fs->e2fs_rev));
! #endif
! 
! 	if (fs2h32(fs->e2fs_rev) > E2FS_REV) {
  #ifdef DIAGNOSTIC
  		printf("Ext2 fs: unsupported revision number: %x (expected %x)\n",
  					fs2h32(fs->e2fs_rev), E2FS_REV);
***************
*** 571,577 ****
  	m_fs->e2fs_bmask = ~m_fs->e2fs_qbmask;
  	m_fs->e2fs_ngdb = howmany(m_fs->e2fs_ncg,
  		m_fs->e2fs_bsize / sizeof(struct ext2_gd));
! 	m_fs->e2fs_ipb = m_fs->e2fs_bsize / EXT2_DINODE_SIZE;
  	m_fs->e2fs_itpg = m_fs->e2fs.e2fs_ipg/m_fs->e2fs_ipb;
  
  	m_fs->e2fs_gd = malloc(m_fs->e2fs_ngdb * m_fs->e2fs_bsize,
--- 602,632 ----
  	m_fs->e2fs_bmask = ~m_fs->e2fs_qbmask;
  	m_fs->e2fs_ngdb = howmany(m_fs->e2fs_ncg,
  		m_fs->e2fs_bsize / sizeof(struct ext2_gd));
! 	if (m_fs->e2fs.e2fs_rev == E2FS_OLD_REV) {
! 		m_fs->e2fs_isize = EXT2_DINODE_SIZE;
! 		m_fs->e2fs_firstino = EXT2_FIRSTINO;
! 	} else {
! 		m_fs->e2fs_isize = m_fs->e2fs.e2fs_inode_size;
! 		m_fs->e2fs_firstino = m_fs->e2fs.e2fs_first_ino;
! 	}
! 	/*
! 	 * Check the inode size.
! 	 */
! 	if (m_fs->e2fs_isize != EXT2_DINODE_SIZE) {
! #ifdef DIAGNOSTIC
! 		printf("Ext2 fs: unsupported inode size: %d (expected %d)\n",
! 		       m_fs->e2fs_isize, EXT2_DINODE_SIZE);
! #endif
! 		error = EINVAL;	/* XXX needs translation */
! 		goto out;
! 	}
! 
! #ifdef DEBUG_EXT2
! 	printf("inode size: %d, first inode: %d\n",
! 	       m_fs->e2fs_isize, m_fs->e2fs_firstino);
! #endif
! 
! 	m_fs->e2fs_ipb = m_fs->e2fs_bsize / m_fs->e2fs_isize;
  	m_fs->e2fs_itpg = m_fs->e2fs.e2fs_ipg/m_fs->e2fs_ipb;
  
  	m_fs->e2fs_gd = malloc(m_fs->e2fs_ngdb * m_fs->e2fs_bsize,
***************
*** 877,883 ****
  		return (error);
  	}
  	cp = (caddr_t)bp->b_data +
! 	    (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE);
  	e2fs_iload((struct ext2fs_dinode *)cp, &ip->i_din.e2fs_din);
  	brelse(bp);
  
--- 932,938 ----
  		return (error);
  	}
  	cp = (caddr_t)bp->b_data +
! 	    (ino_to_fsbo(fs, ino) * fs->e2fs_isize);
  	e2fs_iload((struct ext2fs_dinode *)cp, &ip->i_din.e2fs_din);
  	brelse(bp);
  
***************
*** 940,946 ****
  
  	ufhp = (struct ufid *)fhp;
  	fs = VFSTOUFS(mp)->um_e2fs;
! 	if ((ufhp->ufid_ino < EXT2_FIRSTINO && ufhp->ufid_ino != EXT2_ROOTINO) ||
  		ufhp->ufid_ino >= fs->e2fs_ncg * fs->e2fs.e2fs_ipg)
  		return (ESTALE);
  
--- 995,1002 ----
  
  	ufhp = (struct ufid *)fhp;
  	fs = VFSTOUFS(mp)->um_e2fs;
! 	if ((ufhp->ufid_ino < fs->e2fs_firstino &&
! 	     ufhp->ufid_ino != EXT2_ROOTINO) ||
  		ufhp->ufid_ino >= fs->e2fs_ncg * fs->e2fs.e2fs_ipg)
  		return (ESTALE);
  
>Audit-Trail:
>Unformatted: