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
This commit is contained in:
Guido van Rooij 1996-10-08 14:54:53 +00:00
parent 0764dce2cb
commit 47ceb63687
16 changed files with 220 additions and 5 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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;
}

View file

@ -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;
/*

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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;
}

View file

@ -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;
/*

View file

@ -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 */

View file

@ -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

View file

@ -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;
}

View file

@ -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;
/*