From d2404f04709780b94449cd97f168dd12803e266b Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Fri, 15 Jul 2011 15:43:40 +0000 Subject: [PATCH] Break out the pass 5 inode and block map updating into a separate function so that the function can be used by the journaling soft updates recovery. --- sbin/fsck_ffs/fsck.h | 1 + sbin/fsck_ffs/pass5.c | 72 ++++++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 250fc1f9890f..8091d0f9a370 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -395,5 +395,6 @@ void setinodebuf(ino_t); int setup(char *dev); void gjournal_check(const char *filesys); int suj_check(const char *filesys); +void update_maps(struct cg *, struct cg*, int); #endif /* !_FSCK_H_ */ diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c index 01ed8a54052d..b95df7350a2e 100644 --- a/sbin/fsck_ffs/pass5.c +++ b/sbin/fsck_ffs/pass5.c @@ -49,8 +49,8 @@ __FBSDID("$FreeBSD$"); #include "fsck.h" -static void check_maps(u_char *, u_char *, int, ufs2_daddr_t, const char *, int *, int, int); - +static void check_maps(u_char *, u_char *, int, ufs2_daddr_t, const char *, + int *, int, int, int); static void clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end); void @@ -61,7 +61,7 @@ pass5(void) struct fs *fs = &sblock; struct cg *cg = &cgrp; ufs2_daddr_t d, dbase, dmax, start; - int excessdirs, rewritecg = 0; + int rewritecg = 0; struct csum *cs; struct csum_total cstotal; struct inodesc idesc[3]; @@ -333,27 +333,8 @@ pass5(void) memmove(cg, newcg, (size_t)basesize); cgdirty(); } - if (bkgrdflag != 0 || usedsoftdep || debug) { - excessdirs = cg->cg_cs.cs_ndir - newcg->cg_cs.cs_ndir; - if (excessdirs < 0) { - pfatal("LOST %d DIRECTORIES\n", -excessdirs); - excessdirs = 0; - } - if (excessdirs > 0) - check_maps(cg_inosused(newcg), cg_inosused(cg), - inomapsize, - cg->cg_cgx * (ufs2_daddr_t) fs->fs_ipg, - "DIR", - freedirs, 0, excessdirs); - check_maps(cg_inosused(newcg), cg_inosused(cg), - inomapsize, - cg->cg_cgx * (ufs2_daddr_t) fs->fs_ipg, "FILE", - freefiles, excessdirs, fs->fs_ipg); - check_maps(cg_blksfree(cg), cg_blksfree(newcg), - blkmapsize, - cg->cg_cgx * (ufs2_daddr_t) fs->fs_fpg, "FRAG", - freeblks, 0, fs->fs_fpg); - } + if (bkgrdflag != 0 || usedsoftdep || debug) + update_maps(cg, newcg, bkgrdflag); if (cursnapshot == 0 && memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 && dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) { @@ -426,6 +407,40 @@ pass5(void) } } +/* + * Compare the original cylinder group inode and block bitmaps with the + * updated cylinder group inode and block bitmaps. Free inodes and blocks + * that have been added. Complain if any previously freed inodes blocks + * are now allocated. + */ +void +update_maps( + struct cg *oldcg, /* cylinder group of claimed allocations */ + struct cg *newcg, /* cylinder group of determined allocations */ + int usesysctl) /* 1 => use sysctl interface to update maps */ +{ + int inomapsize, excessdirs; + struct fs *fs = &sblock; + + inomapsize = howmany(fs->fs_ipg, CHAR_BIT); + excessdirs = oldcg->cg_cs.cs_ndir - newcg->cg_cs.cs_ndir; + if (excessdirs < 0) { + pfatal("LOST %d DIRECTORIES\n", -excessdirs); + excessdirs = 0; + } + if (excessdirs > 0) + check_maps(cg_inosused(newcg), cg_inosused(oldcg), inomapsize, + oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_ipg, "DIR", freedirs, + 0, excessdirs, usesysctl); + check_maps(cg_inosused(newcg), cg_inosused(oldcg), inomapsize, + oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_ipg, "FILE", freefiles, + excessdirs, fs->fs_ipg, usesysctl); + check_maps(cg_blksfree(oldcg), cg_blksfree(newcg), + howmany(fs->fs_fpg, CHAR_BIT), + oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_fpg, "FRAG", + freeblks, 0, fs->fs_fpg, usesysctl); +} + static void check_maps( u_char *map1, /* map of claimed allocations */ @@ -435,7 +450,8 @@ check_maps( const char *name, /* name of resource found in maps */ int *opcode, /* sysctl opcode to free resource */ int skip, /* number of entries to skip before starting to free */ - int limit) /* limit on number of entries to free */ + int limit, /* limit on number of entries to free */ + int usesysctl) /* 1 => use sysctl interface to update maps */ { # define BUFSIZE 16 char buf[BUFSIZE]; @@ -443,7 +459,7 @@ check_maps( ufs2_daddr_t n, astart, aend, ustart, uend; void (*msg)(const char *fmt, ...); - if (bkgrdflag) + if (usesysctl) msg = pfatal; else msg = pwarn; @@ -506,7 +522,7 @@ check_maps( " MARKED USED\n", "UNALLOCATED", name, ustart, ustart + size - 1); - if (bkgrdflag != 0) { + if (usesysctl != 0) { cmd.value = ustart; cmd.size = size; if (sysctl(opcode, MIBSIZE, 0, 0, @@ -552,7 +568,7 @@ check_maps( " MARKED USED\n", name, ustart, ustart + size - 1); } - if (bkgrdflag != 0) { + if (usesysctl != 0) { cmd.value = ustart; cmd.size = size; if (sysctl(opcode, MIBSIZE, 0, 0, &cmd,