freebsd-dev/sbin/fsck_ffs/gjournal.c
Chuck Silvers 4064755812 fsck_ffs: fix the previous change that skipped pass 5 in some cases
The previous change involved calling check_cgmagic() twice in a row
for the same CG in order to differentiate when the CG was already ok vs.
when the CG was rebuilt, but that doesn't work because the second call
(which was supposed to rebuild the CG) returns 0 (indicating that
the CG was not rebuilt) due to the prevfailcg check causing an early
failure return.  Fix this by moving the rebuild part of check_cgmagic()
out into a separate function which is called by pass1() when it wants to
rebuild a CG.

Fixes: da86e7a20d
Reported by:	pho
Discussed with:	mckusick
Sponsored by:	Netflix
2023-05-03 13:31:32 -07:00

172 lines
5.7 KiB
C

/*-
* SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <string.h>
#include <sys/stat.h>
#include <ufs/ffs/fs.h>
#include "fsck.h"
void
gjournal_check(const char *filesys)
{
struct fs *fs;
struct inode ip;
union dinode *dp;
struct bufarea *cgbp;
struct cg *cgp;
struct inodesc idesc;
uint8_t *inosused;
ino_t cino, ino;
int cg;
fs = &sblock;
/* Are there any unreferenced inodes in this file system? */
if (fs->fs_unrefs == 0) {
//printf("No unreferenced inodes.\n");
sbdirty();
ckfini(1);
return;
}
for (cg = 0; cg < fs->fs_ncg; cg++) {
/* Show progress if requested. */
if (got_siginfo) {
printf("%s: phase j: cyl group %d of %d (%d%%)\n",
cdevname, cg, fs->fs_ncg, cg * 100 / fs->fs_ncg);
got_siginfo = 0;
}
if (got_sigalarm) {
setproctitle("%s pj %d%%", cdevname,
cg * 100 / fs->fs_ncg);
got_sigalarm = 0;
}
cgbp = cglookup(cg);
cgp = cgbp->b_un.b_cg;
if (!check_cgmagic(cg, cgbp)) {
rerun = 1;
ckfini(0);
return;
}
/* Are there any unreferenced inodes in this cylinder group? */
if (cgp->cg_unrefs == 0)
continue;
//printf("Analizing cylinder group %d (count=%d)\n", cg, cgp->cg_unrefs);
/*
* Now go through the list of all inodes in this cylinder group
* to find unreferenced ones.
*/
inosused = cg_inosused(cgp);
for (cino = 0; cino < fs->fs_ipg; cino++) {
ino = fs->fs_ipg * cg + cino;
/* Unallocated? Skip it. */
if (isclr(inosused, cino))
continue;
ginode(ino, &ip);
dp = ip.i_dp;
/* Not a regular file nor directory? Skip it. */
if (!S_ISREG(dp->dp2.di_mode) &&
!S_ISDIR(dp->dp2.di_mode)) {
irelse(&ip);
continue;
}
/* Has reference(s)? Skip it. */
if (dp->dp2.di_nlink > 0) {
irelse(&ip);
continue;
}
/* printf("Clearing inode=%d (size=%jd)\n", ino,
(intmax_t)dp->dp2->di_size); */
/* Deallocate it. */
memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = ADDR;
idesc.id_func = freeblock;
idesc.id_number = ino;
clri(&idesc, "UNREF", 1);
clrbit(inosused, cino);
/* Update position of last used inode. */
if (ino < cgp->cg_irotor)
cgp->cg_irotor = ino;
/* Update statistics. */
cgp->cg_unrefs--;
fs->fs_unrefs--;
/* Zero-fill the inode. */
dp->dp2 = zino.dp2;
/* Write the inode back. */
inodirty(&ip);
irelse(&ip);
cgdirty(cgbp);
if (cgp->cg_unrefs == 0) {
//printf("No more unreferenced inodes in cg=%d.\n", cg);
break;
}
}
/*
* If there are no more unreferenced inodes, there is no need to
* check other cylinder groups.
*/
if (fs->fs_unrefs == 0) {
//printf("No more unreferenced inodes (cg=%d/%d).\n", cg,
// fs->fs_ncg);
break;
}
}
/* Write back updated statistics and super-block. */
sbdirty();
ckfini(1);
}