Module Name:    src
Committed By:   jakllsch
Date:           Sun Nov 25 19:42:14 UTC 2012

Modified Files:
        src/sbin/fsck_ext2fs: dir.c extern.h inode.c pass1.c

Log Message:
Catch up to the kernel with respect to Ext2 huge_file feature.


To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.25 src/sbin/fsck_ext2fs/dir.c
cvs rdiff -u -r1.7 -r1.8 src/sbin/fsck_ext2fs/extern.h
cvs rdiff -u -r1.31 -r1.32 src/sbin/fsck_ext2fs/inode.c
cvs rdiff -u -r1.21 -r1.22 src/sbin/fsck_ext2fs/pass1.c

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

Modified files:

Index: src/sbin/fsck_ext2fs/dir.c
diff -u src/sbin/fsck_ext2fs/dir.c:1.24 src/sbin/fsck_ext2fs/dir.c:1.25
--- src/sbin/fsck_ext2fs/dir.c:1.24	Sun Nov 25 19:36:23 2012
+++ src/sbin/fsck_ext2fs/dir.c	Sun Nov 25 19:42:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: dir.c,v 1.24 2012/11/25 19:36:23 jakllsch Exp $	*/
+/*	$NetBSD: dir.c,v 1.25 2012/11/25 19:42:14 jakllsch Exp $	*/
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -58,7 +58,7 @@
 #if 0
 static char sccsid[] = "@(#)dir.c	8.5 (Berkeley) 12/8/94";
 #else
-__RCSID("$NetBSD: dir.c,v 1.24 2012/11/25 19:36:23 jakllsch Exp $");
+__RCSID("$NetBSD: dir.c,v 1.25 2012/11/25 19:42:14 jakllsch Exp $");
 #endif
 #endif /* not lint */
 
@@ -569,8 +569,7 @@ expanddir(struct ext2fs_dinode *dp, char
 	dp->e2di_blocks[lastbn + 1] = dp->e2di_blocks[lastbn];
 	dp->e2di_blocks[lastbn] = h2fs32(newblk);
 	inossize(dp, inosize(dp) + sblock.e2fs_bsize);
-	dp->e2di_nblock = h2fs32(fs2h32(dp->e2di_nblock) +
-		btodb(sblock.e2fs_bsize));
+	inosnblock(dp, inonblock(dp) + btodb(sblock.e2fs_bsize));
 	bp = getdirblk(fs2h32(dp->e2di_blocks[lastbn + 1]),
 		sblock.e2fs_bsize);
 	if (bp->b_errs)
@@ -604,8 +603,7 @@ bad:
 	dp->e2di_blocks[lastbn] = dp->e2di_blocks[lastbn + 1];
 	dp->e2di_blocks[lastbn + 1] = 0;
 	inossize(dp, inosize(dp) - sblock.e2fs_bsize);
-	dp->e2di_nblock = h2fs32(fs2h32(dp->e2di_nblock) -
-		btodb(sblock.e2fs_bsize));
+	inosnblock(dp, inonblock(dp) - btodb(sblock.e2fs_bsize));
 	freeblk(newblk);
 	return (0);
 }

Index: src/sbin/fsck_ext2fs/extern.h
diff -u src/sbin/fsck_ext2fs/extern.h:1.7 src/sbin/fsck_ext2fs/extern.h:1.8
--- src/sbin/fsck_ext2fs/extern.h:1.7	Thu Jun  9 19:57:50 2011
+++ src/sbin/fsck_ext2fs/extern.h	Sun Nov 25 19:42:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.7 2011/06/09 19:57:50 christos Exp $	*/
+/*	$NetBSD: extern.h,v 1.8 2012/11/25 19:42:14 jakllsch Exp $	*/
 
 /*
  * Copyright (c) 1997 Manuel Bouyer.
@@ -71,3 +71,5 @@ int	reply(const char *);
 void	resetinodebuf(void);
 int	setup(const char *);
 struct	ext2fs_dinode * getnextinode(ino_t);
+uint64_t inonblock(struct ext2fs_dinode *);
+void	inosnblock(struct ext2fs_dinode *, uint64_t);

Index: src/sbin/fsck_ext2fs/inode.c
diff -u src/sbin/fsck_ext2fs/inode.c:1.31 src/sbin/fsck_ext2fs/inode.c:1.32
--- src/sbin/fsck_ext2fs/inode.c:1.31	Thu Feb  4 23:55:42 2010
+++ src/sbin/fsck_ext2fs/inode.c	Sun Nov 25 19:42:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: inode.c,v 1.31 2010/02/04 23:55:42 christos Exp $	*/
+/*	$NetBSD: inode.c,v 1.32 2012/11/25 19:42:14 jakllsch Exp $	*/
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -58,7 +58,7 @@
 #if 0
 static char sccsid[] = "@(#)inode.c	8.5 (Berkeley) 2/8/95";
 #else
-__RCSID("$NetBSD: inode.c,v 1.31 2010/02/04 23:55:42 christos Exp $");
+__RCSID("$NetBSD: inode.c,v 1.32 2012/11/25 19:42:14 jakllsch Exp $");
 #endif
 #endif /* not lint */
 
