summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2020-07-13 06:52:54 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2020-07-13 06:52:54 +0000
commitef7784c3e0514af6b97cc2f5399fa35bcbaed2f6 (patch)
tree1e0896c23daf918fd4c54e0a8e2c7380b873b260 /sbin
parent5ff7bae0987afb03f3604e4730901d826dded4ad (diff)
Both phase 1 and phase 5 need the cylinder group meta data, so save those
in phase one to be used in phase 5, unless we're tight on memory. From FreeBSD; ok bket@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/fsck_ffs/fsck.h9
-rw-r--r--sbin/fsck_ffs/inode.c20
-rw-r--r--sbin/fsck_ffs/pass1.c21
-rw-r--r--sbin/fsck_ffs/pass5.c14
-rw-r--r--sbin/fsck_ffs/utilities.c117
5 files changed, 149 insertions, 32 deletions
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 99803042c37..682266c6392 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fsck.h,v 1.32 2018/01/05 09:33:47 otto Exp $ */
+/* $OpenBSD: fsck.h,v 1.33 2020/07/13 06:52:53 otto Exp $ */
/* $NetBSD: fsck.h,v 1.13 1996/10/11 20:15:46 thorpej Exp $ */
/*
@@ -136,7 +136,6 @@ struct bufarea {
struct bufarea bufhead; /* head of list of other blks in filesys */
struct bufarea sblk; /* file system superblock */
struct bufarea asblk; /* alternate file system superblock */
-struct bufarea cgblk; /* cylinder group blocks */
struct bufarea *pdirbp; /* current directory contents */
struct bufarea *pbp; /* current inode block */
struct bufarea *getdatablk(daddr_t, long);
@@ -148,9 +147,7 @@ struct bufarea *getdatablk(daddr_t, long);
(bp)->b_flags = 0;
#define sbdirty() sblk.b_dirty = 1
-#define cgdirty() cgblk.b_dirty = 1
#define sblock (*sblk.b_un.b_fs)
-#define cgrp (*cgblk.b_un.b_cg)
enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE};
@@ -275,9 +272,13 @@ struct ufs2_dinode ufs2_zino;
#define FOUND 0x10
union dinode *ginode(ino_t);
+struct bufarea *cglookup(u_int cg);
struct inoinfo *getinoinfo(ino_t);
void getblk(struct bufarea *, daddr_t, long);
ino_t allocino(ino_t, int);
+void *Malloc(size_t);
+void *Calloc(size_t, size_t);
+void *Reallocarray(void *, size_t, size_t);
int (*info_fn)(char *, size_t);
char *info_filesys;
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
index bdac6546e33..a1c583e4657 100644
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inode.c,v 1.49 2018/09/16 02:43:11 millert Exp $ */
+/* $OpenBSD: inode.c,v 1.50 2020/07/13 06:52:53 otto Exp $ */
/* $NetBSD: inode.c,v 1.23 1996/10/11 20:15:47 thorpej Exp $ */
/*
@@ -370,7 +370,7 @@ setinodebuf(ino_t inum)
partialsize = inobufsize;
}
if (inodebuf == NULL &&
- (inodebuf = malloc((unsigned)inobufsize)) == NULL)
+ (inodebuf = Malloc((unsigned)inobufsize)) == NULL)
errexit("Cannot allocate space for inode buffer\n");
}
@@ -401,7 +401,7 @@ cacheino(union dinode *dp, ino_t inumber)
blks = howmany(DIP(dp, di_size), sblock.fs_bsize);
if (blks > NDADDR)
blks = NDADDR + NIADDR;
- inp = malloc(sizeof(*inp) + (blks ? blks - 1 : 0) * sizeof(daddr_t));
+ inp = Malloc(sizeof(*inp) + (blks ? blks - 1 : 0) * sizeof(daddr_t));
if (inp == NULL)
errexit("cannot allocate memory for inode cache\n");
inpp = &inphead[inumber % numdirs];
@@ -423,10 +423,10 @@ cacheino(union dinode *dp, ino_t inumber)
inp->i_blks[NDADDR + i] = DIP(dp, di_ib[i]);
if (inplast == listmax) {
newlistmax = listmax + 100;
- newinpsort = reallocarray(inpsort,
+ newinpsort = Reallocarray(inpsort,
(unsigned)newlistmax, sizeof(struct inoinfo *));
if (newinpsort == NULL)
- errexit("cannot increase directory list");
+ errexit("cannot increase directory list\n");
inpsort = newinpsort;
listmax = newlistmax;
}
@@ -582,7 +582,8 @@ allocino(ino_t request, int type)
{
ino_t ino;
union dinode *dp;
- struct cg *cgp = &cgrp;
+ struct bufarea *cgbp;
+ struct cg *cgp;
int cg;
time_t t;
struct inostat *info;
@@ -602,7 +603,7 @@ allocino(ino_t request, int type)
unsigned long newalloced, i;
newalloced = MINIMUM(sblock.fs_ipg,
MAXIMUM(2 * inostathead[cg].il_numalloced, 10));
- info = calloc(newalloced, sizeof(struct inostat));
+ info = Calloc(newalloced, sizeof(struct inostat));
if (info == NULL) {
pwarn("cannot alloc %zu bytes to extend inoinfo\n",
sizeof(struct inostat) * newalloced);
@@ -619,7 +620,8 @@ allocino(ino_t request, int type)
inostathead[cg].il_numalloced = newalloced;
info = inoinfo(ino);
}
- getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
+ cgbp = cglookup(cg);
+ cgp = cgbp->b_un.b_cg;
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
@@ -637,7 +639,7 @@ allocino(ino_t request, int type)
default:
return (0);
}
- cgdirty();
+ dirty(cgbp);
dp = ginode(ino);
DIP_SET(dp, di_db[0], allocblk(1));
if (DIP(dp, di_db[0]) == 0) {
diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index 0bc318788c0..7da7087be71 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass1.c,v 1.46 2020/06/20 07:49:04 otto Exp $ */
+/* $OpenBSD: pass1.c,v 1.47 2020/07/13 06:52:53 otto Exp $ */
/* $NetBSD: pass1.c,v 1.16 1996/09/27 22:45:15 christos Exp $ */
/*
@@ -66,6 +66,8 @@ pass1(void)
ino_t inumber, inosused, ninosused;
size_t inospace;
struct inostat *info;
+ struct bufarea *cgbp;
+ struct cg *cgp;
u_int c;
struct inodesc idesc;
daddr_t i, cgd;
@@ -99,9 +101,10 @@ pass1(void)
for (c = 0; c < sblock.fs_ncg; c++) {
inumber = c * sblock.fs_ipg;
setinodebuf(inumber);
- getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize);
+ cgbp = cglookup(c);
+ cgp = cgbp->b_un.b_cg;
if (sblock.fs_magic == FS_UFS2_MAGIC) {
- inosused = cgrp.cg_initediblk;
+ inosused = cgp->cg_initediblk;
if (inosused > sblock.fs_ipg)
inosused = sblock.fs_ipg;
} else
@@ -115,7 +118,7 @@ pass1(void)
* read only those inodes in from disk.
*/
if (preen && usedsoftdep) {
- cp = &cg_inosused(&cgrp)[(inosused - 1) / CHAR_BIT];
+ cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
for ( ; inosused != 0; cp--) {
if (*cp == 0) {
if (inosused > CHAR_BIT)
@@ -140,10 +143,10 @@ pass1(void)
inostathead[c].il_stat = 0;
continue;
}
- info = calloc((unsigned)inosused, sizeof(struct inostat));
+ info = Calloc((unsigned)inosused, sizeof(struct inostat));
inospace = (unsigned)inosused * sizeof(struct inostat);
if (info == NULL)
- errexit("cannot alloc %zu bytes for inoinfo", inospace);
+ errexit("cannot alloc %zu bytes for inoinfo\n", inospace);
inostathead[c].il_stat = info;
/*
* Scan the allocated inodes.
@@ -179,7 +182,7 @@ pass1(void)
struct inostat *ninfo;
size_t ninospace;
- ninfo = reallocarray(info, ninosused, sizeof(*ninfo));
+ ninfo = Reallocarray(info, ninosused, sizeof(*ninfo));
if (ninfo == NULL) {
pfatal("too many inodes %llu, or out of memory\n",
(unsigned long long)ninosused);
@@ -300,7 +303,7 @@ checkinode(ino_t inumber, struct inodesc *idesc)
n_files++;
ILNCOUNT(inumber) = DIP(dp, di_nlink);
if (DIP(dp, di_nlink) <= 0) {
- zlnp = malloc(sizeof *zlnp);
+ zlnp = Malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0) {
@@ -392,7 +395,7 @@ pass1check(struct inodesc *idesc)
}
return (STOP);
}
- new = malloc(sizeof(struct dups));
+ new = Malloc(sizeof(struct dups));
if (new == NULL) {
pfatal("DUP TABLE OVERFLOW.");
if (reply("CONTINUE") == 0) {
diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c
index 9dca5bdce83..c5e357d7c5d 100644
--- a/sbin/fsck_ffs/pass5.c
+++ b/sbin/fsck_ffs/pass5.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass5.c,v 1.49 2020/06/20 07:49:04 otto Exp $ */
+/* $OpenBSD: pass5.c,v 1.50 2020/07/13 06:52:53 otto Exp $ */
/* $NetBSD: pass5.c,v 1.16 1996/09/27 22:45:18 christos Exp $ */
/*
@@ -65,7 +65,6 @@ pass5(void)
u_int c;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
- struct cg *cg = &cgrp;
daddr_t dbase, dmax;
daddr_t d;
long i, k, rewritecg = 0;
@@ -76,6 +75,8 @@ pass5(void)
char buf[MAXBSIZE];
struct cg *newcg = (struct cg *)buf;
struct ocg *ocg = (struct ocg *)buf;
+ struct cg *cg;
+ struct bufarea *cgbp;
memset(newcg, 0, (size_t)fs->fs_cgsize);
if (cvtlevel >= 3) {
@@ -179,7 +180,8 @@ pass5(void)
info_fn = pass5_info;
for (c = 0; c < fs->fs_ncg; c++) {
info_cg = c;
- getblk(&cgblk, cgtod(fs, c), fs->fs_cgsize);
+ cgbp = cglookup(c);
+ cg = cgbp->b_un.b_cg;
if (!cg_chkmagic(cg))
pfatal("CG %u: BAD MAGIC NUMBER\n", c);
dbase = cgbase(fs, c);
@@ -323,13 +325,13 @@ pass5(void)
}
if (rewritecg) {
memcpy(cg, newcg, (size_t)fs->fs_cgsize);
- cgdirty();
+ dirty(cgbp);
continue;
}
if (memcmp(newcg, cg, basesize) &&
dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
memcpy(cg, newcg, (size_t)basesize);
- cgdirty();
+ dirty(cgbp);
}
if (usedsoftdep) {
for (i = 0; i < inomapsize; i++) {
@@ -364,7 +366,7 @@ pass5(void)
dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
memmove(cg_inosused(cg), cg_inosused(newcg),
(size_t)mapsize);
- cgdirty();
+ dirty(cgbp);
}
}
info_fn = NULL;
diff --git a/sbin/fsck_ffs/utilities.c b/sbin/fsck_ffs/utilities.c
index b2f92e4fd36..130e18e4b15 100644
--- a/sbin/fsck_ffs/utilities.c
+++ b/sbin/fsck_ffs/utilities.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: utilities.c,v 1.53 2020/06/20 07:49:04 otto Exp $ */
+/* $OpenBSD: utilities.c,v 1.54 2020/07/13 06:52:53 otto Exp $ */
/* $NetBSD: utilities.c,v 1.18 1996/09/27 22:45:20 christos Exp $ */
/*
@@ -51,7 +51,8 @@
#include "fsck.h"
#include "extern.h"
-long diskreads, totalreads; /* Disk cache statistics */
+long diskreads, totalreads; /* Disk cache statistics */
+static struct bufarea cgblk; /* backup buffer for cylinder group blocks */
static void rwerror(char *, daddr_t);
@@ -176,6 +177,39 @@ bufinit(void)
}
/*
+ * Manage cylinder group buffers.
+ */
+static struct bufarea *cgbufs; /* header for cylinder group cache */
+static int flushtries; /* number of tries to reclaim memory */
+struct bufarea *
+cglookup(u_int cg)
+{
+ struct bufarea *cgbp;
+ struct cg *cgp;
+
+ if (cgbufs == NULL) {
+ cgbufs = calloc(sblock.fs_ncg, sizeof(struct bufarea));
+ if (cgbufs == NULL)
+ errexit("cannot allocate cylinder group buffers");
+ }
+ cgbp = &cgbufs[cg];
+ if (cgbp->b_un.b_cg != NULL)
+ return (cgbp);
+ cgp = NULL;
+ if (flushtries == 0)
+ cgp = malloc((unsigned int)sblock.fs_cgsize);
+ if (cgp == NULL) {
+ getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
+ return (&cgblk);
+ }
+ cgbp->b_un.b_cg = cgp;
+ initbarea(cgbp);
+ getblk(cgbp, cgtod(&sblock, cg), sblock.fs_cgsize);
+ return (cgbp);
+}
+
+
+/*
* Manage a cache of directory blocks.
*/
struct bufarea *
@@ -305,6 +339,15 @@ ckfini(int markclean)
}
if (bufhead.b_size != cnt)
errexit("Panic: lost %d buffers\n", bufhead.b_size - cnt);
+ if (cgbufs != NULL) {
+ for (cnt = 0; cnt < sblock.fs_ncg; cnt++) {
+ if (cgbufs[cnt].b_un.b_cg == NULL)
+ continue;
+ flush(fswritefd, &cgbufs[cnt]);
+ free(cgbufs[cnt].b_un.b_cg);
+ }
+ free(cgbufs);
+ }
pbp = pdirbp = NULL;
if (markclean && (sblock.fs_clean & FS_ISCLEAN) == 0) {
/*
@@ -400,7 +443,8 @@ allocblk(int frags)
{
daddr_t i, baseblk;
int j, k, cg;
- struct cg *cgp = &cgrp;
+ struct bufarea *cgbp;
+ struct cg *cgp;
if (frags <= 0 || frags > sblock.fs_frag)
return (0);
@@ -416,7 +460,8 @@ allocblk(int frags)
continue;
}
cg = dtog(&sblock, i + j);
- getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
+ cgbp = cglookup(cg);
+ cgp = cgbp->b_un.b_cg;
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
baseblk = dtogd(&sblock, i + j);
@@ -615,3 +660,67 @@ catchinfo(int signo)
}
errno = save_errno;
}
+/*
+ * Attempt to flush a cylinder group cache entry.
+ * Return whether the flush was successful.
+ */
+static int
+flushentry(void)
+{
+ struct bufarea *cgbp;
+
+ if (flushtries == sblock.fs_ncg || cgbufs == NULL)
+ return (0);
+ cgbp = &cgbufs[flushtries++];
+ if (cgbp->b_un.b_cg == NULL)
+ return (0);
+ flush(fswritefd, cgbp);
+ free(cgbp->b_un.b_buf);
+ cgbp->b_un.b_buf = NULL;
+ return (1);
+}
+
+/*
+ * Wrapper for malloc() that flushes the cylinder group cache to try
+ * to get space.
+ */
+void *
+Malloc(size_t size)
+{
+ void *retval;
+
+ while ((retval = malloc(size)) == NULL)
+ if (flushentry() == 0)
+ break;
+ return (retval);
+}
+
+/*
+ * Wrapper for calloc() that flushes the cylinder group cache to try
+ * to get space.
+ */
+void*
+Calloc(size_t cnt, size_t size)
+{
+ void *retval;
+
+ while ((retval = calloc(cnt, size)) == NULL)
+ if (flushentry() == 0)
+ break;
+ return (retval);
+}
+
+/*
+ * Wrapper for reallocarray() that flushes the cylinder group cache to try
+ * to get space.
+ */
+void*
+Reallocarray(void *p, size_t cnt, size_t size)
+{
+ void *retval;
+
+ while ((retval = reallocarray(p, cnt, size)) == NULL)
+ if (flushentry() == 0)
+ break;
+ return (retval);
+}