Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 6 May 2019 19:15:59 +0000 (UTC)
From:      Kirk McKusick <mckusick@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r347200 - stable/11/sbin/fsck_ffs
Message-ID:  <201905061915.x46JFxBY004453@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mckusick
Date: Mon May  6 19:15:59 2019
New Revision: 347200
URL: https://svnweb.freebsd.org/changeset/base/347200

Log:
  MFC of 346185
  
  Properly calculate last block of large sparse files.
  
  Sponsored by: Netflix

Modified:
  stable/11/sbin/fsck_ffs/fsck.h
  stable/11/sbin/fsck_ffs/inode.c
  stable/11/sbin/fsck_ffs/pass1.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sbin/fsck_ffs/fsck.h
==============================================================================
--- stable/11/sbin/fsck_ffs/fsck.h	Mon May  6 19:13:04 2019	(r347199)
+++ stable/11/sbin/fsck_ffs/fsck.h	Mon May  6 19:15:59 2019	(r347200)
@@ -229,6 +229,7 @@ struct inodesc {
 	ino_t id_parent;	/* for DATA nodes, their parent */
 	ufs_lbn_t id_lbn;	/* logical block number of current block */
 	ufs2_daddr_t id_blkno;	/* current block number being examined */
+	int id_level;		/* level of indirection of this block */
 	int id_numfrags;	/* number of frags contained in block */
 	ufs_lbn_t id_lballoc;	/* pass1: last LBN that is allocated */
 	off_t id_filesize;	/* for DATA nodes, the size of the directory */

Modified: stable/11/sbin/fsck_ffs/inode.c
==============================================================================
--- stable/11/sbin/fsck_ffs/inode.c	Mon May  6 19:13:04 2019	(r347199)
+++ stable/11/sbin/fsck_ffs/inode.c	Mon May  6 19:15:59 2019	(r347200)
@@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$");
 
 static ino_t startinum;
 
-static int iblock(struct inodesc *, long ilevel, off_t isize, int type);
+static int iblock(struct inodesc *, off_t isize, int type);
 
 int
 ckinode(union dinode *dp, struct inodesc *idesc)
@@ -67,6 +67,8 @@ ckinode(union dinode *dp, struct inodesc *idesc)
 	if (idesc->id_fix != IGNORE)
 		idesc->id_fix = DONTKNOW;
 	idesc->id_lbn = -1;
+	idesc->id_lballoc = -1;
+	idesc->id_level = 0;
 	idesc->id_entryno = 0;
 	idesc->id_filesize = DIP(dp, di_size);
 	mode = DIP(dp, di_mode) & IFMT;
@@ -119,9 +121,10 @@ ckinode(union dinode *dp, struct inodesc *idesc)
 	sizepb = sblock.fs_bsize;
 	for (i = 0; i < NIADDR; i++) {
 		sizepb *= NINDIR(&sblock);
+		idesc->id_level = i + 1;
 		if (DIP(&dino, di_ib[i])) {
 			idesc->id_blkno = DIP(&dino, di_ib[i]);
-			ret = iblock(idesc, i + 1, remsize, BT_LEVEL1 + i);
+			ret = iblock(idesc, remsize, BT_LEVEL1 + i);
 			if (ret & STOP)
 				return (ret);
 		} else if (remsize > 0) {
@@ -151,7 +154,7 @@ ckinode(union dinode *dp, struct inodesc *idesc)
 }
 
 static int
-iblock(struct inodesc *idesc, long ilevel, off_t isize, int type)
+iblock(struct inodesc *idesc, off_t isize, int type)
 {
 	struct bufarea *bp;
 	int i, n, (*func)(struct inodesc *), nif;
@@ -169,8 +172,8 @@ iblock(struct inodesc *idesc, long ilevel, off_t isize
 	if (chkrange(idesc->id_blkno, idesc->id_numfrags))
 		return (SKIP);
 	bp = getdatablk(idesc->id_blkno, sblock.fs_bsize, type);
-	ilevel--;
-	for (sizepb = sblock.fs_bsize, i = 0; i < ilevel; i++)
+	idesc->id_level--;
+	for (sizepb = sblock.fs_bsize, i = 0; i < idesc->id_level; i++)
 		sizepb *= NINDIR(&sblock);
 	if (howmany(isize, sizepb) > NINDIR(&sblock))
 		nif = NINDIR(&sblock);
@@ -192,19 +195,21 @@ iblock(struct inodesc *idesc, long ilevel, off_t isize
 		flush(fswritefd, bp);
 	}
 	for (i = 0; i < nif; i++) {
-		if (ilevel == 0)
-			idesc->id_lbn++;
 		if (IBLK(bp, i)) {
 			idesc->id_blkno = IBLK(bp, i);
-			if (ilevel == 0)
+			if (idesc->id_level == 0) {
+				idesc->id_lbn++;
 				n = (*func)(idesc);
-			else
-				n = iblock(idesc, ilevel, isize, type);
+			} else {
+				n = iblock(idesc, isize, type);
+				idesc->id_level++;
+			}
 			if (n & STOP) {
 				bp->b_flags &= ~B_INUSE;
 				return (n);
 			}
 		} else {
+			idesc->id_lbn += sizepb / sblock.fs_bsize;
 			if (idesc->id_type == DATA && isize > 0) {
 				/* An empty block in a directory XXX */
 				getpathname(pathbuf, idesc->id_number,

Modified: stable/11/sbin/fsck_ffs/pass1.c
==============================================================================
--- stable/11/sbin/fsck_ffs/pass1.c	Mon May  6 19:13:04 2019	(r347199)
+++ stable/11/sbin/fsck_ffs/pass1.c	Mon May  6 19:15:59 2019	(r347200)
@@ -376,7 +376,6 @@ checkinode(ino_t inumber, struct inodesc *idesc, int r
 		idesc->id_type = SNAP;
 	else
 		idesc->id_type = ADDR;
-	idesc->id_lballoc = -1;
 	(void)ckinode(dp, idesc);
 	if (sblock.fs_magic == FS_UFS2_MAGIC && dp->dp2.di_extsize > 0) {
 		idesc->id_type = ADDR;
@@ -563,7 +562,7 @@ pass1check(struct inodesc *idesc)
 		 */
 		idesc->id_entryno++;
 	}
-	if (idesc->id_lballoc == -1 || idesc->id_lballoc < idesc->id_lbn)
+	if (idesc->id_level == 0 && idesc->id_lballoc < idesc->id_lbn)
 		idesc->id_lballoc = idesc->id_lbn;
 	return (res);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905061915.x46JFxBY004453>