From fa2df9711183d8333b77f915f0f7304e3b408afa Mon Sep 17 00:00:00 2001 From: guido Date: Tue, 8 Oct 1996 14:54:53 +0000 Subject: Fix the case where fsck would not see sparse directories and the kernel would panic. If such a thing is fixed fsck needs a rerun (and bugs the user to do so). Reviewed by: Kirk McKusick --- sbin/fsck_ffs/SMM.doc/0.t | 2 +- sbin/fsck_ffs/SMM.doc/3.t | 13 ++++++++++ sbin/fsck_ffs/fsck.h | 1 + sbin/fsck_ffs/fsck_ffs.8 | 2 ++ sbin/fsck_ffs/inode.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++- sbin/fsck_ffs/main.c | 2 ++ 6 files changed, 78 insertions(+), 2 deletions(-) (limited to 'sbin/fsck_ffs') diff --git a/sbin/fsck_ffs/SMM.doc/0.t b/sbin/fsck_ffs/SMM.doc/0.t index 9de391e..528dd96 100644 --- a/sbin/fsck_ffs/SMM.doc/0.t +++ b/sbin/fsck_ffs/SMM.doc/0.t @@ -94,7 +94,7 @@ Both the program and the interaction between the program and the operator are described. .sp 2 .LP -Revised July 16, 1985 +Revised October 7, 1996 .AE .LP .bp diff --git a/sbin/fsck_ffs/SMM.doc/3.t b/sbin/fsck_ffs/SMM.doc/3.t index 07b5431..bb6f05b 100644 --- a/sbin/fsck_ffs/SMM.doc/3.t +++ b/sbin/fsck_ffs/SMM.doc/3.t @@ -344,6 +344,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 diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 317052f..57cb17a 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -180,6 +180,7 @@ 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 returntosingle; /* return to single user mode */ +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/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8 index 364327f..c8ae6fa 100644 --- a/sbin/fsck_ffs/fsck_ffs.8 +++ b/sbin/fsck_ffs/fsck_ffs.8 @@ -249,6 +249,8 @@ File pointing to unallocated inode. .It Inode number out of range. .It +Holes in directories. +.It Dot or dot-dot not the first two entries of a directory or having the wrong inode number. .El diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c index 1c9f9b6..5adac75 100644 --- a/sbin/fsck_ffs/inode.c +++ b/sbin/fsck_ffs/inode.c @@ -61,6 +61,7 @@ ckinode(dp, idesc) struct dinode dino; quad_t remsize, sizepb; mode_t mode; + char pathbuf[MAXPATHLEN + 1]; if (idesc->id_fix != IGNORE) idesc->id_fix = DONTKNOW; @@ -78,8 +79,26 @@ 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); @@ -97,6 +116,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; @@ -116,6 +153,8 @@ iblock(idesc, ilevel, isize) int i, n, (*func)(), nif; quad_t sizepb; char buf[BUFSIZ]; + char pathbuf[MAXPATHLEN + 1]; + struct dinode *dp; if (idesc->id_type == ADDR) { func = idesc->id_func; @@ -158,6 +197,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 f2ac7d3..363bba7 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -310,6 +310,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; /* -- cgit v1.1