From nobody Tue Apr 18 23:14:01 2023 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Q1KVf1l5zz45qFg; Tue, 18 Apr 2023 23:14:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Q1KVd6dZ1z4F3p; Tue, 18 Apr 2023 23:14:01 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1681859642; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nQPNjIt6vTejxu9pCC/8gxoOp5mT9oLW4A731wZU4Sg=; b=ULY8hg6rzmcVB6oYgPzQ0XBrNymUUAT+NIezm/9fXyxCn85i2z+sugcMle0ae6UytorBxV 6f/RH31WMSQFHAVUzt29SEczxrLUyYMjkg8LrEt/6b44fubedwqWqNbZWXAJzz+J5vFmaG sUlq3CE+TgLzwro6R4PiPe875/hWlIsFE1tUJkr+xQM+Fc4ktdq+Ag286AE4GWVdwUks7M 2qPf8ZyT9eqfLQ+JjyQJbEKLWov8id9TOh6wFU5qUU688TbpgChT8+kGQhTt35VdFn5ucP PTIeKVwSdzrp6rK4M216om6k1tBA7X6HMyMmuArYvf4LDVGVz0WrHQtzqQ3hwg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1681859642; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nQPNjIt6vTejxu9pCC/8gxoOp5mT9oLW4A731wZU4Sg=; b=ODWVnzAfCzVdErf075o0Sg6sIrnn8ZGVT+phCjf7lyVnm4rL/yZFslLT0YHhgDSSVkSV5M NrOrcuBFXKziHRm0btb5Z9lpPDnf7eJA+sSWIjePYIvF63CXxg6v57JAw8qkl4wUh12FF/ 8p4gsTp4kNM+vXKG9yzSyCy3j/inoC6YAq79iZfs2Dpth2pUEp5cszflWB9kRx2mgXLn9E fuC/qb3TYI9Y6Zzr2Z4wvGetpU1mMdezGKDSrKX8MumOIm4zolbsXZLmar+B1h4zS8/BoC rD/7Nz4XMLdme1JU03Dpwyf5A73B3N4r1SKm/TWAPBWg95ssMUEh1TAsllvUlg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1681859642; a=rsa-sha256; cv=none; b=GpeuJ8NJcVC5cBdH4Rqgl1JE4rRdlLJwlL5cXd4Xy0baC+IpXHKXaRq6LrGOo7nmAtADSD 1cdUtN9jdFQkMeJ8IUurlZl7yq3oa3OuyYQ4GryC614BhYhsi//gY6WyHs5b8NEE+4VDMV t4Dk6nMl2SN1t0dYOUE3zCj4/7kyjjYWjolohpsGiLoazLTySQ3l2TVnSwYnAGJ/RZ12hW 2ubdyb9VNSZ0wg1wD+GVE7SMJTAh1snRuqq1G1BKONCzfKSvz+5WFzgagrGAGRj4VkMQz9 t8KbJWib69K8xbVyh3LDC4j/rqsH9zdkP+kLLfIwVRb7CmYnFYdn3POC4zTWFw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Q1KVd5fzDzX2Q; Tue, 18 Apr 2023 23:14:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 33INE1cu095408; Tue, 18 Apr 2023 23:14:01 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 33INE1qg095407; Tue, 18 Apr 2023 23:14:01 GMT (envelope-from git) Date: Tue, 18 Apr 2023 23:14:01 GMT Message-Id: <202304182314.33INE1qg095407@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kirk McKusick Subject: git: da86e7a20dc4 - main - Skip Pass 5 in fsck_ffs(8) when corrupt cylinder groups remain unfixed. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mckusick X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: da86e7a20dc4a4b17e8d9e7630ed9b675cf71702 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by mckusick: URL: https://cgit.FreeBSD.org/src/commit/?id=da86e7a20dc4a4b17e8d9e7630ed9b675cf71702 commit da86e7a20dc4a4b17e8d9e7630ed9b675cf71702 Author: Kirk McKusick AuthorDate: 2023-04-18 23:10:49 +0000 Commit: Kirk McKusick CommitDate: 2023-04-18 23:13:26 +0000 Skip Pass 5 in fsck_ffs(8) when corrupt cylinder groups remain unfixed. Pass 1 of fsck_ffs checks the integrity of all the cylinder groups. If any are found to have been corrupted it offers to rebuild them. Pass 5 then makes a second pass over the cylinder groups to validate their block and inode maps. Pass 5 assumes that the cylinder groups are not corrupted and can segment fault if they are corrupted. Rather than rerunning the corruption checks a second time in pass 5, this fix keeps track whether any corrupt cylinder groups were found but not fixed in pass 1 either due to running with the -n flag or by explicitly answering `no' when asked whether to fix a corrupted cylinder group. If any corrupted cylinder groups remain after pass 1, fsck_ffs will decline to run pass 5. Instead it marks the filesystem as unclean so that fsck_ffs will need to be run again before the filesystem can be mounted. This patch cleans up and documents the return value from check_cgmagic(). It also renames the variable / parameter "rebuildcg" to "rebuiltcg". This parameter describes whether the cylinder group has been rebuilt rather than whether it should be rebuilt. Reported by: Chuck Silvers Reviewed by: Chuck Silvers MFC after: 1 week --- sbin/fsck_ffs/fsck.h | 3 ++- sbin/fsck_ffs/fsutil.c | 8 ++++++-- sbin/fsck_ffs/globs.c | 2 ++ sbin/fsck_ffs/inode.c | 4 ++-- sbin/fsck_ffs/main.c | 9 +++++++-- sbin/fsck_ffs/pass1.c | 30 +++++++++++++++++------------- 6 files changed, 36 insertions(+), 20 deletions(-) diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 43e826e13b77..95dccf0d672d 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -346,6 +346,7 @@ extern off_t bflag; /* location of alternate super block */ extern int bkgrdflag; /* use a snapshot to run on an active system */ extern char *blockmap; /* ptr to primary blk allocation map */ extern char *cdevname; /* name of device being checked */ +extern int cgheader_corrupt; /* one or more CG headers are corrupt */ extern char ckclean; /* only do work if not cleanly unmounted */ extern int ckhashadd; /* check hashes to be added */ extern char *copybuf; /* buffer to copy snapshot blocks */ @@ -493,7 +494,7 @@ int ftypeok(union dinode *dp); void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size); struct bufarea *getdatablk(ufs2_daddr_t blkno, long size, int type); struct inoinfo *getinoinfo(ino_t inumber); -union dinode *getnextinode(ino_t inumber, int rebuildcg); +union dinode *getnextinode(ino_t inumber, int rebuiltcg); void getpathname(char *namebuf, ino_t curdir, ino_t ino); void ginode(ino_t, struct inode *); void gjournal_check(const char *filesys); diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index 2b915d28aa26..1df52b7cfdc9 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -988,6 +988,10 @@ blzero(int fd, ufs2_daddr_t blk, long size) /* * Verify cylinder group's magic number and other parameters. If the * test fails, offer an option to rebuild the whole cylinder group. + * + * Return 1 if the cylinder group is good or if repair is requested + * and is completed successfully. Return 0 if it is bad or if a repair + * has been requested but is not completed successfully. */ #undef CHK #define CHK(lhs, op, rhs, fmt) \ @@ -1080,7 +1084,7 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild) if (!reply("REBUILD CYLINDER GROUP")) { printf("YOU WILL NEED TO RERUN FSCK.\n"); rerun = 1; - return (1); + return (0); } /* * Zero out the cylinder group and then initialize critical fields. @@ -1123,7 +1127,7 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild) } cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize); cgdirty(cgbp); - return (0); + return (1); } /* diff --git a/sbin/fsck_ffs/globs.c b/sbin/fsck_ffs/globs.c index 306944fa95b9..bce499754301 100644 --- a/sbin/fsck_ffs/globs.c +++ b/sbin/fsck_ffs/globs.c @@ -110,6 +110,7 @@ ino_t lfdir; /* lost & found directory inode number */ const char *lfname; /* lost & found directory name */ int lfmode; /* lost & found directory creation mode */ ufs2_daddr_t n_blks; /* number of blocks in use */ +int cgheader_corrupt; /* one or more CG headers are corrupt */ ino_t n_files; /* number of files in use */ volatile sig_atomic_t got_siginfo; /* received a SIGINFO */ volatile sig_atomic_t got_sigalarm; /* received a SIGALRM */ @@ -164,6 +165,7 @@ fsckinit(void) lfmode = 0700; n_blks = 0; n_files = 0; + cgheader_corrupt = 0; got_siginfo = 0; got_sigalarm = 0; bzero(&zino.dp1, sizeof(struct ufs1_dinode)); diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c index 37b0f9ebc1b1..2d563f617a56 100644 --- a/sbin/fsck_ffs/inode.c +++ b/sbin/fsck_ffs/inode.c @@ -510,7 +510,7 @@ static ino_t nextinum, lastvalidinum; static long readcount, readpercg, fullcnt, inobufsize, partialcnt, partialsize; union dinode * -getnextinode(ino_t inumber, int rebuildcg) +getnextinode(ino_t inumber, int rebuiltcg) { int j; long size; @@ -569,7 +569,7 @@ getnextinode(ino_t inumber, int rebuildcg) dirty(&inobuf); } } - if (rebuildcg && (char *)dp == inobuf.b_un.b_buf) { + if (rebuiltcg && (char *)dp == inobuf.b_un.b_buf) { /* * Try to determine if we have reached the end of the * allocated inodes. diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index f7d995a54d1b..2bd61dda7030 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -490,8 +490,13 @@ checkfilesys(char *filesys) if (preen == 0) printf("** Phase 5 - Check Cyl groups\n"); snapflush(std_checkblkavail); - pass5(); - IOstats("Pass5"); + if (cgheader_corrupt) { + printf("PHASE 5 SKIPPED DUE TO CORRUPT CYLINDER GROUP " + "HEADER(S)\n"); + } else { + pass5(); + IOstats("Pass5"); + } /* * print out summary statistics diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c index afe9f7f2b789..55233e0bc4f4 100644 --- a/sbin/fsck_ffs/pass1.c +++ b/sbin/fsck_ffs/pass1.c @@ -56,7 +56,7 @@ static ufs2_daddr_t badblk; static ufs2_daddr_t dupblk; static ino_t lastino; /* last inode in use */ -static int checkinode(ino_t inumber, struct inodesc *, int rebuildcg); +static int checkinode(ino_t inumber, struct inodesc *, int rebuiltcg); void pass1(void) @@ -68,7 +68,7 @@ pass1(void) ino_t inumber, inosused, mininos; ufs2_daddr_t i, cgd; u_int8_t *cp; - int c, rebuildcg; + int c, rebuiltcg; badblk = dupblk = lastino = 0; @@ -99,10 +99,14 @@ pass1(void) inumber = c * sblock.fs_ipg; cgbp = cglookup(c); cgp = cgbp->b_un.b_cg; - rebuildcg = 0; - if (!check_cgmagic(c, cgbp, 1)) - rebuildcg = 1; - if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) { + rebuiltcg = 0; + if (!check_cgmagic(c, cgbp, 0)) { + if (!check_cgmagic(c, cgbp, 1)) + cgheader_corrupt = 1; + else + rebuiltcg = 1; + } + if (!rebuiltcg && sblock.fs_magic == FS_UFS2_MAGIC) { inosused = cgp->cg_initediblk; if (inosused > sblock.fs_ipg) { pfatal("Too many initialized inodes (%ju > %d) " @@ -132,7 +136,7 @@ pass1(void) * to find the inodes that are really in use, and then * read only those inodes in from disk. */ - if ((preen || inoopt) && usedsoftdep && !rebuildcg) { + if ((preen || inoopt) && usedsoftdep && !rebuiltcg) { cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT]; for ( ; inosused != 0; cp--) { if (*cp == 0) { @@ -169,7 +173,7 @@ pass1(void) setinodebuf(c, inosused); for (i = 0; i < inosused; i++, inumber++) { if (inumber < UFS_ROOTINO) { - (void)getnextinode(inumber, rebuildcg); + (void)getnextinode(inumber, rebuiltcg); continue; } /* @@ -178,7 +182,7 @@ pass1(void) * We always keep trying until we get to the minimum * valid number for this cylinder group. */ - if (checkinode(inumber, &idesc, rebuildcg) == 0 && + if (checkinode(inumber, &idesc, rebuiltcg) == 0 && i > cgp->cg_initediblk) break; } @@ -189,7 +193,7 @@ pass1(void) * fewer in use. */ mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock)); - if (inoopt && !preen && !rebuildcg && + if (inoopt && !preen && !rebuiltcg && sblock.fs_magic == FS_UFS2_MAGIC && cgp->cg_initediblk > 2 * INOPB(&sblock) && mininos < cgp->cg_initediblk) { @@ -209,7 +213,7 @@ pass1(void) inosused = 0; else inosused = lastino - (c * sblock.fs_ipg); - if (rebuildcg && inosused > cgp->cg_initediblk && + if (rebuiltcg && inosused > cgp->cg_initediblk && sblock.fs_magic == FS_UFS2_MAGIC) { cgp->cg_initediblk = roundup(inosused, INOPB(&sblock)); pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c, @@ -242,7 +246,7 @@ pass1(void) } static int -checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg) +checkinode(ino_t inumber, struct inodesc *idesc, int rebuiltcg) { struct inode ip; union dinode *dp; @@ -252,7 +256,7 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg) intmax_t size, fixsize; int j, ret, offset; - if ((dp = getnextinode(inumber, rebuildcg)) == NULL) { + if ((dp = getnextinode(inumber, rebuiltcg)) == NULL) { pfatal("INVALID INODE"); goto unknown; }