@@ -97,6 +97,8 @@ static int iblock(struct inodesc *, long
 
 static int setlarge(void);
 
+static int sethuge(void);
+
 static int
 setlarge(void)
 {
@@ -115,6 +117,24 @@ setlarge(void)
 	return 1;
 }
 
+static int
+sethuge(void)
+{
+	if (sblock.e2fs.e2fs_rev < E2FS_REV1) {
+		pfatal("HUGE FILES UNSUPPORTED ON REVISION 0 FILESYSTEMS");
+		return 0;
+	}
+	if (!(sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE)) {
+		if (preen)
+			pwarn("SETTING HUGE FILE FEATURE\n");
+		else if (!reply("SET HUGE FILE FEATURE"))
+			return 0;
+		sblock.e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_HUGE_FILE;
+		sbdirty();
+	}
+	return 1;
+}
+
 u_int64_t
 inosize(struct ext2fs_dinode *dp)
 {
@@ -707,7 +727,7 @@ allocino(ino_t request, int type)
 	dp->e2di_mtime = dp->e2di_ctime = dp->e2di_atime;
 	dp->e2di_dtime = 0;
 	inossize(dp, sblock.e2fs_bsize);
-	dp->e2di_nblock = h2fs32(btodb(sblock.e2fs_bsize));
+	inosnblock(dp, btodb(sblock.e2fs_bsize));
 	n_files++;
 	inodirty();
 	typemap[ino] = E2IFTODT(type);
@@ -734,3 +754,59 @@ freeino(ino_t ino)
 	statemap[ino] = USTATE;
 	n_files--;
 }
+
+uint64_t
+inonblock(struct ext2fs_dinode *dp)
+{
+	uint64_t nblock;
+
+	/* XXX check for EXT2_HUGE_FILE without EXT2F_ROCOMPAT_HUGE_FILE? */
+
+	nblock = fs2h32(dp->e2di_nblock);
+
+	if ((sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_HUGE_FILE)) {
+		nblock |= (uint64_t)fs2h16(dp->e2di_nblock_high) << 32;
+		if (fs2h32(dp->e2di_flags) & EXT2_HUGE_FILE) {
+			nblock = fsbtodb(&sblock, nblock);
+		}
+	}
+
+	return nblock;
+}
+
+void
+inosnblock(struct ext2fs_dinode *dp, uint64_t nblock)
+{
+	uint32_t flags;
+
+	flags = fs2h32(dp->e2di_flags);
+
+	if (nblock <= 0xffffffffULL) {
+		flags &= ~EXT2_HUGE_FILE;
+		dp->e2di_flags = h2fs32(flags);
+		dp->e2di_nblock = h2fs32(nblock);
+		return;
+	}
+
+	sethuge();
+
+	if (nblock <= 0xffffffffffffULL) {
+		flags &= ~EXT2_HUGE_FILE;
+		dp->e2di_flags = h2fs32(flags);
+		dp->e2di_nblock = h2fs32(nblock);
+		dp->e2di_nblock_high = h2fs16((nblock >> 32));
+		return;
+	}
+
+	if (dbtofsb(&sblock, nblock) <= 0xffffffffffffULL) {
+		flags |= EXT2_HUGE_FILE;
+		dp->e2di_flags = h2fs32(flags);
+		dp->e2di_nblock = h2fs32(dbtofsb(&sblock, nblock));
+		dp->e2di_nblock_high = h2fs16((dbtofsb(&sblock, nblock) >> 32));
+		return;
+	}
+
+	pfatal("trying to set nblocks higher than representable");
+
+	return;
+}

Index: src/sbin/fsck_ext2fs/pass1.c
diff -u src/sbin/fsck_ext2fs/pass1.c:1.21 src/sbin/fsck_ext2fs/pass1.c:1.22
--- src/sbin/fsck_ext2fs/pass1.c:1.21	Thu Feb  4 23:55:42 2010
+++ src/sbin/fsck_ext2fs/pass1.c	Sun Nov 25 19:42:14 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: pass1.c,v 1.21 2010/02/04 23:55:42 christos Exp $	*/
+/*	$NetBSD: pass1.c,v 1.22 2012/11/25 19:42:14 jakllsch Exp $	*/
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -58,7 +58,7 @@
 #if 0
 static char sccsid[] = "@(#)pass1.c	8.1 (Berkeley) 6/5/93";
 #else
-__RCSID("$NetBSD: pass1.c,v 1.21 2010/02/04 23:55:42 christos Exp $");
+__RCSID("$NetBSD: pass1.c,v 1.22 2012/11/25 19:42:14 jakllsch Exp $");
 #endif
 #endif /* not lint */
 
@@ -302,16 +302,17 @@ checkinode(ino_t inumber, struct inodesc
 	idesc->id_number = inumber;
 	(void)ckinode(dp, idesc);
 	idesc->id_entryno *= btodb(sblock.e2fs_bsize);
-	if (fs2h32(dp->e2di_nblock) != (uint32_t)idesc->id_entryno) {
-		pwarn("INCORRECT BLOCK COUNT I=%llu (%d should be %d)",
-		    (unsigned long long)inumber, fs2h32(dp->e2di_nblock),
+	if (inonblock(dp) != (uint32_t)idesc->id_entryno) {
+		pwarn("INCORRECT BLOCK COUNT I=%llu (%llu should be %d)",
+		    (unsigned long long)inumber,
+		    (unsigned long long)inonblock(dp),
 		    idesc->id_entryno);
 		if (preen)
 			printf(" (CORRECTED)\n");
 		else if (reply("CORRECT") == 0)
 			return;
 		dp = ginode(inumber);
-		dp->e2di_nblock = h2fs32(idesc->id_entryno);
+		inosnblock(dp, idesc->id_entryno);
 		inodirty();
 	}
 	return;

Reply via email to