diff --git a/sbin/fsck_ffs/SMM.doc/3.t b/sbin/fsck_ffs/SMM.doc/3.t index 1cacb506b5d8..84372c581dd4 100644 --- a/sbin/fsck_ffs/SMM.doc/3.t +++ b/sbin/fsck_ffs/SMM.doc/3.t @@ -1,4 +1,4 @@ -.\" $NetBSD: 3.t,v 1.3 1996/04/05 01:45:45 cgd Exp $ +.\" $NetBSD: 3.t,v 1.4 1996/10/11 20:15:49 thorpej Exp $ .\" .\" Copyright (c) 1982, 1993 .\" The Regents of the University of California. All rights reserved. @@ -346,6 +346,19 @@ will remove that directory entry. Again, this condition can only arise when there has been a hardware failure. .PP +.I Fsck +also checks for directories with unallocated blocks (holes). +Such directories should never be created. +When found, +.I fsck +will prompt the user to adjust the length of the offending directory +which is done by shortening the size of the directory to the end of the +last allocated block preceeding the hole. +Unfortunately, this means that another Phase 1 run has to be done. +.I Fsck +will remind the user to rerun fsck after repairing a +directory containing an unallocated block. +.PP If a directory entry inode number references outside the inode list, then .I fsck_ffs diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 36ed6b1aac3a..84af0bfb29aa 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -1,4 +1,4 @@ -/* $NetBSD: fsck.h,v 1.12 1996/09/23 16:18:33 christos Exp $ */ +/* $NetBSD: fsck.h,v 1.13 1996/10/11 20:15:46 thorpej Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -181,6 +181,7 @@ char skipclean; /* skip clean file systems if preening */ int fsmodified; /* 1 => write done to file system */ int fsreadfd; /* file descriptor for reading file system */ int fswritefd; /* file descriptor for writing file system */ +int rerun; /* rerun fsck. Only used in non-preen mode */ daddr_t maxfsblock; /* number of blocks in the file system */ char *blockmap; /* ptr to primary blk allocation map */ diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c index ca936079fab6..75876d23b84e 100644 --- a/sbin/fsck_ffs/inode.c +++ b/sbin/fsck_ffs/inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: inode.c,v 1.22 1996/09/27 22:45:13 christos Exp $ */ +/* $NetBSD: inode.c,v 1.23 1996/10/11 20:15:47 thorpej Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)inode.c 8.5 (Berkeley) 2/8/95"; #else -static char rcsid[] = "$NetBSD: inode.c,v 1.22 1996/09/27 22:45:13 christos Exp $"; +static char rcsid[] = "$NetBSD: inode.c,v 1.23 1996/10/11 20:15:47 thorpej Exp $"; #endif #endif /* not lint */ @@ -71,6 +71,7 @@ ckinode(dp, idesc) struct dinode dino; u_int64_t remsize, sizepb; mode_t mode; + char pathbuf[MAXPATHLEN + 1]; if (idesc->id_fix != IGNORE) idesc->id_fix = DONTKNOW; @@ -89,8 +90,25 @@ ckinode(dp, idesc) numfrags(&sblock, fragroundup(&sblock, offset)); else idesc->id_numfrags = sblock.fs_frag; - if (*ap == 0) + if (*ap == 0) { + if (idesc->id_type == DATA && ndb >= 0) { + /* An empty block in a directory XXX */ + getpathname(pathbuf, idesc->id_number, + idesc->id_number); + pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", + pathbuf); + if (reply("ADJUST LENGTH") == 1) { + dp = ginode(idesc->id_number); + dp->di_size = (ap - &dino.di_db[0]) * + sblock.fs_bsize; + printf( + "YOU MUST RERUN FSCK AFTERWARDS\n"); + rerun = 1; + inodirty(); + } + } continue; + } idesc->id_blkno = *ap; if (idesc->id_type == ADDR) ret = (*idesc->id_func)(idesc); @@ -108,6 +126,24 @@ ckinode(dp, idesc) ret = iblock(idesc, n, remsize); if (ret & STOP) return (ret); + } else { + if (idesc->id_type == DATA && remsize > 0) { + /* An empty block in a directory XXX */ + getpathname(pathbuf, idesc->id_number, + idesc->id_number); + pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", + pathbuf); + if (reply("ADJUST LENGTH") == 1) { + dp = ginode(idesc->id_number); + dp->di_size -= remsize; + remsize = 0; + printf( + "YOU MUST RERUN FSCK AFTERWARDS\n"); + rerun = 1; + inodirty(); + break; + } + } } sizepb *= NINDIR(&sblock); remsize -= sizepb; @@ -127,6 +163,8 @@ iblock(idesc, ilevel, isize) int i, n, (*func) __P((struct inodesc *)), nif; u_int64_t sizepb; char buf[BUFSIZ]; + char pathbuf[MAXPATHLEN + 1]; + struct dinode *dp; if (idesc->id_type == ADDR) { func = idesc->id_func; @@ -170,6 +208,25 @@ iblock(idesc, ilevel, isize) bp->b_flags &= ~B_INUSE; return (n); } + } else { + if (idesc->id_type == DATA && isize > 0) { + /* An empty block in a directory XXX */ + getpathname(pathbuf, idesc->id_number, + idesc->id_number); + pfatal("DIRECTORY %s: CONTAINS EMPTY BLOCKS", + pathbuf); + if (reply("ADJUST LENGTH") == 1) { + dp = ginode(idesc->id_number); + dp->di_size -= isize; + isize = 0; + printf( + "YOU MUST RERUN FSCK AFTERWARDS\n"); + rerun = 1; + inodirty(); + bp->b_flags &= ~B_INUSE; + return(STOP); + } + } } isize -= sizepb; } diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index 3af2077720cf..f9d5a6928bbb 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.21 1996/09/27 22:45:14 christos Exp $ */ +/* $NetBSD: main.c,v 1.22 1996/10/11 20:15:48 thorpej Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -43,7 +43,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/23/94"; #else -static char rcsid[] = "$NetBSD: main.c,v 1.21 1996/09/27 22:45:14 christos Exp $"; +static char rcsid[] = "$NetBSD: main.c,v 1.22 1996/10/11 20:15:48 thorpej Exp $"; #endif #endif /* not lint */ @@ -311,6 +311,8 @@ checkfilesys(filesys, mntpt, auxdata, child) return (0); if (!preen) printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); + if (rerun) + printf("\n***** PLEASE RERUN FSCK *****\n"); if (hotroot()) { struct statfs stfs_buf; /*