Reviewed by: dyson@freebsd.org (john Dyson), dg@root.com (david greenman)

Submitted by:	Kirk McKusick (mcKusick@mckusick.com)
Obtained from:  WHistle development tree
This commit is contained in:
Julian Elischer 1998-03-08 09:59:44 +00:00
parent fe80c56322
commit b1897c197c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=34266
80 changed files with 2349 additions and 643 deletions

View File

@ -315,12 +315,13 @@ adjust(idesc, lcnt)
pinode(idesc->id_number);
printf(" COUNT %d SHOULD BE %d",
dp->di_nlink, dp->di_nlink - lcnt);
if (preen) {
if (preen || usedsoftdep) {
if (lcnt < 0) {
printf("\n");
pfatal("LINK COUNT INCREASING");
}
printf(" (ADJUSTED)\n");
if (preen)
printf(" (ADJUSTED)\n");
}
if (preen || reply("ADJUST") == 1) {
dp->di_nlink -= lcnt;
@ -406,13 +407,15 @@ linkup(orphan, parentdir)
lostdir = (dp->di_mode & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
if (preen && dp->di_size == 0)
if ((preen || usedsoftdep) && dp->di_size == 0)
return (0);
if (preen)
printf(" (RECONNECTED)\n");
else
if (reply("RECONNECT") == 0)
return (0);
if (parentdir != 0)
lncntp[parentdir]++;
if (lfdir == 0) {
dp = ginode(ROOTINO);
idesc.id_name = lfname;

View File

@ -176,6 +176,8 @@ int cvtlevel; /* convert to newer file system format */
int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
char usedsoftdep; /* just fix soft dependency inconsistencies */
char resolved; /* cleared if unresolved changes => not clean */
char preen; /* just fix normal inconsistencies */
char hotroot; /* checking root device */
char havesb; /* superblock has been read */

View File

@ -559,6 +559,8 @@ allocino(request, type)
{
register ino_t ino;
register struct dinode *dp;
struct cg *cgp = &cgrp;
int cg;
if (request == 0)
request = ROOTINO;
@ -569,9 +571,16 @@ allocino(request, type)
break;
if (ino == maxino)
return (0);
cg = ino_to_cg(&sblock, ino);
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
cgp->cg_cs.cs_nifree--;
switch (type & IFMT) {
case IFDIR:
statemap[ino] = DSTATE;
cgp->cg_cs.cs_ndir++;
break;
case IFREG:
case IFLNK:
@ -580,12 +589,14 @@ allocino(request, type)
default:
return (0);
}
cgdirty();
dp = ginode(ino);
dp->di_db[0] = allocblk((long)1);
if (dp->di_db[0] == 0) {
statemap[ino] = USTATE;
return (0);
}
dp->di_flags = 0;
dp->di_mode = type;
dp->di_atime = time(NULL);
dp->di_mtime = dp->di_ctime = dp->di_atime;

View File

@ -42,7 +42,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
#endif
static const char rcsid[] =
"$Id$";
"$Id: main.c,v 1.12 1997/12/20 22:24:32 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
@ -209,6 +209,11 @@ checkfilesys(filesys, mntpt, auxdata, child)
return (0);
}
/*
* Cleared if any questions answered no. Used to decide if
* the superblock should be marked clean.
*/
resolved = 1;
/*
* 1: scan inodes tallying blocks used
*/
@ -224,7 +229,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
* 1b: locate first references to duplicates, if any
*/
if (duplist) {
if (preen)
if (preen || usedsoftdep)
pfatal("INTERNAL ERROR: dups with -p");
printf("** Phase 1b - Rescan For More DUPS\n");
pass1b();
@ -306,19 +311,20 @@ checkfilesys(filesys, mntpt, auxdata, child)
bwrite(fswritefd, (char *)&sblock,
fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
}
if (!hotroot) {
ckfini(1);
} else {
if (rerun)
resolved = 0;
flags = 0;
if (hotroot) {
struct statfs stfs_buf;
/*
* Check to see if root is mounted read-write.
*/
if (statfs("/", &stfs_buf) == 0)
flags = stfs_buf.f_flags;
else
flags = 0;
ckfini(flags & MNT_RDONLY);
if ((flags & MNT_RDONLY) == 0)
resolved = 0;
}
ckfini(resolved);
free(blockmap);
free(statemap);
free((char *)lncntp);

View File

@ -200,8 +200,10 @@ checkinode(inumber, idesc)
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
} else {
zlnp->zlncnt = inumber;
zlnp->next = zlnhead;
@ -270,8 +272,10 @@ pass1check(idesc)
idesc->id_number);
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
else if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
}
@ -288,15 +292,19 @@ pass1check(idesc)
idesc->id_number);
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
else if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
new = (struct dups *)malloc(sizeof(struct dups));
if (new == NULL) {
pfatal("DUP TABLE OVERFLOW.");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
new->dup = blkno;

View File

@ -66,8 +66,10 @@ pass2()
case USTATE:
pfatal("ROOT INODE UNALLOCATED");
if (reply("ALLOCATE") == 0)
if (reply("ALLOCATE") == 0) {
ckfini(0);
exit(EEXIT);
}
if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
@ -80,8 +82,10 @@ pass2()
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
}
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
break;
case FSTATE:
@ -93,8 +97,10 @@ pass2()
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
}
if (reply("FIX") == 0)
if (reply("FIX") == 0) {
ckfini(0);
exit(EEXIT);
}
dp = ginode(ROOTINO);
dp->di_mode &= ~IFMT;
dp->di_mode |= IFDIR;
@ -139,8 +145,14 @@ pass2()
}
} else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
getpathname(pathbuf, inp->i_number, inp->i_number);
pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d",
pathbuf, inp->i_isize, DIRBLKSIZ);
if (usedsoftdep)
pfatal("%s %s: LENGTH %d NOT MULTIPLE OF %d",
"DIRECTORY", pathbuf, inp->i_isize,
DIRBLKSIZ);
else
pwarn("%s %s: LENGTH %d NOT MULTIPLE OF %d",
"DIRECTORY", pathbuf, inp->i_isize,
DIRBLKSIZ);
if (preen)
printf(" (ADJUSTED)\n");
inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ);
@ -394,7 +406,7 @@ pass2check(idesc)
break;
if (statemap[dirp->d_ino] == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen)
else if (!preen && !usedsoftdep)
errmsg = "ZERO LENGTH DIRECTORY";
else {
n = 1;
@ -423,8 +435,11 @@ pass2check(idesc)
pwarn("%s %s %s\n", pathbuf,
"IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
namebuf);
if (preen)
printf(" (IGNORED)\n");
if (preen) {
printf(" (REMOVED)\n");
n = 1;
break;
}
else if ((n = reply("REMOVE")) == 1)
break;
}

View File

@ -50,11 +50,12 @@ void
pass5()
{
int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
ufs_daddr_t dbase, dmax;
ufs_daddr_t d;
long i, j;
long i, j, k;
struct csum *cs;
struct csum cstotal;
struct inodesc idesc[3];
@ -112,6 +113,8 @@ pass5()
sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
(u_char *)&ocg->cg_iused[0];
blkmapsize = howmany(fs->fs_fpg, NBBY);
inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
ocg->cg_magic = CG_MAGIC;
savednrpos = fs->fs_nrpos;
fs->fs_nrpos = 8;
@ -126,12 +129,12 @@ pass5()
fs->fs_cpg * fs->fs_nrpos * sizeof(short);
newcg->cg_freeoff =
newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
if (fs->fs_contigsumsize <= 0) {
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
} else {
newcg->cg_clustersumoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) -
inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff;
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
if (fs->fs_contigsumsize > 0) {
newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
sizeof(long);
newcg->cg_clustersumoff =
roundup(newcg->cg_clustersumoff, sizeof(long));
@ -148,7 +151,7 @@ pass5()
break;
default:
sumsize = 0; /* keep lint happy */
inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */
errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
fs->fs_postblformat);
}
@ -299,13 +302,6 @@ pass5()
cgdirty();
continue;
}
if (memcmp(cg_inosused(newcg),
cg_inosused(cg), mapsize) != 0 &&
dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
memmove(cg_inosused(cg), cg_inosused(newcg),
(size_t)mapsize);
cgdirty();
}
if ((memcmp(newcg, cg, basesize) != 0 ||
memcmp(&cg_blktot(newcg)[0],
&cg_blktot(cg)[0], sumsize) != 0) &&
@ -315,6 +311,40 @@ pass5()
&cg_blktot(newcg)[0], (size_t)sumsize);
cgdirty();
}
if (usedsoftdep) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];
if ((cg_inosused(cg)[i] & j) == j)
continue;
for (k = 0; k < NBBY; k++) {
if ((j & (1 << k)) == 0)
continue;
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED INODE %d MARKED FREE",
c * fs->fs_ipg + i * 8 + k);
}
}
for (i = 0; i < blkmapsize; i++) {
j = cg_blksfree(cg)[i];
if ((cg_blksfree(newcg)[i] & j) == j)
continue;
for (k = 0; k < NBBY; k++) {
if ((j & (1 << k)) == 0)
continue;
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED FRAG %d MARKED FREE",
c * fs->fs_fpg + i * 8 + k);
}
}
}
if (memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 &&
dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
memmove(cg_inosused(cg), cg_inosused(newcg),
(size_t)mapsize);
cgdirty();
}
}
if (fs->fs_postblformat == FS_42POSTBLFMT)
fs->fs_nrpos = savednrpos;

View File

@ -255,8 +255,10 @@ setup(dev)
fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
size) != 0 && !asked) {
pfatal("BAD SUMMARY INFORMATION");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
asked++;
}
}
@ -311,6 +313,10 @@ setup(dev)
goto badsb;
}
bufinit();
if (sblock.fs_flags & FS_DOSOFTDEP)
usedsoftdep = 1;
else
usedsoftdep = 0;
return (1);
badsb:

View File

@ -87,6 +87,7 @@ reply(question)
printf("\n");
if (!persevere && (nflag || fswritefd < 0)) {
printf("%s? no\n\n", question);
resolved = 0;
return (0);
}
if (yflag || (persevere && nflag)) {
@ -97,13 +98,17 @@ reply(question)
printf("%s? [yn] ", question);
(void) fflush(stdout);
c = getc(stdin);
while (c != '\n' && getc(stdin) != '\n')
if (feof(stdin))
while (c != '\n' && getc(stdin) != '\n') {
if (feof(stdin)) {
resolved = 0;
return (0);
}
}
} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
printf("\n");
if (c == 'y' || c == 'Y')
return (1);
resolved = 0;
return (0);
}
@ -360,7 +365,8 @@ ufs_daddr_t
allocblk(frags)
long frags;
{
register int i, j, k;
int i, j, k, cg, baseblk;
struct cg *cgp = &cgrp;
if (frags <= 0 || frags > sblock.fs_frag)
return (0);
@ -375,9 +381,21 @@ allocblk(frags)
j += k;
continue;
}
for (k = 0; k < frags; k++)
cg = dtog(&sblock, i + j);
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
baseblk = dtogd(&sblock, i + j);
for (k = 0; k < frags; k++) {
setbmap(i + j + k);
clrbit(cg_blksfree(cgp), baseblk + k);
}
n_blks += frags;
if (frags == sblock.fs_frag)
cgp->cg_cs.cs_nbfree--;
else
cgp->cg_cs.cs_nffree -= frags;
cgdirty();
return (i + j);
}
}
@ -545,7 +563,8 @@ dofix(idesc, msg)
/*
* An unexpected inconsistency occured.
* Die if preening, otherwise just print message and continue.
* Die if preening or filesystem is running with soft dependency protocol,
* otherwise just print message and continue.
*/
void
#if __STDC__
@ -565,19 +584,23 @@ pfatal(fmt, va_alist)
if (!preen) {
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
if (usedsoftdep)
(void)fprintf(stderr,
"\nUNEXPECTED SOFTDEP INCONSISTENCY\n");
return;
}
(void)fprintf(stderr, "%s: ", cdevname);
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr,
"\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
cdevname);
"\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n",
cdevname, usedsoftdep ? " SOFTDEP " : " ");
ckfini(0);
exit(EEXIT);
}
/*
* Pwarn just prints a message when not preening,
* or a warning (preceded by filename) when preening.
* Pwarn just prints a message when not preening or running soft dependency
* protocol, or a warning (preceded by filename) when preening.
*/
void
#if __STDC__

View File

@ -315,12 +315,13 @@ adjust(idesc, lcnt)
pinode(idesc->id_number);
printf(" COUNT %d SHOULD BE %d",
dp->di_nlink, dp->di_nlink - lcnt);
if (preen) {
if (preen || usedsoftdep) {
if (lcnt < 0) {
printf("\n");
pfatal("LINK COUNT INCREASING");
}
printf(" (ADJUSTED)\n");
if (preen)
printf(" (ADJUSTED)\n");
}
if (preen || reply("ADJUST") == 1) {
dp->di_nlink -= lcnt;
@ -406,13 +407,15 @@ linkup(orphan, parentdir)
lostdir = (dp->di_mode & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
if (preen && dp->di_size == 0)
if ((preen || usedsoftdep) && dp->di_size == 0)
return (0);
if (preen)
printf(" (RECONNECTED)\n");
else
if (reply("RECONNECT") == 0)
return (0);
if (parentdir != 0)
lncntp[parentdir]++;
if (lfdir == 0) {
dp = ginode(ROOTINO);
idesc.id_name = lfname;

View File

@ -176,6 +176,8 @@ int cvtlevel; /* convert to newer file system format */
int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
char usedsoftdep; /* just fix soft dependency inconsistencies */
char resolved; /* cleared if unresolved changes => not clean */
char preen; /* just fix normal inconsistencies */
char hotroot; /* checking root device */
char havesb; /* superblock has been read */

View File

@ -559,6 +559,8 @@ allocino(request, type)
{
register ino_t ino;
register struct dinode *dp;
struct cg *cgp = &cgrp;
int cg;
if (request == 0)
request = ROOTINO;
@ -569,9 +571,16 @@ allocino(request, type)
break;
if (ino == maxino)
return (0);
cg = ino_to_cg(&sblock, ino);
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
cgp->cg_cs.cs_nifree--;
switch (type & IFMT) {
case IFDIR:
statemap[ino] = DSTATE;
cgp->cg_cs.cs_ndir++;
break;
case IFREG:
case IFLNK:
@ -580,12 +589,14 @@ allocino(request, type)
default:
return (0);
}
cgdirty();
dp = ginode(ino);
dp->di_db[0] = allocblk((long)1);
if (dp->di_db[0] == 0) {
statemap[ino] = USTATE;
return (0);
}
dp->di_flags = 0;
dp->di_mode = type;
dp->di_atime = time(NULL);
dp->di_mtime = dp->di_ctime = dp->di_atime;

View File

@ -42,7 +42,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
#endif
static const char rcsid[] =
"$Id$";
"$Id: main.c,v 1.12 1997/12/20 22:24:32 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
@ -209,6 +209,11 @@ checkfilesys(filesys, mntpt, auxdata, child)
return (0);
}
/*
* Cleared if any questions answered no. Used to decide if
* the superblock should be marked clean.
*/
resolved = 1;
/*
* 1: scan inodes tallying blocks used
*/
@ -224,7 +229,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
* 1b: locate first references to duplicates, if any
*/
if (duplist) {
if (preen)
if (preen || usedsoftdep)
pfatal("INTERNAL ERROR: dups with -p");
printf("** Phase 1b - Rescan For More DUPS\n");
pass1b();
@ -306,19 +311,20 @@ checkfilesys(filesys, mntpt, auxdata, child)
bwrite(fswritefd, (char *)&sblock,
fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
}
if (!hotroot) {
ckfini(1);
} else {
if (rerun)
resolved = 0;
flags = 0;
if (hotroot) {
struct statfs stfs_buf;
/*
* Check to see if root is mounted read-write.
*/
if (statfs("/", &stfs_buf) == 0)
flags = stfs_buf.f_flags;
else
flags = 0;
ckfini(flags & MNT_RDONLY);
if ((flags & MNT_RDONLY) == 0)
resolved = 0;
}
ckfini(resolved);
free(blockmap);
free(statemap);
free((char *)lncntp);

View File

@ -200,8 +200,10 @@ checkinode(inumber, idesc)
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
} else {
zlnp->zlncnt = inumber;
zlnp->next = zlnhead;
@ -270,8 +272,10 @@ pass1check(idesc)
idesc->id_number);
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
else if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
}
@ -288,15 +292,19 @@ pass1check(idesc)
idesc->id_number);
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
else if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
new = (struct dups *)malloc(sizeof(struct dups));
if (new == NULL) {
pfatal("DUP TABLE OVERFLOW.");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
new->dup = blkno;

View File

@ -66,8 +66,10 @@ pass2()
case USTATE:
pfatal("ROOT INODE UNALLOCATED");
if (reply("ALLOCATE") == 0)
if (reply("ALLOCATE") == 0) {
ckfini(0);
exit(EEXIT);
}
if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
@ -80,8 +82,10 @@ pass2()
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
}
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
break;
case FSTATE:
@ -93,8 +97,10 @@ pass2()
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
}
if (reply("FIX") == 0)
if (reply("FIX") == 0) {
ckfini(0);
exit(EEXIT);
}
dp = ginode(ROOTINO);
dp->di_mode &= ~IFMT;
dp->di_mode |= IFDIR;
@ -139,8 +145,14 @@ pass2()
}
} else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
getpathname(pathbuf, inp->i_number, inp->i_number);
pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d",
pathbuf, inp->i_isize, DIRBLKSIZ);
if (usedsoftdep)
pfatal("%s %s: LENGTH %d NOT MULTIPLE OF %d",
"DIRECTORY", pathbuf, inp->i_isize,
DIRBLKSIZ);
else
pwarn("%s %s: LENGTH %d NOT MULTIPLE OF %d",
"DIRECTORY", pathbuf, inp->i_isize,
DIRBLKSIZ);
if (preen)
printf(" (ADJUSTED)\n");
inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ);
@ -394,7 +406,7 @@ pass2check(idesc)
break;
if (statemap[dirp->d_ino] == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen)
else if (!preen && !usedsoftdep)
errmsg = "ZERO LENGTH DIRECTORY";
else {
n = 1;
@ -423,8 +435,11 @@ pass2check(idesc)
pwarn("%s %s %s\n", pathbuf,
"IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
namebuf);
if (preen)
printf(" (IGNORED)\n");
if (preen) {
printf(" (REMOVED)\n");
n = 1;
break;
}
else if ((n = reply("REMOVE")) == 1)
break;
}

View File

@ -50,11 +50,12 @@ void
pass5()
{
int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
ufs_daddr_t dbase, dmax;
ufs_daddr_t d;
long i, j;
long i, j, k;
struct csum *cs;
struct csum cstotal;
struct inodesc idesc[3];
@ -112,6 +113,8 @@ pass5()
sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
(u_char *)&ocg->cg_iused[0];
blkmapsize = howmany(fs->fs_fpg, NBBY);
inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
ocg->cg_magic = CG_MAGIC;
savednrpos = fs->fs_nrpos;
fs->fs_nrpos = 8;
@ -126,12 +129,12 @@ pass5()
fs->fs_cpg * fs->fs_nrpos * sizeof(short);
newcg->cg_freeoff =
newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
if (fs->fs_contigsumsize <= 0) {
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
} else {
newcg->cg_clustersumoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) -
inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff;
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
if (fs->fs_contigsumsize > 0) {
newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
sizeof(long);
newcg->cg_clustersumoff =
roundup(newcg->cg_clustersumoff, sizeof(long));
@ -148,7 +151,7 @@ pass5()
break;
default:
sumsize = 0; /* keep lint happy */
inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */
errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
fs->fs_postblformat);
}
@ -299,13 +302,6 @@ pass5()
cgdirty();
continue;
}
if (memcmp(cg_inosused(newcg),
cg_inosused(cg), mapsize) != 0 &&
dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
memmove(cg_inosused(cg), cg_inosused(newcg),
(size_t)mapsize);
cgdirty();
}
if ((memcmp(newcg, cg, basesize) != 0 ||
memcmp(&cg_blktot(newcg)[0],
&cg_blktot(cg)[0], sumsize) != 0) &&
@ -315,6 +311,40 @@ pass5()
&cg_blktot(newcg)[0], (size_t)sumsize);
cgdirty();
}
if (usedsoftdep) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];
if ((cg_inosused(cg)[i] & j) == j)
continue;
for (k = 0; k < NBBY; k++) {
if ((j & (1 << k)) == 0)
continue;
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED INODE %d MARKED FREE",
c * fs->fs_ipg + i * 8 + k);
}
}
for (i = 0; i < blkmapsize; i++) {
j = cg_blksfree(cg)[i];
if ((cg_blksfree(newcg)[i] & j) == j)
continue;
for (k = 0; k < NBBY; k++) {
if ((j & (1 << k)) == 0)
continue;
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED FRAG %d MARKED FREE",
c * fs->fs_fpg + i * 8 + k);
}
}
}
if (memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 &&
dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
memmove(cg_inosused(cg), cg_inosused(newcg),
(size_t)mapsize);
cgdirty();
}
}
if (fs->fs_postblformat == FS_42POSTBLFMT)
fs->fs_nrpos = savednrpos;

View File

@ -255,8 +255,10 @@ setup(dev)
fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
size) != 0 && !asked) {
pfatal("BAD SUMMARY INFORMATION");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
asked++;
}
}
@ -311,6 +313,10 @@ setup(dev)
goto badsb;
}
bufinit();
if (sblock.fs_flags & FS_DOSOFTDEP)
usedsoftdep = 1;
else
usedsoftdep = 0;
return (1);
badsb:

View File

@ -87,6 +87,7 @@ reply(question)
printf("\n");
if (!persevere && (nflag || fswritefd < 0)) {
printf("%s? no\n\n", question);
resolved = 0;
return (0);
}
if (yflag || (persevere && nflag)) {
@ -97,13 +98,17 @@ reply(question)
printf("%s? [yn] ", question);
(void) fflush(stdout);
c = getc(stdin);
while (c != '\n' && getc(stdin) != '\n')
if (feof(stdin))
while (c != '\n' && getc(stdin) != '\n') {
if (feof(stdin)) {
resolved = 0;
return (0);
}
}
} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
printf("\n");
if (c == 'y' || c == 'Y')
return (1);
resolved = 0;
return (0);
}
@ -360,7 +365,8 @@ ufs_daddr_t
allocblk(frags)
long frags;
{
register int i, j, k;
int i, j, k, cg, baseblk;
struct cg *cgp = &cgrp;
if (frags <= 0 || frags > sblock.fs_frag)
return (0);
@ -375,9 +381,21 @@ allocblk(frags)
j += k;
continue;
}
for (k = 0; k < frags; k++)
cg = dtog(&sblock, i + j);
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
baseblk = dtogd(&sblock, i + j);
for (k = 0; k < frags; k++) {
setbmap(i + j + k);
clrbit(cg_blksfree(cgp), baseblk + k);
}
n_blks += frags;
if (frags == sblock.fs_frag)
cgp->cg_cs.cs_nbfree--;
else
cgp->cg_cs.cs_nffree -= frags;
cgdirty();
return (i + j);
}
}
@ -545,7 +563,8 @@ dofix(idesc, msg)
/*
* An unexpected inconsistency occured.
* Die if preening, otherwise just print message and continue.
* Die if preening or filesystem is running with soft dependency protocol,
* otherwise just print message and continue.
*/
void
#if __STDC__
@ -565,19 +584,23 @@ pfatal(fmt, va_alist)
if (!preen) {
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
if (usedsoftdep)
(void)fprintf(stderr,
"\nUNEXPECTED SOFTDEP INCONSISTENCY\n");
return;
}
(void)fprintf(stderr, "%s: ", cdevname);
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr,
"\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
cdevname);
"\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n",
cdevname, usedsoftdep ? " SOFTDEP " : " ");
ckfini(0);
exit(EEXIT);
}
/*
* Pwarn just prints a message when not preening,
* or a warning (preceded by filename) when preening.
* Pwarn just prints a message when not preening or running soft dependency
* protocol, or a warning (preceded by filename) when preening.
*/
void
#if __STDC__

View File

@ -315,12 +315,13 @@ adjust(idesc, lcnt)
pinode(idesc->id_number);
printf(" COUNT %d SHOULD BE %d",
dp->di_nlink, dp->di_nlink - lcnt);
if (preen) {
if (preen || usedsoftdep) {
if (lcnt < 0) {
printf("\n");
pfatal("LINK COUNT INCREASING");
}
printf(" (ADJUSTED)\n");
if (preen)
printf(" (ADJUSTED)\n");
}
if (preen || reply("ADJUST") == 1) {
dp->di_nlink -= lcnt;
@ -406,13 +407,15 @@ linkup(orphan, parentdir)
lostdir = (dp->di_mode & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
if (preen && dp->di_size == 0)
if ((preen || usedsoftdep) && dp->di_size == 0)
return (0);
if (preen)
printf(" (RECONNECTED)\n");
else
if (reply("RECONNECT") == 0)
return (0);
if (parentdir != 0)
lncntp[parentdir]++;
if (lfdir == 0) {
dp = ginode(ROOTINO);
idesc.id_name = lfname;

View File

@ -176,6 +176,8 @@ int cvtlevel; /* convert to newer file system format */
int doinglevel1; /* converting to new cylinder group format */
int doinglevel2; /* converting to new inode format */
int newinofmt; /* filesystem has new inode format */
char usedsoftdep; /* just fix soft dependency inconsistencies */
char resolved; /* cleared if unresolved changes => not clean */
char preen; /* just fix normal inconsistencies */
char hotroot; /* checking root device */
char havesb; /* superblock has been read */

View File

@ -559,6 +559,8 @@ allocino(request, type)
{
register ino_t ino;
register struct dinode *dp;
struct cg *cgp = &cgrp;
int cg;
if (request == 0)
request = ROOTINO;
@ -569,9 +571,16 @@ allocino(request, type)
break;
if (ino == maxino)
return (0);
cg = ino_to_cg(&sblock, ino);
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
setbit(cg_inosused(cgp), ino % sblock.fs_ipg);
cgp->cg_cs.cs_nifree--;
switch (type & IFMT) {
case IFDIR:
statemap[ino] = DSTATE;
cgp->cg_cs.cs_ndir++;
break;
case IFREG:
case IFLNK:
@ -580,12 +589,14 @@ allocino(request, type)
default:
return (0);
}
cgdirty();
dp = ginode(ino);
dp->di_db[0] = allocblk((long)1);
if (dp->di_db[0] == 0) {
statemap[ino] = USTATE;
return (0);
}
dp->di_flags = 0;
dp->di_mode = type;
dp->di_atime = time(NULL);
dp->di_mtime = dp->di_ctime = dp->di_atime;

View File

@ -42,7 +42,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
#endif
static const char rcsid[] =
"$Id$";
"$Id: main.c,v 1.12 1997/12/20 22:24:32 bde Exp $";
#endif /* not lint */
#include <sys/param.h>
@ -209,6 +209,11 @@ checkfilesys(filesys, mntpt, auxdata, child)
return (0);
}
/*
* Cleared if any questions answered no. Used to decide if
* the superblock should be marked clean.
*/
resolved = 1;
/*
* 1: scan inodes tallying blocks used
*/
@ -224,7 +229,7 @@ checkfilesys(filesys, mntpt, auxdata, child)
* 1b: locate first references to duplicates, if any
*/
if (duplist) {
if (preen)
if (preen || usedsoftdep)
pfatal("INTERNAL ERROR: dups with -p");
printf("** Phase 1b - Rescan For More DUPS\n");
pass1b();
@ -306,19 +311,20 @@ checkfilesys(filesys, mntpt, auxdata, child)
bwrite(fswritefd, (char *)&sblock,
fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE);
}
if (!hotroot) {
ckfini(1);
} else {
if (rerun)
resolved = 0;
flags = 0;
if (hotroot) {
struct statfs stfs_buf;
/*
* Check to see if root is mounted read-write.
*/
if (statfs("/", &stfs_buf) == 0)
flags = stfs_buf.f_flags;
else
flags = 0;
ckfini(flags & MNT_RDONLY);
if ((flags & MNT_RDONLY) == 0)
resolved = 0;
}
ckfini(resolved);
free(blockmap);
free(statemap);
free((char *)lncntp);

View File

@ -200,8 +200,10 @@ checkinode(inumber, idesc)
zlnp = (struct zlncnt *)malloc(sizeof *zlnp);
if (zlnp == NULL) {
pfatal("LINK COUNT TABLE OVERFLOW");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
} else {
zlnp->zlncnt = inumber;
zlnp->next = zlnhead;
@ -270,8 +272,10 @@ pass1check(idesc)
idesc->id_number);
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
else if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
}
@ -288,15 +292,19 @@ pass1check(idesc)
idesc->id_number);
if (preen)
printf(" (SKIPPING)\n");
else if (reply("CONTINUE") == 0)
else if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
new = (struct dups *)malloc(sizeof(struct dups));
if (new == NULL) {
pfatal("DUP TABLE OVERFLOW.");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
return (STOP);
}
new->dup = blkno;

View File

@ -66,8 +66,10 @@ pass2()
case USTATE:
pfatal("ROOT INODE UNALLOCATED");
if (reply("ALLOCATE") == 0)
if (reply("ALLOCATE") == 0) {
ckfini(0);
exit(EEXIT);
}
if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
@ -80,8 +82,10 @@ pass2()
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
}
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
break;
case FSTATE:
@ -93,8 +97,10 @@ pass2()
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
break;
}
if (reply("FIX") == 0)
if (reply("FIX") == 0) {
ckfini(0);
exit(EEXIT);
}
dp = ginode(ROOTINO);
dp->di_mode &= ~IFMT;
dp->di_mode |= IFDIR;
@ -139,8 +145,14 @@ pass2()
}
} else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) {
getpathname(pathbuf, inp->i_number, inp->i_number);
pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d",
pathbuf, inp->i_isize, DIRBLKSIZ);
if (usedsoftdep)
pfatal("%s %s: LENGTH %d NOT MULTIPLE OF %d",
"DIRECTORY", pathbuf, inp->i_isize,
DIRBLKSIZ);
else
pwarn("%s %s: LENGTH %d NOT MULTIPLE OF %d",
"DIRECTORY", pathbuf, inp->i_isize,
DIRBLKSIZ);
if (preen)
printf(" (ADJUSTED)\n");
inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ);
@ -394,7 +406,7 @@ pass2check(idesc)
break;
if (statemap[dirp->d_ino] == FCLEAR)
errmsg = "DUP/BAD";
else if (!preen)
else if (!preen && !usedsoftdep)
errmsg = "ZERO LENGTH DIRECTORY";
else {
n = 1;
@ -423,8 +435,11 @@ pass2check(idesc)
pwarn("%s %s %s\n", pathbuf,
"IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
namebuf);
if (preen)
printf(" (IGNORED)\n");
if (preen) {
printf(" (REMOVED)\n");
n = 1;
break;
}
else if ((n = reply("REMOVE")) == 1)
break;
}

View File

@ -50,11 +50,12 @@ void
pass5()
{
int c, blk, frags, basesize, sumsize, mapsize, savednrpos;
int inomapsize, blkmapsize;
struct fs *fs = &sblock;
struct cg *cg = &cgrp;
ufs_daddr_t dbase, dmax;
ufs_daddr_t d;
long i, j;
long i, j, k;
struct csum *cs;
struct csum cstotal;
struct inodesc idesc[3];
@ -112,6 +113,8 @@ pass5()
sumsize = &ocg->cg_iused[0] - (u_int8_t *)(&ocg->cg_btot[0]);
mapsize = &ocg->cg_free[howmany(fs->fs_fpg, NBBY)] -
(u_char *)&ocg->cg_iused[0];
blkmapsize = howmany(fs->fs_fpg, NBBY);
inomapsize = &ocg->cg_free[0] - (u_char *)&ocg->cg_iused[0];
ocg->cg_magic = CG_MAGIC;
savednrpos = fs->fs_nrpos;
fs->fs_nrpos = 8;
@ -126,12 +129,12 @@ pass5()
fs->fs_cpg * fs->fs_nrpos * sizeof(short);
newcg->cg_freeoff =
newcg->cg_iusedoff + howmany(fs->fs_ipg, NBBY);
if (fs->fs_contigsumsize <= 0) {
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
} else {
newcg->cg_clustersumoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY) -
inomapsize = newcg->cg_freeoff - newcg->cg_iusedoff;
newcg->cg_nextfreeoff = newcg->cg_freeoff +
howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
blkmapsize = newcg->cg_nextfreeoff - newcg->cg_freeoff;
if (fs->fs_contigsumsize > 0) {
newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
sizeof(long);
newcg->cg_clustersumoff =
roundup(newcg->cg_clustersumoff, sizeof(long));
@ -148,7 +151,7 @@ pass5()
break;
default:
sumsize = 0; /* keep lint happy */
inomapsize = blkmapsize = sumsize = 0; /* keep lint happy */
errx(EEXIT, "UNKNOWN ROTATIONAL TABLE FORMAT %d",
fs->fs_postblformat);
}
@ -299,13 +302,6 @@ pass5()
cgdirty();
continue;
}
if (memcmp(cg_inosused(newcg),
cg_inosused(cg), mapsize) != 0 &&
dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
memmove(cg_inosused(cg), cg_inosused(newcg),
(size_t)mapsize);
cgdirty();
}
if ((memcmp(newcg, cg, basesize) != 0 ||
memcmp(&cg_blktot(newcg)[0],
&cg_blktot(cg)[0], sumsize) != 0) &&
@ -315,6 +311,40 @@ pass5()
&cg_blktot(newcg)[0], (size_t)sumsize);
cgdirty();
}
if (usedsoftdep) {
for (i = 0; i < inomapsize; i++) {
j = cg_inosused(newcg)[i];
if ((cg_inosused(cg)[i] & j) == j)
continue;
for (k = 0; k < NBBY; k++) {
if ((j & (1 << k)) == 0)
continue;
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED INODE %d MARKED FREE",
c * fs->fs_ipg + i * 8 + k);
}
}
for (i = 0; i < blkmapsize; i++) {
j = cg_blksfree(cg)[i];
if ((cg_blksfree(newcg)[i] & j) == j)
continue;
for (k = 0; k < NBBY; k++) {
if ((j & (1 << k)) == 0)
continue;
if (cg_inosused(cg)[i] & (1 << k))
continue;
pwarn("ALLOCATED FRAG %d MARKED FREE",
c * fs->fs_fpg + i * 8 + k);
}
}
}
if (memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 &&
dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
memmove(cg_inosused(cg), cg_inosused(newcg),
(size_t)mapsize);
cgdirty();
}
}
if (fs->fs_postblformat == FS_42POSTBLFMT)
fs->fs_nrpos = savednrpos;

View File

@ -255,8 +255,10 @@ setup(dev)
fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
size) != 0 && !asked) {
pfatal("BAD SUMMARY INFORMATION");
if (reply("CONTINUE") == 0)
if (reply("CONTINUE") == 0) {
ckfini(0);
exit(EEXIT);
}
asked++;
}
}
@ -311,6 +313,10 @@ setup(dev)
goto badsb;
}
bufinit();
if (sblock.fs_flags & FS_DOSOFTDEP)
usedsoftdep = 1;
else
usedsoftdep = 0;
return (1);
badsb:

View File

@ -87,6 +87,7 @@ reply(question)
printf("\n");
if (!persevere && (nflag || fswritefd < 0)) {
printf("%s? no\n\n", question);
resolved = 0;
return (0);
}
if (yflag || (persevere && nflag)) {
@ -97,13 +98,17 @@ reply(question)
printf("%s? [yn] ", question);
(void) fflush(stdout);
c = getc(stdin);
while (c != '\n' && getc(stdin) != '\n')
if (feof(stdin))
while (c != '\n' && getc(stdin) != '\n') {
if (feof(stdin)) {
resolved = 0;
return (0);
}
}
} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
printf("\n");
if (c == 'y' || c == 'Y')
return (1);
resolved = 0;
return (0);
}
@ -360,7 +365,8 @@ ufs_daddr_t
allocblk(frags)
long frags;
{
register int i, j, k;
int i, j, k, cg, baseblk;
struct cg *cgp = &cgrp;
if (frags <= 0 || frags > sblock.fs_frag)
return (0);
@ -375,9 +381,21 @@ allocblk(frags)
j += k;
continue;
}
for (k = 0; k < frags; k++)
cg = dtog(&sblock, i + j);
getblk(&cgblk, cgtod(&sblock, cg), sblock.fs_cgsize);
if (!cg_chkmagic(cgp))
pfatal("CG %d: BAD MAGIC NUMBER\n", cg);
baseblk = dtogd(&sblock, i + j);
for (k = 0; k < frags; k++) {
setbmap(i + j + k);
clrbit(cg_blksfree(cgp), baseblk + k);
}
n_blks += frags;
if (frags == sblock.fs_frag)
cgp->cg_cs.cs_nbfree--;
else
cgp->cg_cs.cs_nffree -= frags;
cgdirty();
return (i + j);
}
}
@ -545,7 +563,8 @@ dofix(idesc, msg)
/*
* An unexpected inconsistency occured.
* Die if preening, otherwise just print message and continue.
* Die if preening or filesystem is running with soft dependency protocol,
* otherwise just print message and continue.
*/
void
#if __STDC__
@ -565,19 +584,23 @@ pfatal(fmt, va_alist)
if (!preen) {
(void)vfprintf(stderr, fmt, ap);
va_end(ap);
if (usedsoftdep)
(void)fprintf(stderr,
"\nUNEXPECTED SOFTDEP INCONSISTENCY\n");
return;
}
(void)fprintf(stderr, "%s: ", cdevname);
(void)vfprintf(stderr, fmt, ap);
(void)fprintf(stderr,
"\n%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
cdevname);
"\n%s: UNEXPECTED%sINCONSISTENCY; RUN fsck MANUALLY.\n",
cdevname, usedsoftdep ? " SOFTDEP " : " ");
ckfini(0);
exit(EEXIT);
}
/*
* Pwarn just prints a message when not preening,
* or a warning (preceded by filename) when preening.
* Pwarn just prints a message when not preening or running soft dependency
* protocol, or a warning (preceded by filename) when preening.
*/
void
#if __STDC__

View File

@ -42,7 +42,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95";
#else
static const char rcsid[] =
"$Id: mount.c,v 1.21 1997/11/13 00:28:49 julian Exp $";
"$Id: mount.c,v 1.22 1998/02/13 04:54:27 bde Exp $";
#endif
#endif /* not lint */
@ -98,6 +98,7 @@ static struct opt {
{ MNT_NOCLUSTERR, "noclusterr" },
{ MNT_NOCLUSTERW, "noclusterw" },
{ MNT_SUIDDIR, "suiddir" },
{ MNT_SOFTDEP, "soft-updates" },
{ NULL }
};
@ -495,7 +496,8 @@ prmount(sfp)
else
(void)printf("%d", sfp->f_owner);
}
(void)printf(f ? ")\n" : "\n");
(void)printf("%swrites: sync %d async %d)\n", !f++ ? " (" : ", ",
sfp->f_syncwrites, sfp->f_asyncwrites);
}
struct statfs *
@ -602,6 +604,8 @@ putfsent(ent)
printf(",noclusterr");
if (ent->f_flags & MNT_NOCLUSTERW)
printf(",noclusterw");
if (ent->f_flags & MNT_SUIDDIR)
printf(",suiddir");
if ((fst = getfsspec(ent->f_mntfromname)))
printf("\t%u %u\n", fst->fs_freq, fst->fs_passno);

View File

@ -42,7 +42,7 @@ static const char copyright[] =
static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95";
#else
static const char rcsid[] =
"$Id: mount.c,v 1.21 1997/11/13 00:28:49 julian Exp $";
"$Id: mount.c,v 1.22 1998/02/13 04:54:27 bde Exp $";
#endif
#endif /* not lint */
@ -98,6 +98,7 @@ static struct opt {
{ MNT_NOCLUSTERR, "noclusterr" },
{ MNT_NOCLUSTERW, "noclusterw" },
{ MNT_SUIDDIR, "suiddir" },
{ MNT_SOFTDEP, "soft-updates" },
{ NULL }
};
@ -495,7 +496,8 @@ prmount(sfp)
else
(void)printf("%d", sfp->f_owner);
}
(void)printf(f ? ")\n" : "\n");
(void)printf("%swrites: sync %d async %d)\n", !f++ ? " (" : ", ",
sfp->f_syncwrites, sfp->f_asyncwrites);
}
struct statfs *
@ -602,6 +604,8 @@ putfsent(ent)
printf(",noclusterr");
if (ent->f_flags & MNT_NOCLUSTERW)
printf(",noclusterw");
if (ent->f_flags & MNT_SUIDDIR)
printf(",suiddir");
if ((fst = getfsspec(ent->f_mntfromname)))
printf("\t%u %u\n", fst->fs_freq, fst->fs_passno);

View File

@ -46,6 +46,7 @@
.Op Fl m Ar minfree
.Op Fl p
.Bk -words
.Op Fl n Ar soft_dependency_enabling
.Op Fl o Ar optimize_preference
.Ek
.Op Ar special | Ar filesys

View File

@ -81,7 +81,7 @@ main(argc, argv)
int argc;
char *argv[];
{
char *cp, *special, *name;
char *cp, *special, *name, *action;
struct stat st;
int i;
int Aflag = 0;
@ -182,6 +182,24 @@ main(argc, argv)
warnx(OPTWARN, "space", "<", MINFREE);
continue;
case 'n':
name = "soft updates";
if (argc < 1)
errx(10, "-s: missing %s", name);
argc--, argv++;
if (strcmp(*argv, "enable") == 0) {
sblock.fs_flags |= FS_DOSOFTDEP;
action = "set";
} else if (strcmp(*argv, "disable") == 0) {
sblock.fs_flags &= ~FS_DOSOFTDEP;
action = "cleared";
} else {
errx(10, "bad %s (options are %s)",
name, "`enable' or `disable'");
}
warnx("%s %s", name, action);
continue;
case 'o':
name = "optimization preference";
if (argc < 1)
@ -237,6 +255,7 @@ usage()
fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
fprintf(stderr, "\t-m minimum percentage of free space\n");
fprintf(stderr, "\t-n soft updates (`enable' or `disable')\n");
fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
fprintf(stderr, "\t-p no change - just prints current tuneable settings\n");
exit(2);
@ -261,6 +280,8 @@ getsb(fs, file)
void
printfs()
{
warnx("soft updates: (-n) %s",
(sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled");
warnx("maximum contiguous block count: (-a) %d",
sblock.fs_maxcontig);
warnx("rotational delay between contiguous blocks: (-d) %d ms",

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.412 1998/02/24 22:24:46 phk Exp $
# $Id: LINT,v 1.413 1998/02/27 10:02:41 itojun Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -466,6 +466,13 @@ options NFS_ROOT #NFS usable as root device
# This DEVFS is experimental but seems to work
options DEVFS #devices filesystem
# Allow the FFS to use Softupdates technology.
# To do this you need to fetch the two files
# /sys/ufs/ffs/softdep.h and /sys/ufs/ffs/ffs_softdep.c
# from freebsd.org and understand the licensing restrictions.
#options SOFTUPDATES
# (we can't actually enable it because the files may not be present)
# Make space in the kernel for a MFS root filesystem. Define to the number
# of kilobytes to reserve for the filesystem.
options MFS_ROOT=10

View File

@ -416,6 +416,8 @@ ufs/ffs/ffs_balloc.c optional ffs
ufs/ffs/ffs_balloc.c optional mfs
ufs/ffs/ffs_inode.c optional ffs
ufs/ffs/ffs_inode.c optional mfs
ufs/ffs/ffs_softdep_stub.c optional ffs
ufs/ffs/ffs_softdep.c optional softupdates
ufs/ffs/ffs_subr.c optional ffs
ufs/ffs/ffs_subr.c optional mfs
ufs/ffs/ffs_tables.c optional ffs

View File

@ -1,4 +1,4 @@
# $Id: options,v 1.63 1998/02/27 10:02:37 itojun Exp $
# $Id: options,v 1.64 1998/03/04 10:24:08 dufault Exp $
# Format:
# Option name filename
@ -59,6 +59,12 @@ CD9660
FFS
NFS
# If you are following the conditions in the copyright,
# you can enable soft-updates which will speed up a lot of thigs
# and make the system safer from crashes at the same time.
# otherwise a STUB module will be compiled in.
SOFTUPDATES opt_ffs.h
# The above static dependencies are planned removed, with a
# <filesystem>_ROOT option to control if it usable as root. This list
# allows these options to be present in config files already (though

View File

@ -1,5 +1,7 @@
#undef __FreeBSD__
#define __FreeBSD__ 3
/* $NetBSD: if_de.c,v 1.56 1997/10/20 14:32:46 matt Exp $ */
/* $Id: if_de.c,v 1.79 1998/02/06 12:14:08 eivind Exp $ */
/* $Id: if_de.c,v 1.80 1998/02/20 13:11:50 bde Exp $ */
/*-
* Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
* $Id: cd9660_vfsops.c,v 1.33 1997/12/21 21:40:02 joerg Exp $
* $Id: cd9660_vfsops.c,v 1.34 1998/03/01 22:46:00 msmith Exp $
*/
#include <sys/param.h>
@ -392,7 +392,7 @@ iso_mountfs(devvp, mp, p, argp)
isomp->im_dev = dev;
isomp->im_devvp = devvp;
devvp->v_specflags |= SI_MOUNTEDON;
devvp->v_specmountpoint = mp;
/* Check the Rock Ridge Extention support */
if (!(argp->flags & ISOFSMNT_NORRIP)) {
@ -438,7 +438,7 @@ iso_mountfs(devvp, mp, p, argp)
return 0;
out:
devvp->v_specflags &= ~SI_MOUNTEDON;
devvp->v_specmountpoint = NULL;
if (bp)
brelse(bp);
if (needclose)
@ -489,7 +489,7 @@ cd9660_unmount(mp, mntflags, p)
isomp = VFSTOISOFS(mp);
isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
isomp->im_devvp->v_specmountpoint = NULL;
error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
vrele(isomp->im_devvp);
free((caddr_t)isomp, M_ISOFSMNT);
@ -561,7 +561,8 @@ cd9660_statfs(mp, sbp, p)
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
/* Use the first spare for flags: */
sbp->f_spare[0] = isomp->im_flags;
/* Don't do this!!! XXX */
/* sbp->f_spare[0] = isomp->im_flags; */
return 0;
}

View File

@ -1,4 +1,4 @@
/* $Id: msdosfs_vfsops.c,v 1.28 1998/02/23 16:44:32 ache Exp $ */
/* $Id: msdosfs_vfsops.c,v 1.29 1998/03/01 22:46:27 msmith Exp $ */
/* $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $ */
/*-
@ -772,7 +772,7 @@ mountmsdosfs(devvp, mp, p, argp)
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_flag |= MNT_LOCAL;
devvp->v_specflags |= SI_MOUNTEDON;
devvp->v_specmountpoint = mp;
return 0;
@ -818,7 +818,7 @@ msdosfs_unmount(mp, mntflags, p)
if (error)
return error;
pmp = VFSTOMSDOSFS(mp);
pmp->pm_devvp->v_specflags &= ~SI_MOUNTEDON;
pmp->pm_devvp->v_specmountpoint = NULL;
#ifdef MSDOSFS_DEBUG
{
struct vnode *vp = pmp->pm_devvp;
@ -841,8 +841,9 @@ msdosfs_unmount(mp, mntflags, p)
((u_int *)vp->v_data)[1]);
}
#endif
error = VOP_CLOSE(pmp->pm_devvp, (pmp->pm_flags&MSDOSFSMNT_RONLY) ? FREAD : FREAD | FWRITE,
NOCRED, p);
error = VOP_CLOSE(pmp->pm_devvp,
(pmp->pm_flags&MSDOSFSMNT_RONLY) ? FREAD : FREAD | FWRITE,
NOCRED, p);
vrele(pmp->pm_devvp);
free(pmp->pm_inusemap, M_MSDOSFSFAT);
free(pmp, M_MSDOSFSMNT);
@ -946,9 +947,11 @@ msdosfs_sync(mp, waitfor, cred, p)
simple_lock(&vp->v_interlock);
nvp = vp->v_mntvnodes.le_next;
dep = VTODE(vp);
if (vp->v_type == VNON || ((dep->de_flag &
(DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0)
&& vp->v_dirtyblkhd.lh_first == NULL) {
if (vp->v_type == VNON
|| (waitfor == MNT_LAZY) /* can this happen with msdosfs? */
|| (((dep->de_flag &
(DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0)
&& (vp->v_dirtyblkhd.lh_first == NULL))) {
simple_unlock(&vp->v_interlock);
continue;
}

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
* $Id: spec_vnops.c,v 1.58 1998/03/07 21:35:52 dyson Exp $
* $Id: spec_vnops.c,v 1.59 1998/03/08 08:46:18 dyson Exp $
*/
#include <sys/param.h>
@ -548,8 +548,12 @@ spec_strategy(ap)
struct buf *a_bp;
} */ *ap;
{
struct buf *bp;
(*bdevsw[major(ap->a_bp->b_dev)]->d_strategy)(ap->a_bp);
bp = ap->a_bp;
if ((LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start)
(*bioops.io_start)(bp);
(*bdevsw[major(bp->b_dev)]->d_strategy)(bp);
return (0);
}
@ -633,7 +637,9 @@ spec_close(ap)
* we must invalidate any in core blocks, so that
* we can, for instance, change floppy disks.
*/
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p);
error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0);
VOP_UNLOCK(vp, 0, ap->a_p);
if (error)
return (error);

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)inode.h 8.9 (Berkeley) 5/14/95
* $Id: inode.h,v 1.19 1997/12/05 13:43:47 jkh Exp $
* $Id: inode.h,v 1.20 1998/01/30 11:34:02 phk Exp $
*/
#ifndef _UFS_UFS_INODE_H_
@ -45,6 +45,11 @@
#include <sys/lock.h>
#include <ufs/ufs/dinode.h>
/*
* The size of a logical block number.
*/
typedef long ufs_lbn_t;
/*
* This must agree with the definition in <ufs/ufs/dir.h>.
*/
@ -67,6 +72,7 @@ struct inode {
u_int32_t i_flag; /* flags, see below */
dev_t i_dev; /* Device associated with the inode. */
ino_t i_number; /* The identity of the inode. */
int i_effnlink; /* i_nlink when I/O completes */
union { /* Associated filesystem. */
struct fs *fs; /* FFS */
@ -160,6 +166,9 @@ struct indir {
} \
}
/* Determine if soft dependencies are being done */
#define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & MNT_SOFTDEP)
/* This overlays the fid structure (see mount.h). */
struct ufid {
u_int16_t ufid_len; /* Length of structure. */

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)inode.h 8.9 (Berkeley) 5/14/95
* $Id: inode.h,v 1.19 1997/12/05 13:43:47 jkh Exp $
* $Id: inode.h,v 1.20 1998/01/30 11:34:02 phk Exp $
*/
#ifndef _UFS_UFS_INODE_H_
@ -45,6 +45,11 @@
#include <sys/lock.h>
#include <ufs/ufs/dinode.h>
/*
* The size of a logical block number.
*/
typedef long ufs_lbn_t;
/*
* This must agree with the definition in <ufs/ufs/dir.h>.
*/
@ -67,6 +72,7 @@ struct inode {
u_int32_t i_flag; /* flags, see below */
dev_t i_dev; /* Device associated with the inode. */
ino_t i_number; /* The identity of the inode. */
int i_effnlink; /* i_nlink when I/O completes */
union { /* Associated filesystem. */
struct fs *fs; /* FFS */
@ -160,6 +166,9 @@ struct indir {
} \
}
/* Determine if soft dependencies are being done */
#define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & MNT_SOFTDEP)
/* This overlays the fid structure (see mount.h). */
struct ufid {
u_int16_t ufid_len; /* Length of structure. */

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.412 1998/02/24 22:24:46 phk Exp $
# $Id: LINT,v 1.413 1998/02/27 10:02:41 itojun Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -466,6 +466,13 @@ options NFS_ROOT #NFS usable as root device
# This DEVFS is experimental but seems to work
options DEVFS #devices filesystem
# Allow the FFS to use Softupdates technology.
# To do this you need to fetch the two files
# /sys/ufs/ffs/softdep.h and /sys/ufs/ffs/ffs_softdep.c
# from freebsd.org and understand the licensing restrictions.
#options SOFTUPDATES
# (we can't actually enable it because the files may not be present)
# Make space in the kernel for a MFS root filesystem. Define to the number
# of kilobytes to reserve for the filesystem.
options MFS_ROOT=10

View File

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
# $Id: LINT,v 1.412 1998/02/24 22:24:46 phk Exp $
# $Id: LINT,v 1.413 1998/02/27 10:02:41 itojun Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@ -466,6 +466,13 @@ options NFS_ROOT #NFS usable as root device
# This DEVFS is experimental but seems to work
options DEVFS #devices filesystem
# Allow the FFS to use Softupdates technology.
# To do this you need to fetch the two files
# /sys/ufs/ffs/softdep.h and /sys/ufs/ffs/ffs_softdep.c
# from freebsd.org and understand the licensing restrictions.
#options SOFTUPDATES
# (we can't actually enable it because the files may not be present)
# Make space in the kernel for a MFS root filesystem. Define to the number
# of kilobytes to reserve for the filesystem.
options MFS_ROOT=10

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
* $Id: cd9660_vfsops.c,v 1.33 1997/12/21 21:40:02 joerg Exp $
* $Id: cd9660_vfsops.c,v 1.34 1998/03/01 22:46:00 msmith Exp $
*/
#include <sys/param.h>
@ -392,7 +392,7 @@ iso_mountfs(devvp, mp, p, argp)
isomp->im_dev = dev;
isomp->im_devvp = devvp;
devvp->v_specflags |= SI_MOUNTEDON;
devvp->v_specmountpoint = mp;
/* Check the Rock Ridge Extention support */
if (!(argp->flags & ISOFSMNT_NORRIP)) {
@ -438,7 +438,7 @@ iso_mountfs(devvp, mp, p, argp)
return 0;
out:
devvp->v_specflags &= ~SI_MOUNTEDON;
devvp->v_specmountpoint = NULL;
if (bp)
brelse(bp);
if (needclose)
@ -489,7 +489,7 @@ cd9660_unmount(mp, mntflags, p)
isomp = VFSTOISOFS(mp);
isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
isomp->im_devvp->v_specmountpoint = NULL;
error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
vrele(isomp->im_devvp);
free((caddr_t)isomp, M_ISOFSMNT);
@ -561,7 +561,8 @@ cd9660_statfs(mp, sbp, p)
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
/* Use the first spare for flags: */
sbp->f_spare[0] = isomp->im_flags;
/* Don't do this!!! XXX */
/* sbp->f_spare[0] = isomp->im_flags; */
return 0;
}

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94
* $Id: kern_malloc.c,v 1.43 1998/02/09 06:09:22 eivind Exp $
* $Id: kern_malloc.c,v 1.44 1998/02/23 07:41:23 dyson Exp $
*/
#include "opt_vm.h"
@ -128,7 +128,7 @@ malloc(size, type, flags)
indx = BUCKETINDX(size);
kbp = &bucket[indx];
s = splhigh();
s = splmem();
while (ksp->ks_memuse >= ksp->ks_limit) {
if (flags & M_NOWAIT) {
splx(s);
@ -268,7 +268,7 @@ free(addr, type)
kup = btokup(addr);
size = 1 << kup->ku_indx;
kbp = &bucket[kup->ku_indx];
s = splhigh();
s = splmem();
#ifdef DIAGNOSTIC
/*
* Check for returns of data that do not point to the

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94
* $Id: kern_shutdown.c,v 1.27 1997/11/25 07:07:43 julian Exp $
* $Id: kern_shutdown.c,v 1.28 1998/02/16 23:57:44 eivind Exp $
*/
#include "opt_ddb.h"
@ -217,17 +217,27 @@ boot(howto)
sync(&proc0, NULL);
/*
* With soft updates, some buffers that are
* written will be remarked as dirty until other
* buffers are written.
*/
for (iter = 0; iter < 20; iter++) {
nbusy = 0;
for (bp = &buf[nbuf]; --bp >= buf; ) {
if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) {
nbusy++;
} else if ((bp->b_flags & (B_DELWRI | B_INVAL))
== B_DELWRI) {
/* bawrite(bp);*/
nbusy++;
}
}
if (nbusy == 0)
break;
printf("%d ", nbusy);
DELAY(40000 * iter);
sync(&proc0, NULL);
DELAY(50000 * iter);
}
if (nbusy) {
/*

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)kern_synch.c 8.9 (Berkeley) 5/19/95
* $Id: kern_synch.c,v 1.47 1998/02/25 06:04:46 bde Exp $
* $Id: kern_synch.c,v 1.48 1998/03/04 10:25:55 dufault Exp $
*/
#include "opt_ktrace.h"
@ -230,7 +230,6 @@ schedcpu(arg)
register int s;
register unsigned int newcpu;
wakeup((caddr_t)&lbolt);
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
/*
* Increment time in/out of memory and sleep time
@ -282,6 +281,7 @@ schedcpu(arg)
splx(s);
}
vmmeter();
wakeup((caddr_t)&lbolt);
timeout(schedcpu, (void *)0, hz);
}

View File

@ -11,7 +11,7 @@
* 2. Absolutely no warranty of function or purpose is made by the author
* John S. Dyson.
*
* $Id: vfs_bio.c,v 1.153 1998/03/04 03:17:30 dyson Exp $
* $Id: vfs_bio.c,v 1.154 1998/03/07 21:35:24 dyson Exp $
*/
/*
@ -37,6 +37,7 @@
#include <sys/vnode.h>
#include <sys/vmmeter.h>
#include <sys/lock.h>
#include <miscfs/specfs/specdev.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_prot.h>
@ -53,6 +54,9 @@
static MALLOC_DEFINE(M_BIOBUF, "BIO buffer", "BIO buffer");
struct bio_ops bioops; /* I/O operation notification */
#if 0 /* replaced bu sched_sync */
static void vfs_update __P((void));
static struct proc *updateproc;
static struct kproc_desc up_kp = {
@ -61,6 +65,7 @@ static struct kproc_desc up_kp = {
&updateproc
};
SYSINIT_KT(update, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp)
#endif
struct buf *buf; /* buffer header pool */
struct swqueue bswlist;
@ -179,6 +184,7 @@ bufinit()
bp->b_qindex = QUEUE_EMPTY;
bp->b_vnbufs.le_next = NOLIST;
bp->b_generation = 0;
LIST_INIT(&bp->b_dep);
TAILQ_INSERT_TAIL(&bufqueues[QUEUE_EMPTY], bp, b_freelist);
LIST_INSERT_HEAD(&invalhash, bp, b_hash);
}
@ -362,6 +368,9 @@ int
bwrite(struct buf * bp)
{
int oldflags = bp->b_flags;
struct vnode *vp;
struct mount *mp;
if (bp->b_flags & B_INVAL) {
brelse(bp);
@ -386,6 +395,23 @@ bwrite(struct buf * bp)
curproc->p_stats->p_ru.ru_oublock++;
VOP_STRATEGY(bp);
/*
* Collect statistics on synchronous and asynchronous writes.
* Writes to block devices are charged to their associated
* filesystem (if any).
*/
if ((vp = bp->b_vp) != NULL) {
if (vp->v_type == VBLK)
mp = vp->v_specmountpoint;
else
mp = vp->v_mount;
if (mp != NULL)
if ((oldflags & B_ASYNC) == 0)
mp->mnt_stat.f_syncwrites++;
else
mp->mnt_stat.f_asyncwrites++;
}
if ((oldflags & B_ASYNC) == 0) {
int rtval = biowait(bp);
@ -420,6 +446,8 @@ vfs_bio_need_satisfy(void) {
void
bdwrite(struct buf * bp)
{
int s;
struct vnode *vp;
#if !defined(MAX_PERF)
if ((bp->b_flags & B_BUSY) == 0) {
@ -438,7 +466,9 @@ bdwrite(struct buf * bp)
bp->b_flags &= ~(B_READ|B_RELBUF);
if ((bp->b_flags & B_DELWRI) == 0) {
bp->b_flags |= B_DONE | B_DELWRI;
s = splbio();
reassignbuf(bp, bp->b_vp);
splx(s);
++numdirtybuffers;
}
@ -470,12 +500,45 @@ bdwrite(struct buf * bp)
vfs_clean_pages(bp);
bqrelse(bp);
/*
* XXX The soft dependency code is not prepared to
* have I/O done when a bdwrite is requested. For
* now we just let the write be delayed if it is
* requested by the soft dependency code.
*/
if ((vp = bp->b_vp) &&
(vp->v_type == VBLK && vp->v_specmountpoint &&
(vp->v_specmountpoint->mnt_flag & MNT_SOFTDEP)) ||
(vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)))
return;
if (numdirtybuffers >= hidirtybuffers)
flushdirtybuffers(0, 0);
return;
}
/*
* Same as first half of bdwrite, mark buffer dirty, but do not release it.
* Check how this compares with vfs_setdirty(); XXX [JRE]
*/
void
bdirty(bp)
struct buf *bp;
{
int s;
bp->b_flags &= ~(B_READ|B_RELBUF); /* XXX ??? check this */
if ((bp->b_flags & B_DELWRI) == 0) {
bp->b_flags |= B_DONE | B_DELWRI; /* why done? XXX JRE */
s = splbio();
reassignbuf(bp, bp->b_vp);
splx(s);
++numdirtybuffers;
}
}
/*
* Asynchronous write.
* Start output on a buffer, but do not wait for it to complete.
@ -535,6 +598,8 @@ brelse(struct buf * bp)
if ((bp->b_flags & (B_NOCACHE | B_INVAL | B_ERROR)) ||
(bp->b_bufsize <= 0)) {
bp->b_flags |= B_INVAL;
if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate)
(*bioops.io_deallocate)(bp);
if (bp->b_flags & B_DELWRI)
--numdirtybuffers;
bp->b_flags &= ~(B_DELWRI | B_CACHE);
@ -1065,6 +1130,9 @@ getnewbuf(struct vnode *vp, daddr_t blkno,
crfree(bp->b_wcred);
bp->b_wcred = NOCRED;
}
if (LIST_FIRST(&bp->b_dep) != NULL &&
bioops.io_deallocate)
(*bioops.io_deallocate)(bp);
LIST_REMOVE(bp, b_hash);
LIST_INSERT_HEAD(&invalhash, bp, b_hash);
@ -1083,6 +1151,8 @@ getnewbuf(struct vnode *vp, daddr_t blkno,
bp->b_dirtyoff = bp->b_dirtyend = 0;
bp->b_validoff = bp->b_validend = 0;
bp->b_usecount = 5;
/* Here, not kern_physio.c, is where this should be done*/
LIST_INIT(&bp->b_dep);
maxsize = (maxsize + PAGE_MASK) & ~PAGE_MASK;
@ -1799,6 +1869,9 @@ biodone(register struct buf * bp)
splx(s);
return;
}
if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_complete)
(*bioops.io_complete)(bp);
if (bp->b_flags & B_VMIO) {
int i, resid;
vm_ooffset_t foff;
@ -1944,6 +2017,7 @@ count_lock_queue()
return (count);
}
#if 0 /* not with kirks code */
static int vfs_update_interval = 30;
static void
@ -1970,6 +2044,8 @@ sysctl_kern_updateinterval SYSCTL_HANDLER_ARGS
SYSCTL_PROC(_kern, KERN_UPDATEINTERVAL, update, CTLTYPE_INT|CTLFLAG_RW,
&vfs_update_interval, 0, sysctl_kern_updateinterval, "I", "");
#endif
/*
* This routine is called in lieu of iodone in the case of

View File

@ -33,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_cluster.c 8.7 (Berkeley) 2/13/94
* $Id: vfs_cluster.c,v 1.55 1998/02/06 12:13:30 eivind Exp $
* $Id: vfs_cluster.c,v 1.56 1998/03/07 21:35:28 dyson Exp $
*/
#include "opt_debug_cluster.h"
@ -399,6 +399,9 @@ cluster_rbuild(vp, filesize, lbn, blkno, size, run, fbp)
break;
}
}
/* check for latent dependencies to be handled */
if ((LIST_FIRST(&tbp->b_dep)) != NULL && bioops.io_start)
(*bioops.io_start)(tbp);
TAILQ_INSERT_TAIL(&bp->b_cluster.cluster_head,
tbp, b_cluster.cluster_entry);
for (j = 0; j < tbp->b_npages; j += 1) {
@ -684,7 +687,6 @@ cluster_wbuild(vp, size, start_lbn, len)
(tbp->b_flags & (B_VMIO|B_NEEDCOMMIT));
bp->b_iodone = cluster_callback;
pbgetvp(vp, bp);
for (i = 0; i < len; ++i, ++start_lbn) {
if (i != 0) {
s = splbio();
@ -714,7 +716,10 @@ cluster_wbuild(vp, size, start_lbn, len)
tbp->b_flags &= ~B_DONE;
splx(s);
}
/* check for latent dependencies to be handled */
if ((LIST_FIRST(&tbp->b_dep)) != NULL &&
bioops.io_start)
(*bioops.io_start)(tbp);
if (tbp->b_flags & B_VMIO) {
vm_page_t m;

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
* $Id: vfs_subr.c,v 1.136 1998/03/01 23:07:45 dyson Exp $
* $Id: vfs_subr.c,v 1.137 1998/03/07 21:35:35 dyson Exp $
*/
/*
@ -123,6 +123,19 @@ static struct simplelock spechash_slock;
struct nfs_public nfs_pub; /* publicly exported FS */
static vm_zone_t vnode_zone;
/*
* The workitem queue.
*/
#define SYNCER_MAXDELAY 32
int syncer_maxdelay = SYNCER_MAXDELAY; /* maximum delay time */
time_t syncdelay = 30;
int rushjob; /* number of slots to run ASAP */
static int syncer_delayno = 0;
static long syncer_mask;
LIST_HEAD(synclist, vnode);
static struct synclist *syncer_workitem_pending;
int desiredvnodes;
SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RW, &desiredvnodes, 0, "");
@ -147,6 +160,12 @@ vntblinit()
simple_lock_init(&vnode_free_list_slock);
CIRCLEQ_INIT(&mountlist);
vnode_zone = zinit("VNODE", sizeof (struct vnode), 0, 0, 5);
/*
* Initialize the filesystem syncer.
*/
syncer_workitem_pending = hashinit(syncer_maxdelay, M_VNODE,
&syncer_mask);
syncer_maxdelay = syncer_mask + 1;
}
/*
@ -554,7 +573,7 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
int s, error;
vm_object_t object;
if (flags & V_SAVE) {
if ((flags & V_SAVE) && vp->v_dirtyblkhd.lh_first != NULL) {
if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)))
return (error);
if (vp->v_dirtyblkhd.lh_first != NULL)
@ -688,16 +707,153 @@ brelvp(bp)
/*
* Delete from old vnode list, if on one.
*/
vp = bp->b_vp;
s = splbio();
if (bp->b_vnbufs.le_next != NOLIST)
bufremvn(bp);
if ((vp->v_flag & VONWORKLST) && (LIST_FIRST(&vp->v_dirtyblkhd) == NULL)) {
vp->v_flag &= ~VONWORKLST;
LIST_REMOVE(vp, v_synclist);
}
splx(s);
vp = bp->b_vp;
bp->b_vp = (struct vnode *) 0;
vdrop(vp);
}
/*
* The workitem queue.
*
* It is useful to delay writes of file data and filesystem metadata
* for tens of seconds so that quickly created and deleted files need
* not waste disk bandwidth being created and removed. To realize this,
* we append vnodes to a "workitem" queue. When running with a soft
* updates implementation, most pending metadata dependencies should
* not wait for more than a few seconds. Thus, mounted on block devices
* are delayed only about a half the time that file data is delayed.
* Similarly, directory updates are more critical, so are only delayed
* about a third the time that file data is delayed. Thus, there are
* SYNCER_MAXDELAY queues that are processed round-robin at a rate of
* one each second (driven off the filesystem syner process). The
* syncer_delayno variable indicates the next queue that is to be processed.
* Items that need to be processed soon are placed in this queue:
*
* syncer_workitem_pending[syncer_delayno]
*
* A delay of fifteen seconds is done by placing the request fifteen
* entries later in the queue:
*
* syncer_workitem_pending[(syncer_delayno + 15) & syncer_mask]
*
*/
/*
* Add an item to the syncer work queue.
*/
void
vn_syncer_add_to_worklist(vp, delay)
struct vnode *vp;
int delay;
{
int s, slot;
s = splbio();
if (vp->v_flag & VONWORKLST) {
LIST_REMOVE(vp, v_synclist);
}
if (delay > syncer_maxdelay - 2)
delay = syncer_maxdelay - 2;
slot = (syncer_delayno + delay) & syncer_mask;
LIST_INSERT_HEAD(&syncer_workitem_pending[slot], vp, v_synclist);
vp->v_flag |= VONWORKLST;
splx(s);
}
static void sched_sync __P((void));
static struct proc *updateproc;
static struct kproc_desc up_kp = {
"syncer",
sched_sync,
&updateproc
};
SYSINIT_KT(syncer, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp)
/*
* System filesystem synchronizer daemon.
*/
void
sched_sync(void)
{
struct synclist *slp;
struct vnode *vp;
long starttime;
int s;
struct proc *p = updateproc;
for (;;) {
starttime = time.tv_sec;
/*
* Push files whose dirty time has expired.
*/
s = splbio();
slp = &syncer_workitem_pending[syncer_delayno];
syncer_delayno += 1;
if (syncer_delayno == syncer_maxdelay)
syncer_delayno = 0;
splx(s);
while ((vp = LIST_FIRST(slp)) != NULL) {
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
(void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY, p);
VOP_UNLOCK(vp, 0, p);
if (LIST_FIRST(slp) == vp) {
if (LIST_FIRST(&vp->v_dirtyblkhd) == NULL &&
vp->v_type != VBLK)
panic("sched_sync: fsync failed");
/*
* Move ourselves to the back of the sync list.
*/
LIST_REMOVE(vp, v_synclist);
vn_syncer_add_to_worklist(vp, syncdelay);
}
}
/*
* Do soft update processing.
*/
if (bioops.io_sync)
(*bioops.io_sync)(NULL);
/*
* The variable rushjob allows the kernel to speed up the
* processing of the filesystem syncer process. A rushjob
* value of N tells the filesystem syncer to process the next
* N seconds worth of work on its queue ASAP. Currently rushjob
* is used by the soft update code to speed up the filesystem
* syncer process when the incore state is getting so far
* ahead of the disk that the kernel memory pool is being
* threatened with exhaustion.
*/
if (rushjob > 0) {
rushjob -= 1;
continue;
}
/*
* If it has taken us less than a second to process the
* current work, then wait. Otherwise start right over
* again. We can still lose time if any single round
* takes more than two seconds, but it does not really
* matter as we are just trying to generally pace the
* filesystem activity.
*/
if (time.tv_sec == starttime)
tsleep(&lbolt, PPAUSE, "syncer", 0);
}
}
/*
* Associate a p-buffer with a vnode.
*/
@ -743,6 +899,8 @@ reassignbuf(bp, newvp)
register struct buf *bp;
register struct vnode *newvp;
{
struct buflists *listheadp;
int delay;
int s;
if (newvp == NULL) {
@ -765,18 +923,40 @@ reassignbuf(bp, newvp)
if (bp->b_flags & B_DELWRI) {
struct buf *tbp;
tbp = newvp->v_dirtyblkhd.lh_first;
listheadp = &newvp->v_dirtyblkhd;
if ((newvp->v_flag & VONWORKLST) == 0) {
switch (newvp->v_type) {
case VDIR:
delay = syncdelay / 3;
break;
case VBLK:
if (newvp->v_specmountpoint != NULL) {
delay = syncdelay / 2;
break;
}
/* fall through */
default:
delay = syncdelay;
}
vn_syncer_add_to_worklist(newvp, delay);
}
tbp = listheadp->lh_first;
if (!tbp || (tbp->b_lblkno > bp->b_lblkno)) {
bufinsvn(bp, &newvp->v_dirtyblkhd);
bufinsvn(bp, listheadp);
} else {
while (tbp->b_vnbufs.le_next &&
(tbp->b_vnbufs.le_next->b_lblkno < bp->b_lblkno)) {
(tbp->b_vnbufs.le_next->b_lblkno < bp->b_lblkno)) {
tbp = tbp->b_vnbufs.le_next;
}
LIST_INSERT_AFTER(tbp, bp, b_vnbufs);
}
} else {
bufinsvn(bp, &newvp->v_cleanblkhd);
if ((newvp->v_flag & VONWORKLST) &&
LIST_FIRST(&newvp->v_dirtyblkhd) == NULL) {
newvp->v_flag &= ~VONWORKLST;
LIST_REMOVE(newvp, v_synclist);
}
}
bp->b_vp = newvp;
vhold(bp->b_vp);
@ -863,7 +1043,7 @@ checkalias(nvp, nvp_rdev, mp)
nvp->v_rdev = nvp_rdev;
nvp->v_hashchain = vpp;
nvp->v_specnext = *vpp;
nvp->v_specflags = 0;
nvp->v_specmountpoint = NULL;
simple_unlock(&spechash_slock);
*vpp = nvp;
if (vp != NULLVP) {
@ -920,7 +1100,6 @@ vget(vp, flags, p)
if (VSHOULDBUSY(vp))
vbusy(vp);
if (flags & LK_TYPE_MASK) {
if ((error = vn_lock(vp, flags | LK_INTERLOCK, p)) != 0) {
/*
@ -1066,7 +1245,7 @@ vdrop(vp)
simple_lock(&vp->v_interlock);
if (vp->v_holdcnt <= 0)
panic("holdrele: holdcnt");
panic("vdrop: holdcnt");
vp->v_holdcnt--;
if (VSHOULDFREE(vp))
vfree(vp);
@ -1790,7 +1969,7 @@ vfs_mountedon(vp)
struct vnode *vq;
int error = 0;
if (vp->v_specflags & SI_MOUNTEDON)
if (vp->v_specmountpoint != NULL)
return (EBUSY);
if (vp->v_flag & VALIASED) {
simple_lock(&spechash_slock);
@ -1798,7 +1977,7 @@ vfs_mountedon(vp)
if (vq->v_rdev != vp->v_rdev ||
vq->v_type != vp->v_type)
continue;
if (vq->v_specflags & SI_MOUNTEDON) {
if (vq->v_specmountpoint != NULL) {
error = EBUSY;
break;
}
@ -2326,3 +2505,170 @@ vn_pollgone(vp)
}
simple_unlock(&vp->v_pollinfo.vpi_lock);
}
/*
* Routine to create and manage a filesystem syncer vnode.
*/
#define sync_close ((int (*) __P((struct vop_close_args *)))nullop)
int sync_fsync __P((struct vop_fsync_args *));
int sync_inactive __P((struct vop_inactive_args *));
int sync_reclaim __P((struct vop_reclaim_args *));
#define sync_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
#define sync_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
int sync_print __P((struct vop_print_args *));
#define sync_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
vop_t **sync_vnodeop_p;
struct vnodeopv_entry_desc sync_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *) vop_eopnotsupp },
{ &vop_close_desc, (vop_t *) sync_close }, /* close */
{ &vop_fsync_desc, (vop_t *) sync_fsync }, /* fsync */
{ &vop_inactive_desc, (vop_t *) sync_inactive }, /* inactive */
{ &vop_reclaim_desc, (vop_t *) sync_reclaim }, /* reclaim */
{ &vop_lock_desc, (vop_t *) sync_lock }, /* lock */
{ &vop_unlock_desc, (vop_t *) sync_unlock }, /* unlock */
{ &vop_print_desc, (vop_t *) sync_print }, /* print */
{ &vop_islocked_desc, (vop_t *) sync_islocked }, /* islocked */
{ NULL, NULL }
};
struct vnodeopv_desc sync_vnodeop_opv_desc =
{ &sync_vnodeop_p, sync_vnodeop_entries };
VNODEOP_SET(sync_vnodeop_opv_desc);
/*
* Create a new filesystem syncer vnode for the specified mount point.
*/
int
vfs_allocate_syncvnode(mp)
struct mount *mp;
{
struct vnode *vp;
static long start, incr, next;
int error;
/* Allocate a new vnode */
if ((error = getnewvnode(VT_VFS, mp, sync_vnodeop_p, &vp)) != 0) {
mp->mnt_syncer = NULL;
return (error);
}
vp->v_type = VNON;
/*
* Place the vnode onto the syncer worklist. We attempt to
* scatter them about on the list so that they will go off
* at evenly distributed times even if all the filesystems
* are mounted at once.
*/
next += incr;
if (next == 0 || next > syncer_maxdelay) {
start /= 2;
incr /= 2;
if (start == 0) {
start = syncer_maxdelay / 2;
incr = syncer_maxdelay;
}
next = start;
}
vn_syncer_add_to_worklist(vp, syncdelay > 0 ? next % syncdelay : 0);
mp->mnt_syncer = vp;
return (0);
}
/*
* Do a lazy sync of the filesystem.
*/
int
sync_fsync(ap)
struct vop_fsync_args /* {
struct vnode *a_vp;
struct ucred *a_cred;
int a_waitfor;
struct proc *a_p;
} */ *ap;
{
struct vnode *syncvp = ap->a_vp;
struct mount *mp = syncvp->v_mount;
struct proc *p = ap->a_p;
int asyncflag;
/*
* We only need to do something if this is a lazy evaluation.
*/
if (ap->a_waitfor != MNT_LAZY)
return (0);
/*
* Move ourselves to the back of the sync list.
*/
vn_syncer_add_to_worklist(syncvp, syncdelay);
/*
* Walk the list of vnodes pushing all that are dirty and
* not already on the sync list.
*/
simple_lock(&mountlist_slock);
if (vfs_busy(mp, LK_EXCLUSIVE | LK_NOWAIT, &mountlist_slock, p) != 0)
return (0);
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
VFS_SYNC(mp, MNT_LAZY, ap->a_cred, p);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
vfs_unbusy(mp, p);
return (0);
}
/*
* The syncer vnode is no referenced.
*/
int
sync_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
struct proc *a_p;
} */ *ap;
{
vgone(ap->a_vp);
return (0);
}
/*
* The syncer vnode is no longer needed and is being decommissioned.
*/
int
sync_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
vp->v_mount->mnt_syncer = NULL;
if (vp->v_flag & VONWORKLST) {
LIST_REMOVE(vp, v_synclist);
vp->v_flag &= ~VONWORKLST;
}
return (0);
}
/*
* Print out a syncer vnode.
*/
int
sync_print(ap)
struct vop_print_args /* {
struct vnode *a_vp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
printf("syncer vnode");
if (vp->v_vnlock != NULL)
lockmgr_printinfo(vp->v_vnlock);
printf("\n");
return (0);
}

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
* $Id: vfs_syscalls.c,v 1.93 1998/02/15 04:17:09 dyson Exp $
* $Id: vfs_syscalls.c,v 1.94 1998/03/07 21:35:39 dyson Exp $
*/
/* For 4.3 integer FS ID compatibility */
@ -283,6 +283,14 @@ mount(p, uap)
mp->mnt_flag = flag;
mp->mnt_kern_flag = flag2;
}
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
if (mp->mnt_syncer == NULL)
error = vfs_allocate_syncvnode(mp);
} else {
if (mp->mnt_syncer != NULL)
vrele(mp->mnt_syncer);
mp->mnt_syncer = NULL;
}
vfs_unbusy(mp, p);
return (error);
}
@ -296,6 +304,8 @@ mount(p, uap)
simple_unlock(&mountlist_slock);
checkdirs(vp);
VOP_UNLOCK(vp, 0, p);
if ((mp->mnt_flag & MNT_RDONLY) == 0)
error = vfs_allocate_syncvnode(mp);
vfs_unbusy(mp, p);
if (error = VFS_START(mp, 0, p))
vrele(vp);
@ -431,12 +441,16 @@ dounmount(mp, flags, p)
vfs_msync(mp, MNT_WAIT);
mp->mnt_flag &=~ MNT_ASYNC;
cache_purgevfs(mp); /* remove cache entries for this file sys */
if (mp->mnt_syncer != NULL)
vrele(mp->mnt_syncer);
if (((mp->mnt_flag & MNT_RDONLY) ||
(error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
(flags & MNT_FORCE))
error = VFS_UNMOUNT(mp, flags, p);
simple_lock(&mountlist_slock);
if (error) {
if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
(void) vfs_allocate_syncvnode(mp);
mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
&mountlist_slock, p);
@ -490,9 +504,9 @@ sync(p, uap)
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
VFS_SYNC(mp, MNT_NOWAIT, p != NULL ? p->p_ucred : NOCRED, p);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
VFS_SYNC(mp, MNT_NOWAIT,
((p != NULL) ? p->p_ucred : NOCRED), p);
mp->mnt_flag |= asyncflag;
}
simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
@ -665,10 +679,11 @@ getfsstat(p, uap)
if (sfsp && count < maxcount) {
sp = &mp->mnt_stat;
/*
* If MNT_NOWAIT is specified, do not refresh the
* fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
* If MNT_NOWAIT or MNT_LAZY is specified, do not
* refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
* overrides MNT_WAIT.
*/
if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
(SCARG(uap, flags) & MNT_WAIT)) &&
(error = VFS_STATFS(mp, sp, p))) {
simple_lock(&mountlist_slock);

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95
* $Id: vfs_subr.c,v 1.136 1998/03/01 23:07:45 dyson Exp $
* $Id: vfs_subr.c,v 1.137 1998/03/07 21:35:35 dyson Exp $
*/
/*
@ -123,6 +123,19 @@ static struct simplelock spechash_slock;
struct nfs_public nfs_pub; /* publicly exported FS */
static vm_zone_t vnode_zone;
/*
* The workitem queue.
*/
#define SYNCER_MAXDELAY 32
int syncer_maxdelay = SYNCER_MAXDELAY; /* maximum delay time */
time_t syncdelay = 30;
int rushjob; /* number of slots to run ASAP */
static int syncer_delayno = 0;
static long syncer_mask;
LIST_HEAD(synclist, vnode);
static struct synclist *syncer_workitem_pending;
int desiredvnodes;
SYSCTL_INT(_kern, KERN_MAXVNODES, maxvnodes, CTLFLAG_RW, &desiredvnodes, 0, "");
@ -147,6 +160,12 @@ vntblinit()
simple_lock_init(&vnode_free_list_slock);
CIRCLEQ_INIT(&mountlist);
vnode_zone = zinit("VNODE", sizeof (struct vnode), 0, 0, 5);
/*
* Initialize the filesystem syncer.
*/
syncer_workitem_pending = hashinit(syncer_maxdelay, M_VNODE,
&syncer_mask);
syncer_maxdelay = syncer_mask + 1;
}
/*
@ -554,7 +573,7 @@ vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)
int s, error;
vm_object_t object;
if (flags & V_SAVE) {
if ((flags & V_SAVE) && vp->v_dirtyblkhd.lh_first != NULL) {
if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)))
return (error);
if (vp->v_dirtyblkhd.lh_first != NULL)
@ -688,16 +707,153 @@ brelvp(bp)
/*
* Delete from old vnode list, if on one.
*/
vp = bp->b_vp;
s = splbio();
if (bp->b_vnbufs.le_next != NOLIST)
bufremvn(bp);
if ((vp->v_flag & VONWORKLST) && (LIST_FIRST(&vp->v_dirtyblkhd) == NULL)) {
vp->v_flag &= ~VONWORKLST;
LIST_REMOVE(vp, v_synclist);
}
splx(s);
vp = bp->b_vp;
bp->b_vp = (struct vnode *) 0;
vdrop(vp);
}
/*
* The workitem queue.
*
* It is useful to delay writes of file data and filesystem metadata
* for tens of seconds so that quickly created and deleted files need
* not waste disk bandwidth being created and removed. To realize this,
* we append vnodes to a "workitem" queue. When running with a soft
* updates implementation, most pending metadata dependencies should
* not wait for more than a few seconds. Thus, mounted on block devices
* are delayed only about a half the time that file data is delayed.
* Similarly, directory updates are more critical, so are only delayed
* about a third the time that file data is delayed. Thus, there are
* SYNCER_MAXDELAY queues that are processed round-robin at a rate of
* one each second (driven off the filesystem syner process). The
* syncer_delayno variable indicates the next queue that is to be processed.
* Items that need to be processed soon are placed in this queue:
*
* syncer_workitem_pending[syncer_delayno]
*
* A delay of fifteen seconds is done by placing the request fifteen
* entries later in the queue:
*
* syncer_workitem_pending[(syncer_delayno + 15) & syncer_mask]
*
*/
/*
* Add an item to the syncer work queue.
*/
void
vn_syncer_add_to_worklist(vp, delay)
struct vnode *vp;
int delay;
{
int s, slot;
s = splbio();
if (vp->v_flag & VONWORKLST) {
LIST_REMOVE(vp, v_synclist);
}
if (delay > syncer_maxdelay - 2)
delay = syncer_maxdelay - 2;
slot = (syncer_delayno + delay) & syncer_mask;
LIST_INSERT_HEAD(&syncer_workitem_pending[slot], vp, v_synclist);
vp->v_flag |= VONWORKLST;
splx(s);
}
static void sched_sync __P((void));
static struct proc *updateproc;
static struct kproc_desc up_kp = {
"syncer",
sched_sync,
&updateproc
};
SYSINIT_KT(syncer, SI_SUB_KTHREAD_UPDATE, SI_ORDER_FIRST, kproc_start, &up_kp)
/*
* System filesystem synchronizer daemon.
*/
void
sched_sync(void)
{
struct synclist *slp;
struct vnode *vp;
long starttime;
int s;
struct proc *p = updateproc;
for (;;) {
starttime = time.tv_sec;
/*
* Push files whose dirty time has expired.
*/
s = splbio();
slp = &syncer_workitem_pending[syncer_delayno];
syncer_delayno += 1;
if (syncer_delayno == syncer_maxdelay)
syncer_delayno = 0;
splx(s);
while ((vp = LIST_FIRST(slp)) != NULL) {
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
(void) VOP_FSYNC(vp, p->p_ucred, MNT_LAZY, p);
VOP_UNLOCK(vp, 0, p);
if (LIST_FIRST(slp) == vp) {
if (LIST_FIRST(&vp->v_dirtyblkhd) == NULL &&
vp->v_type != VBLK)
panic("sched_sync: fsync failed");
/*
* Move ourselves to the back of the sync list.
*/
LIST_REMOVE(vp, v_synclist);
vn_syncer_add_to_worklist(vp, syncdelay);
}
}
/*
* Do soft update processing.
*/
if (bioops.io_sync)
(*bioops.io_sync)(NULL);
/*
* The variable rushjob allows the kernel to speed up the
* processing of the filesystem syncer process. A rushjob
* value of N tells the filesystem syncer to process the next
* N seconds worth of work on its queue ASAP. Currently rushjob
* is used by the soft update code to speed up the filesystem
* syncer process when the incore state is getting so far
* ahead of the disk that the kernel memory pool is being
* threatened with exhaustion.
*/
if (rushjob > 0) {
rushjob -= 1;
continue;
}
/*
* If it has taken us less than a second to process the
* current work, then wait. Otherwise start right over
* again. We can still lose time if any single round
* takes more than two seconds, but it does not really
* matter as we are just trying to generally pace the
* filesystem activity.
*/
if (time.tv_sec == starttime)
tsleep(&lbolt, PPAUSE, "syncer", 0);
}
}
/*
* Associate a p-buffer with a vnode.
*/
@ -743,6 +899,8 @@ reassignbuf(bp, newvp)
register struct buf *bp;
register struct vnode *newvp;
{
struct buflists *listheadp;
int delay;
int s;
if (newvp == NULL) {
@ -765,18 +923,40 @@ reassignbuf(bp, newvp)
if (bp->b_flags & B_DELWRI) {
struct buf *tbp;
tbp = newvp->v_dirtyblkhd.lh_first;
listheadp = &newvp->v_dirtyblkhd;
if ((newvp->v_flag & VONWORKLST) == 0) {
switch (newvp->v_type) {
case VDIR:
delay = syncdelay / 3;
break;
case VBLK:
if (newvp->v_specmountpoint != NULL) {
delay = syncdelay / 2;
break;
}
/* fall through */
default:
delay = syncdelay;
}
vn_syncer_add_to_worklist(newvp, delay);
}
tbp = listheadp->lh_first;
if (!tbp || (tbp->b_lblkno > bp->b_lblkno)) {
bufinsvn(bp, &newvp->v_dirtyblkhd);
bufinsvn(bp, listheadp);
} else {
while (tbp->b_vnbufs.le_next &&
(tbp->b_vnbufs.le_next->b_lblkno < bp->b_lblkno)) {
(tbp->b_vnbufs.le_next->b_lblkno < bp->b_lblkno)) {
tbp = tbp->b_vnbufs.le_next;
}
LIST_INSERT_AFTER(tbp, bp, b_vnbufs);
}
} else {
bufinsvn(bp, &newvp->v_cleanblkhd);
if ((newvp->v_flag & VONWORKLST) &&
LIST_FIRST(&newvp->v_dirtyblkhd) == NULL) {
newvp->v_flag &= ~VONWORKLST;
LIST_REMOVE(newvp, v_synclist);
}
}
bp->b_vp = newvp;
vhold(bp->b_vp);
@ -863,7 +1043,7 @@ checkalias(nvp, nvp_rdev, mp)
nvp->v_rdev = nvp_rdev;
nvp->v_hashchain = vpp;
nvp->v_specnext = *vpp;
nvp->v_specflags = 0;
nvp->v_specmountpoint = NULL;
simple_unlock(&spechash_slock);
*vpp = nvp;
if (vp != NULLVP) {
@ -920,7 +1100,6 @@ vget(vp, flags, p)
if (VSHOULDBUSY(vp))
vbusy(vp);
if (flags & LK_TYPE_MASK) {
if ((error = vn_lock(vp, flags | LK_INTERLOCK, p)) != 0) {
/*
@ -1066,7 +1245,7 @@ vdrop(vp)
simple_lock(&vp->v_interlock);
if (vp->v_holdcnt <= 0)
panic("holdrele: holdcnt");
panic("vdrop: holdcnt");
vp->v_holdcnt--;
if (VSHOULDFREE(vp))
vfree(vp);
@ -1790,7 +1969,7 @@ vfs_mountedon(vp)
struct vnode *vq;
int error = 0;
if (vp->v_specflags & SI_MOUNTEDON)
if (vp->v_specmountpoint != NULL)
return (EBUSY);
if (vp->v_flag & VALIASED) {
simple_lock(&spechash_slock);
@ -1798,7 +1977,7 @@ vfs_mountedon(vp)
if (vq->v_rdev != vp->v_rdev ||
vq->v_type != vp->v_type)
continue;
if (vq->v_specflags & SI_MOUNTEDON) {
if (vq->v_specmountpoint != NULL) {
error = EBUSY;
break;
}
@ -2326,3 +2505,170 @@ vn_pollgone(vp)
}
simple_unlock(&vp->v_pollinfo.vpi_lock);
}
/*
* Routine to create and manage a filesystem syncer vnode.
*/
#define sync_close ((int (*) __P((struct vop_close_args *)))nullop)
int sync_fsync __P((struct vop_fsync_args *));
int sync_inactive __P((struct vop_inactive_args *));
int sync_reclaim __P((struct vop_reclaim_args *));
#define sync_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
#define sync_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
int sync_print __P((struct vop_print_args *));
#define sync_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked)
vop_t **sync_vnodeop_p;
struct vnodeopv_entry_desc sync_vnodeop_entries[] = {
{ &vop_default_desc, (vop_t *) vop_eopnotsupp },
{ &vop_close_desc, (vop_t *) sync_close }, /* close */
{ &vop_fsync_desc, (vop_t *) sync_fsync }, /* fsync */
{ &vop_inactive_desc, (vop_t *) sync_inactive }, /* inactive */
{ &vop_reclaim_desc, (vop_t *) sync_reclaim }, /* reclaim */
{ &vop_lock_desc, (vop_t *) sync_lock }, /* lock */
{ &vop_unlock_desc, (vop_t *) sync_unlock }, /* unlock */
{ &vop_print_desc, (vop_t *) sync_print }, /* print */
{ &vop_islocked_desc, (vop_t *) sync_islocked }, /* islocked */
{ NULL, NULL }
};
struct vnodeopv_desc sync_vnodeop_opv_desc =
{ &sync_vnodeop_p, sync_vnodeop_entries };
VNODEOP_SET(sync_vnodeop_opv_desc);
/*
* Create a new filesystem syncer vnode for the specified mount point.
*/
int
vfs_allocate_syncvnode(mp)
struct mount *mp;
{
struct vnode *vp;
static long start, incr, next;
int error;
/* Allocate a new vnode */
if ((error = getnewvnode(VT_VFS, mp, sync_vnodeop_p, &vp)) != 0) {
mp->mnt_syncer = NULL;
return (error);
}
vp->v_type = VNON;
/*
* Place the vnode onto the syncer worklist. We attempt to
* scatter them about on the list so that they will go off
* at evenly distributed times even if all the filesystems
* are mounted at once.
*/
next += incr;
if (next == 0 || next > syncer_maxdelay) {
start /= 2;
incr /= 2;
if (start == 0) {
start = syncer_maxdelay / 2;
incr = syncer_maxdelay;
}
next = start;
}
vn_syncer_add_to_worklist(vp, syncdelay > 0 ? next % syncdelay : 0);
mp->mnt_syncer = vp;
return (0);
}
/*
* Do a lazy sync of the filesystem.
*/
int
sync_fsync(ap)
struct vop_fsync_args /* {
struct vnode *a_vp;
struct ucred *a_cred;
int a_waitfor;
struct proc *a_p;
} */ *ap;
{
struct vnode *syncvp = ap->a_vp;
struct mount *mp = syncvp->v_mount;
struct proc *p = ap->a_p;
int asyncflag;
/*
* We only need to do something if this is a lazy evaluation.
*/
if (ap->a_waitfor != MNT_LAZY)
return (0);
/*
* Move ourselves to the back of the sync list.
*/
vn_syncer_add_to_worklist(syncvp, syncdelay);
/*
* Walk the list of vnodes pushing all that are dirty and
* not already on the sync list.
*/
simple_lock(&mountlist_slock);
if (vfs_busy(mp, LK_EXCLUSIVE | LK_NOWAIT, &mountlist_slock, p) != 0)
return (0);
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
VFS_SYNC(mp, MNT_LAZY, ap->a_cred, p);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
vfs_unbusy(mp, p);
return (0);
}
/*
* The syncer vnode is no referenced.
*/
int
sync_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
struct proc *a_p;
} */ *ap;
{
vgone(ap->a_vp);
return (0);
}
/*
* The syncer vnode is no longer needed and is being decommissioned.
*/
int
sync_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
vp->v_mount->mnt_syncer = NULL;
if (vp->v_flag & VONWORKLST) {
LIST_REMOVE(vp, v_synclist);
vp->v_flag &= ~VONWORKLST;
}
return (0);
}
/*
* Print out a syncer vnode.
*/
int
sync_print(ap)
struct vop_print_args /* {
struct vnode *a_vp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
printf("syncer vnode");
if (vp->v_vnlock != NULL)
lockmgr_printinfo(vp->v_vnlock);
printf("\n");
return (0);
}

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
* $Id: vfs_syscalls.c,v 1.93 1998/02/15 04:17:09 dyson Exp $
* $Id: vfs_syscalls.c,v 1.94 1998/03/07 21:35:39 dyson Exp $
*/
/* For 4.3 integer FS ID compatibility */
@ -283,6 +283,14 @@ mount(p, uap)
mp->mnt_flag = flag;
mp->mnt_kern_flag = flag2;
}
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
if (mp->mnt_syncer == NULL)
error = vfs_allocate_syncvnode(mp);
} else {
if (mp->mnt_syncer != NULL)
vrele(mp->mnt_syncer);
mp->mnt_syncer = NULL;
}
vfs_unbusy(mp, p);
return (error);
}
@ -296,6 +304,8 @@ mount(p, uap)
simple_unlock(&mountlist_slock);
checkdirs(vp);
VOP_UNLOCK(vp, 0, p);
if ((mp->mnt_flag & MNT_RDONLY) == 0)
error = vfs_allocate_syncvnode(mp);
vfs_unbusy(mp, p);
if (error = VFS_START(mp, 0, p))
vrele(vp);
@ -431,12 +441,16 @@ dounmount(mp, flags, p)
vfs_msync(mp, MNT_WAIT);
mp->mnt_flag &=~ MNT_ASYNC;
cache_purgevfs(mp); /* remove cache entries for this file sys */
if (mp->mnt_syncer != NULL)
vrele(mp->mnt_syncer);
if (((mp->mnt_flag & MNT_RDONLY) ||
(error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
(flags & MNT_FORCE))
error = VFS_UNMOUNT(mp, flags, p);
simple_lock(&mountlist_slock);
if (error) {
if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
(void) vfs_allocate_syncvnode(mp);
mp->mnt_kern_flag &= ~MNTK_UNMOUNT;
lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
&mountlist_slock, p);
@ -490,9 +504,9 @@ sync(p, uap)
asyncflag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
vfs_msync(mp, MNT_NOWAIT);
VFS_SYNC(mp, MNT_NOWAIT, p != NULL ? p->p_ucred : NOCRED, p);
if (asyncflag)
mp->mnt_flag |= MNT_ASYNC;
VFS_SYNC(mp, MNT_NOWAIT,
((p != NULL) ? p->p_ucred : NOCRED), p);
mp->mnt_flag |= asyncflag;
}
simple_lock(&mountlist_slock);
nmp = mp->mnt_list.cqe_next;
@ -665,10 +679,11 @@ getfsstat(p, uap)
if (sfsp && count < maxcount) {
sp = &mp->mnt_stat;
/*
* If MNT_NOWAIT is specified, do not refresh the
* fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
* If MNT_NOWAIT or MNT_LAZY is specified, do not
* refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
* overrides MNT_WAIT.
*/
if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||
if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
(SCARG(uap, flags) & MNT_WAIT)) &&
(error = VFS_STATFS(mp, sp, p))) {
simple_lock(&mountlist_slock);

View File

@ -31,7 +31,7 @@
# SUCH DAMAGE.
#
# @(#)vnode_if.src 8.12 (Berkeley) 5/14/95
# $Id: vnode_if.src,v 1.14 1997/10/16 10:48:00 phk Exp $
# $Id: vnode_if.src,v 1.15 1997/10/16 20:32:23 phk Exp $
#
#
@ -428,6 +428,18 @@ vop_advlock {
IN int flags;
};
#
#% balloc vp L L L
#
vop_balloc {
IN struct vnode *vp;
IN off_t startoffset;
IN int size;
IN struct ucred *cred;
IN int flags;
OUT struct buf **bpp;
};
#
#% reallocblks vp L L L
#

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95
* $Id: spec_vnops.c,v 1.58 1998/03/07 21:35:52 dyson Exp $
* $Id: spec_vnops.c,v 1.59 1998/03/08 08:46:18 dyson Exp $
*/
#include <sys/param.h>
@ -548,8 +548,12 @@ spec_strategy(ap)
struct buf *a_bp;
} */ *ap;
{
struct buf *bp;
(*bdevsw[major(ap->a_bp->b_dev)]->d_strategy)(ap->a_bp);
bp = ap->a_bp;
if ((LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start)
(*bioops.io_start)(bp);
(*bdevsw[major(bp->b_dev)]->d_strategy)(bp);
return (0);
}
@ -633,7 +637,9 @@ spec_close(ap)
* we must invalidate any in core blocks, so that
* we can, for instance, change floppy disks.
*/
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p);
error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0);
VOP_UNLOCK(vp, 0, ap->a_p);
if (error)
return (error);

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)specdev.h 8.6 (Berkeley) 5/21/95
* $Id: specdev.h,v 1.12 1997/09/14 02:58:03 peter Exp $
* $Id: specdev.h,v 1.13 1997/10/15 13:23:21 phk Exp $
*/
/*
@ -42,7 +42,7 @@
struct specinfo {
struct vnode **si_hashchain;
struct vnode *si_specnext;
long si_flags;
struct mount *si_mountpoint;
dev_t si_rdev;
};
/*
@ -51,12 +51,7 @@ struct specinfo {
#define v_rdev v_specinfo->si_rdev
#define v_hashchain v_specinfo->si_hashchain
#define v_specnext v_specinfo->si_specnext
#define v_specflags v_specinfo->si_flags
/*
* Flags for specinfo
*/
#define SI_MOUNTEDON 0x0001 /* block special device is mounted on */
#define v_specmountpoint v_specinfo->si_mountpoint
/*
* Special device management

View File

@ -1,4 +1,4 @@
/* $Id: msdosfs_vfsops.c,v 1.28 1998/02/23 16:44:32 ache Exp $ */
/* $Id: msdosfs_vfsops.c,v 1.29 1998/03/01 22:46:27 msmith Exp $ */
/* $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $ */
/*-
@ -772,7 +772,7 @@ mountmsdosfs(devvp, mp, p, argp)
mp->mnt_stat.f_fsid.val[0] = (long)dev;
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_flag |= MNT_LOCAL;
devvp->v_specflags |= SI_MOUNTEDON;
devvp->v_specmountpoint = mp;
return 0;
@ -818,7 +818,7 @@ msdosfs_unmount(mp, mntflags, p)
if (error)
return error;
pmp = VFSTOMSDOSFS(mp);
pmp->pm_devvp->v_specflags &= ~SI_MOUNTEDON;
pmp->pm_devvp->v_specmountpoint = NULL;
#ifdef MSDOSFS_DEBUG
{
struct vnode *vp = pmp->pm_devvp;
@ -841,8 +841,9 @@ msdosfs_unmount(mp, mntflags, p)
((u_int *)vp->v_data)[1]);
}
#endif
error = VOP_CLOSE(pmp->pm_devvp, (pmp->pm_flags&MSDOSFSMNT_RONLY) ? FREAD : FREAD | FWRITE,
NOCRED, p);
error = VOP_CLOSE(pmp->pm_devvp,
(pmp->pm_flags&MSDOSFSMNT_RONLY) ? FREAD : FREAD | FWRITE,
NOCRED, p);
vrele(pmp->pm_devvp);
free(pmp->pm_inusemap, M_MSDOSFSFAT);
free(pmp, M_MSDOSFSMNT);
@ -946,9 +947,11 @@ msdosfs_sync(mp, waitfor, cred, p)
simple_lock(&vp->v_interlock);
nvp = vp->v_mntvnodes.le_next;
dep = VTODE(vp);
if (vp->v_type == VNON || ((dep->de_flag &
(DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0)
&& vp->v_dirtyblkhd.lh_first == NULL) {
if (vp->v_type == VNON
|| (waitfor == MNT_LAZY) /* can this happen with msdosfs? */
|| (((dep->de_flag &
(DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0)
&& (vp->v_dirtyblkhd.lh_first == NULL))) {
simple_unlock(&vp->v_interlock);
continue;
}

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
* $Id: nfs_bio.c,v 1.51 1998/03/06 09:46:43 msmith Exp $
* $Id: nfs_bio.c,v 1.52 1998/03/07 21:36:01 dyson Exp $
*/
@ -1206,10 +1206,14 @@ nfs_doio(bp, cr, p)
*/
if (error == EINTR
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
int s;
bp->b_flags &= ~(B_INVAL|B_NOCACHE);
++numdirtybuffers;
bp->b_flags |= B_DELWRI;
s = splbio();
reassignbuf(bp, vp);
splx(s);
if ((bp->b_flags & B_ASYNC) == 0)
bp->b_flags |= B_EINTR;
} else {

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
* $Id: nfs_vnops.c,v 1.79 1998/03/06 09:46:48 msmith Exp $
* $Id: nfs_vnops.c,v 1.80 1998/03/07 21:36:06 dyson Exp $
*/
@ -2846,9 +2846,11 @@ nfs_flush(vp, cred, waitfor, p, commit)
vfs_bio_need_satisfy();
}
}
s = splbio(); /* XXX check this positionning */
bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
bp->b_dirtyoff = bp->b_dirtyend = 0;
reassignbuf(bp, vp);
splx(s);
biodone(bp);
}
}
@ -2994,6 +2996,7 @@ nfs_writebp(bp, force)
register struct buf *bp;
int force;
{
int s;
register int oldflags = bp->b_flags, retv = 1;
off_t off;
@ -3008,6 +3011,7 @@ nfs_writebp(bp, force)
if (needsbuffer)
vfs_bio_need_satisfy();
}
s = splbio(); /* XXX check if needed */
bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) {
@ -3016,6 +3020,7 @@ nfs_writebp(bp, force)
bp->b_vp->v_numoutput++;
curproc->p_stats->p_ru.ru_oublock++;
splx(s);
/*
* If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
@ -3046,7 +3051,9 @@ nfs_writebp(bp, force)
int rtval = biowait(bp);
if (oldflags & B_DELWRI) {
s = splbio();
reassignbuf(bp, bp->b_vp);
splx(s);
}
brelse(bp);

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95
* $Id: nfs_bio.c,v 1.51 1998/03/06 09:46:43 msmith Exp $
* $Id: nfs_bio.c,v 1.52 1998/03/07 21:36:01 dyson Exp $
*/
@ -1206,10 +1206,14 @@ nfs_doio(bp, cr, p)
*/
if (error == EINTR
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
int s;
bp->b_flags &= ~(B_INVAL|B_NOCACHE);
++numdirtybuffers;
bp->b_flags |= B_DELWRI;
s = splbio();
reassignbuf(bp, vp);
splx(s);
if ((bp->b_flags & B_ASYNC) == 0)
bp->b_flags |= B_EINTR;
} else {

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
* $Id: nfs_vnops.c,v 1.79 1998/03/06 09:46:48 msmith Exp $
* $Id: nfs_vnops.c,v 1.80 1998/03/07 21:36:06 dyson Exp $
*/
@ -2846,9 +2846,11 @@ nfs_flush(vp, cred, waitfor, p, commit)
vfs_bio_need_satisfy();
}
}
s = splbio(); /* XXX check this positionning */
bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
bp->b_dirtyoff = bp->b_dirtyend = 0;
reassignbuf(bp, vp);
splx(s);
biodone(bp);
}
}
@ -2994,6 +2996,7 @@ nfs_writebp(bp, force)
register struct buf *bp;
int force;
{
int s;
register int oldflags = bp->b_flags, retv = 1;
off_t off;
@ -3008,6 +3011,7 @@ nfs_writebp(bp, force)
if (needsbuffer)
vfs_bio_need_satisfy();
}
s = splbio(); /* XXX check if needed */
bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) {
@ -3016,6 +3020,7 @@ nfs_writebp(bp, force)
bp->b_vp->v_numoutput++;
curproc->p_stats->p_ru.ru_oublock++;
splx(s);
/*
* If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
@ -3046,7 +3051,9 @@ nfs_writebp(bp, force)
int rtval = biowait(bp);
if (oldflags & B_DELWRI) {
s = splbio();
reassignbuf(bp, bp->b_vp);
splx(s);
}
brelse(bp);

View File

@ -1,5 +1,7 @@
#undef __FreeBSD__
#define __FreeBSD__ 3
/* $NetBSD: if_de.c,v 1.56 1997/10/20 14:32:46 matt Exp $ */
/* $Id: if_de.c,v 1.79 1998/02/06 12:14:08 eivind Exp $ */
/* $Id: if_de.c,v 1.80 1998/02/20 13:11:50 bde Exp $ */
/*-
* Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)buf.h 8.9 (Berkeley) 3/30/95
* $Id: buf.h,v 1.45 1998/01/22 17:30:10 dyson Exp $
* $Id: buf.h,v 1.46 1998/03/07 21:36:20 dyson Exp $
*/
#ifndef _SYS_BUF_H_
@ -47,6 +47,24 @@
#define NOLIST ((struct buf *)0x87654321)
struct buf;
struct mount;
/*
* To avoid including <ufs/ffs/softdep.h>
*/
LIST_HEAD(workhead, worklist);
/*
* These are currently used only by the soft dependency code, hence
* are stored once in a global variable. If other subsystems wanted
* to use these hooks, a pointer to a set of bio_ops could be added
* to each buffer.
*/
extern struct bio_ops {
void (*io_start) __P((struct buf *));
void (*io_complete) __P((struct buf *));
void (*io_deallocate) __P((struct buf *));
int (*io_sync) __P((struct mount *));
} bioops;
struct iodone_chain {
long ic_prev_flags;
@ -104,6 +122,7 @@ struct buf {
} b_cluster;
struct vm_page *b_pages[btoc(MAXPHYS)];
int b_npages;
struct workhead b_dep; /* List of filesystem dependencies. */
};
/*
@ -264,6 +283,7 @@ int breadn __P((struct vnode *, daddr_t, int, daddr_t *, int *, int,
int bwrite __P((struct buf *));
void bdwrite __P((struct buf *));
void bawrite __P((struct buf *));
void bdirty __P((struct buf *));
int bowrite __P((struct buf *));
void brelse __P((struct buf *));
void bqrelse __P((struct buf *));

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)buf.h 8.9 (Berkeley) 3/30/95
* $Id: buf.h,v 1.45 1998/01/22 17:30:10 dyson Exp $
* $Id: buf.h,v 1.46 1998/03/07 21:36:20 dyson Exp $
*/
#ifndef _SYS_BUF_H_
@ -47,6 +47,24 @@
#define NOLIST ((struct buf *)0x87654321)
struct buf;
struct mount;
/*
* To avoid including <ufs/ffs/softdep.h>
*/
LIST_HEAD(workhead, worklist);
/*
* These are currently used only by the soft dependency code, hence
* are stored once in a global variable. If other subsystems wanted
* to use these hooks, a pointer to a set of bio_ops could be added
* to each buffer.
*/
extern struct bio_ops {
void (*io_start) __P((struct buf *));
void (*io_complete) __P((struct buf *));
void (*io_deallocate) __P((struct buf *));
int (*io_sync) __P((struct mount *));
} bioops;
struct iodone_chain {
long ic_prev_flags;
@ -104,6 +122,7 @@ struct buf {
} b_cluster;
struct vm_page *b_pages[btoc(MAXPHYS)];
int b_npages;
struct workhead b_dep; /* List of filesystem dependencies. */
};
/*
@ -264,6 +283,7 @@ int breadn __P((struct vnode *, daddr_t, int, daddr_t *, int *, int,
int bwrite __P((struct buf *));
void bdwrite __P((struct buf *));
void bawrite __P((struct buf *));
void bdirty __P((struct buf *));
int bowrite __P((struct buf *));
void brelse __P((struct buf *));
void bqrelse __P((struct buf *));

View File

@ -31,12 +31,14 @@
* SUCH DAMAGE.
*
* @(#)malloc.h 8.5 (Berkeley) 5/3/95
* $Id: malloc.h,v 1.35 1997/12/05 19:14:36 bde Exp $
* $Id: malloc.h,v 1.36 1997/12/27 09:42:03 bde Exp $
*/
#ifndef _SYS_MALLOC_H_
#define _SYS_MALLOC_H_
#define splmem splhigh
#define KMEMSTATS
/*
@ -165,7 +167,7 @@ struct kmembuckets {
#else /* do not collect statistics */
#define MALLOC(space, cast, size, type, flags) do { \
register struct kmembuckets *kbp = &bucket[BUCKETINDX(size)]; \
long s = splimp(); \
long s = splmem(); \
if (kbp->kb_next == NULL) { \
(space) = (cast)malloc((u_long)(size), type, flags); \
} else { \
@ -178,7 +180,7 @@ struct kmembuckets {
#define FREE(addr, type) do { \
register struct kmembuckets *kbp; \
register struct kmemusage *kup = btokup(addr); \
long s = splimp(); \
long s = splmem(); \
if (1 << kup->ku_indx > MAXALLOCSAVE) { \
free((addr), type); \
} else { \

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)mount.h 8.21 (Berkeley) 5/20/95
* $Id: mount.h,v 1.56 1998/02/22 01:17:51 jkh Exp $
* $Id: mount.h,v 1.57 1998/03/01 22:46:36 msmith Exp $
*/
#ifndef _SYS_MOUNT_H_
@ -79,7 +79,8 @@ struct statfs {
uid_t f_owner; /* user that mounted the filesystem */
int f_type; /* type of filesystem (see below) */
int f_flags; /* copy of mount exported flags */
long f_spare[2]; /* spare for later */
long f_syncwrites; /* count of sync writes since mount */
long f_asyncwrites; /* count of async writes since mount */
char f_fstypename[MFSNAMELEN]; /* fs type name */
char f_mntonname[MNAMELEN]; /* directory on which mounted */
char f_mntfromname[MNAMELEN];/* mounted filesystem */
@ -146,6 +147,7 @@ struct mount {
struct vfsops *mnt_op; /* operations on fs */
struct vfsconf *mnt_vfc; /* configuration info */
struct vnode *mnt_vnodecovered; /* vnode we mounted on */
struct vnode *mnt_syncer; /* syncer vnode */
struct vnodelst mnt_vnodelist; /* list of vnodes this mount */
struct lock mnt_lock; /* mount structure lock */
int mnt_flag; /* flags shared with user */
@ -167,6 +169,7 @@ struct mount {
#define MNT_UNION 0x00000020 /* union with underlying filesystem */
#define MNT_ASYNC 0x00000040 /* file system written asynchronously */
#define MNT_SUIDDIR 0x00100000 /* special handling of SUID on dirs */
#define MNT_SOFTDEP 0x00200000 /* soft updates being done */
#define MNT_NOATIME 0x10000000 /* disable update of file access time */
#define MNT_NOCLUSTERR 0x40000000 /* disable cluster read */
#define MNT_NOCLUSTERW 0x80000000 /* disable cluster write */
@ -203,7 +206,8 @@ struct mount {
MNT_DEFEXPORTED | MNT_EXPORTANON| MNT_EXKERB | \
MNT_LOCAL | MNT_USER | MNT_QUOTA | \
MNT_ROOTFS | MNT_NOATIME | MNT_NOCLUSTERR| \
MNT_NOCLUSTERW | MNT_SUIDDIR/* | MNT_EXPUBLIC */)
MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP \
/* | MNT_EXPUBLIC */)
/*
* External filesystem command modifier flags.
* Unmount can use the MNT_FORCE flag.
@ -248,8 +252,8 @@ struct mount {
*
* waitfor flags to vfs_sync() and getfsstat()
*/
#define MNT_WAIT 1
#define MNT_NOWAIT 2
#define MNT_WAIT 1 /* synchronously wait for I/O to complete */
#define MNT_NOWAIT 2 /* start all I/O, but do not wait for it */
#define MNT_LAZY 3 /* push data not written by filesystem syncer */
/*
@ -448,6 +452,7 @@ int vfs_export /* process mount export info */
int vfs_vrele __P((struct mount *, struct vnode *));
struct netcred *vfs_export_lookup /* lookup host in fs export list */
__P((struct mount *, struct netexport *, struct sockaddr *));
int vfs_allocate_syncvnode __P((struct mount *));
void vfs_getnewfsid __P((struct mount *));
struct mount *vfs_getvfs __P((fsid_t *)); /* return vfs given fsid */
int vfs_mountedon __P((struct vnode *)); /* is a vfs mounted on vp */

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)vnode.h 8.7 (Berkeley) 2/4/94
* $Id: vnode.h,v 1.66 1998/01/24 02:01:31 dyson Exp $
* $Id: vnode.h,v 1.67 1998/03/07 21:36:27 dyson Exp $
*/
#ifndef _SYS_VNODE_H_
@ -61,7 +61,7 @@ enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD };
enum vtagtype {
VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PC, VT_LFS, VT_LOFS, VT_FDESC,
VT_PORTAL, VT_NULL, VT_UMAP, VT_KERNFS, VT_PROCFS, VT_AFS, VT_ISOFS,
VT_UNION, VT_MSDOSFS, VT_DEVFS, VT_TFS
VT_UNION, VT_MSDOSFS, VT_DEVFS, VT_TFS, VT_VFS
};
/*
@ -94,6 +94,7 @@ struct vnode {
LIST_ENTRY(vnode) v_mntvnodes; /* vnodes for mount point */
struct buflists v_cleanblkhd; /* clean blocklist head */
struct buflists v_dirtyblkhd; /* dirty blocklist head */
LIST_ENTRY(vnode) v_synclist; /* vnodes with dirty buffers */
long v_numoutput; /* num of writes in progress */
enum vtype v_type; /* vnode type */
union {
@ -154,7 +155,8 @@ struct vnode {
#define VOWANT 0x20000 /* a process is waiting for VOLOCK */
#define VDOOMED 0x40000 /* This vnode is being recycled */
#define VFREE 0x80000 /* This vnode is on the freelist */
#define VTBFREE 0x100000 /* This vnode is no the to be freelist */
#define VTBFREE 0x100000 /* This vnode is on the to-be-freelist */
#define VONWORKLST 0x200000 /* On syncer work-list */
/*
* Vnode attributes. A field value of VNOVAL represents a field whose value
@ -243,6 +245,7 @@ extern int vttoif_tab[];
#define VREF(vp) vref(vp)
#ifdef DIAGNOSTIC
#define VATTR_NULL(vap) vattr_null(vap)
#else
@ -262,6 +265,8 @@ extern int vttoif_tab[];
*/
extern struct vnode *rootvnode; /* root (i.e. "/") vnode */
extern int desiredvnodes; /* number of vnodes desired */
extern time_t syncdelay; /* time to delay syncing vnodes */
extern int rushjob; /* # of slots filesys_syncer should run ASAP */
extern struct vm_zone *namei_zone;
extern int prtactive; /* nonzero to call vprint() */
extern struct vattr va_null; /* predefined null vattr structure */
@ -499,6 +504,7 @@ int vn_rdwr __P((enum uio_rw rw, struct vnode *vp, caddr_t base,
int len, off_t offset, enum uio_seg segflg, int ioflg,
struct ucred *cred, int *aresid, struct proc *p));
int vn_stat __P((struct vnode *vp, struct stat *sb, struct proc *p));
void vn_syncer_add_to_worklist __P((struct vnode *vp, int delay));
int vfs_cache_lookup __P((struct vop_lookup_args *ap));
int vfs_object_create __P((struct vnode *vp, struct proc *p,
struct ucred *cred, int waslocked));

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_alloc.c 8.18 (Berkeley) 5/26/95
* $Id: ffs_alloc.c,v 1.46 1998/02/04 22:33:27 eivind Exp $
* $Id: ffs_alloc.c,v 1.47 1998/02/06 12:14:13 eivind Exp $
*/
#include "opt_quota.h"
@ -57,7 +57,8 @@ typedef ufs_daddr_t allocfcn_t __P((struct inode *ip, int cg, ufs_daddr_t bpref,
int size));
static ufs_daddr_t ffs_alloccg __P((struct inode *, int, ufs_daddr_t, int));
static ufs_daddr_t ffs_alloccgblk __P((struct fs *, struct cg *, ufs_daddr_t));
static ufs_daddr_t
ffs_alloccgblk __P((struct inode *, struct buf *, ufs_daddr_t));
#ifdef DIAGNOSTIC
static int ffs_checkblk __P((struct inode *, ufs_daddr_t, long));
#endif
@ -292,7 +293,8 @@ ffs_realloccg(ip, lbprev, bpref, osize, nsize, cred, bpp)
ffs_alloccg);
if (bno > 0) {
bp->b_blkno = fsbtodb(fs, bno);
ffs_blkfree(ip, bprev, (long)osize);
if (!DOINGSOFTDEP(ITOV(ip)))
ffs_blkfree(ip, bprev, (long)osize);
if (nsize < request)
ffs_blkfree(ip, bno + numfrags(fs, nsize),
(long)(request - nsize));
@ -455,8 +457,10 @@ ffs_reallocblks(ap)
#endif
blkno = newblk;
for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->fs_frag) {
if (i == ssize)
if (i == ssize) {
bap = ebap;
soff = -i;
}
#ifdef DIAGNOSTIC
if (!ffs_checkblk(ip,
dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->fs_bsize))
@ -468,6 +472,16 @@ ffs_reallocblks(ap)
if (prtrealloc)
printf(" %d,", *bap);
#endif
if (DOINGSOFTDEP(vp)) {
if (sbap == &ip->i_db[0] && i < ssize)
softdep_setup_allocdirect(ip, start_lbn + i,
blkno, *bap, fs->fs_bsize, fs->fs_bsize,
buflist->bs_children[i]);
else
softdep_setup_allocindir_page(ip, start_lbn + i,
i < ssize ? sbp : ebp, soff + i, blkno,
*bap, buflist->bs_children[i]);
}
*bap++ = blkno;
}
/*
@ -509,8 +523,10 @@ ffs_reallocblks(ap)
printf("\n\tnew:");
#endif
for (blkno = newblk, i = 0; i < len; i++, blkno += fs->fs_frag) {
ffs_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno),
fs->fs_bsize);
if (!DOINGSOFTDEP(vp))
ffs_blkfree(ip,
dbtofsb(fs, buflist->bs_children[i]->b_blkno),
fs->fs_bsize);
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
#ifdef DEBUG
if (!ffs_checkblk(ip,
@ -847,6 +863,8 @@ ffs_fragextend(ip, cg, bprev, osize, nsize)
fs->fs_cs(fs, cg).cs_nffree--;
}
fs->fs_fmod = 1;
if (DOINGSOFTDEP(ITOV(ip)))
softdep_setup_blkmapdep(bp, fs, bprev);
bdwrite(bp);
return (bprev);
}
@ -868,7 +886,8 @@ ffs_alloccg(ip, cg, bpref, size)
register struct cg *cgp;
struct buf *bp;
register int i;
int error, bno, frags, allocsiz;
ufs_daddr_t bno, blkno;
int allocsiz, error, frags;
fs = ip->i_fs;
if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
@ -887,7 +906,7 @@ ffs_alloccg(ip, cg, bpref, size)
}
cgp->cg_time = time.tv_sec;
if (size == fs->fs_bsize) {
bno = ffs_alloccgblk(fs, cgp, bpref);
bno = ffs_alloccgblk(ip, bp, bpref);
bdwrite(bp);
return (bno);
}
@ -909,7 +928,7 @@ ffs_alloccg(ip, cg, bpref, size)
brelse(bp);
return (0);
}
bno = ffs_alloccgblk(fs, cgp, bpref);
bno = ffs_alloccgblk(ip, bp, bpref);
bpref = dtogd(fs, bno);
for (i = frags; i < fs->fs_frag; i++)
setbit(cg_blksfree(cgp), bpref + i);
@ -936,8 +955,11 @@ ffs_alloccg(ip, cg, bpref, size)
cgp->cg_frsum[allocsiz]--;
if (frags != allocsiz)
cgp->cg_frsum[allocsiz - frags]++;
blkno = cg * fs->fs_fpg + bno;
if (DOINGSOFTDEP(ITOV(ip)))
softdep_setup_blkmapdep(bp, fs, blkno);
bdwrite(bp);
return (cg * fs->fs_fpg + bno);
return ((u_long)blkno);
}
/*
@ -952,16 +974,20 @@ ffs_alloccg(ip, cg, bpref, size)
* blocks may be fragmented by the routine that allocates them.
*/
static ufs_daddr_t
ffs_alloccgblk(fs, cgp, bpref)
register struct fs *fs;
register struct cg *cgp;
ffs_alloccgblk(ip, bp, bpref)
struct inode *ip;
struct buf *bp;
ufs_daddr_t bpref;
{
struct fs *fs;
struct cg *cgp;
ufs_daddr_t bno, blkno;
int cylno, pos, delta;
short *cylbp;
register int i;
fs = ip->i_fs;
cgp = (struct cg *)bp->b_data;
if (bpref == 0 || dtog(fs, bpref) != cgp->cg_cgx) {
bpref = cgp->cg_rotor;
goto norot;
@ -1052,7 +1078,10 @@ ffs_alloccgblk(fs, cgp, bpref)
cg_blks(fs, cgp, cylno)[cbtorpos(fs, bno)]--;
cg_blktot(cgp)[cylno]--;
fs->fs_fmod = 1;
return (cgp->cg_cgx * fs->fs_fpg + bno);
blkno = cgp->cg_cgx * fs->fs_fpg + bno;
if (DOINGSOFTDEP(ITOV(ip)))
softdep_setup_blkmapdep(bp, fs, blkno);
return (blkno);
}
#ifdef notyet
@ -1155,7 +1184,7 @@ ffs_clusteralloc(ip, cg, bpref, len)
panic("ffs_clusteralloc: allocated out of group");
len = blkstofrags(fs, len);
for (i = 0; i < len; i += fs->fs_frag)
if ((got = ffs_alloccgblk(fs, cgp, bno + i)) != bno + i)
if ((got = ffs_alloccgblk(ip, bp, bno + i)) != bno + i)
panic("ffs_clusteralloc: lost block");
bdwrite(bp);
return (bno);
@ -1234,6 +1263,8 @@ ffs_nodealloccg(ip, cg, ipref, mode)
panic("ffs_nodealloccg: block not in map");
/* NOTREACHED */
gotit:
if (DOINGSOFTDEP(ITOV(ip)))
softdep_setup_inomapdep(bp, ip, cg * fs->fs_ipg + ipref);
setbit(cg_inosused(cgp), ipref);
cgp->cg_cs.cs_nifree--;
fs->fs_cstotal.cs_nifree--;
@ -1268,9 +1299,10 @@ ffs_blkfree(ip, bno, size)
int i, error, cg, blk, frags, bbase;
fs = ip->i_fs;
if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
printf("dev = 0x%lx, bsize = %ld, size = %ld, fs = %s\n",
(u_long)ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);
if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
printf("dev=0x%lx, bno = %d, bsize = %d, size = %ld, fs = %s\n",
(u_long)ip->i_dev, bno, fs->fs_bsize, size, fs->fs_fsmnt);
panic("ffs_blkfree: bad size");
}
cg = dtog(fs, bno);
@ -1294,7 +1326,7 @@ ffs_blkfree(ip, bno, size)
bno = dtogd(fs, bno);
if (size == fs->fs_bsize) {
blkno = fragstoblks(fs, bno);
if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) {
if (!ffs_isfreeblock(fs, cg_blksfree(cgp), blkno)) {
printf("dev = 0x%lx, block = %ld, fs = %s\n",
(u_long) ip->i_dev, bno, fs->fs_fsmnt);
panic("ffs_blkfree: freeing free block");
@ -1404,11 +1436,26 @@ ffs_checkblk(ip, bno, size)
/*
* Free an inode.
*
* The specified inode is placed back in the free map.
*/
int
ffs_vfree(pvp, ino, mode)
ffs_vfree( pvp, ino, mode)
struct vnode *pvp;
ino_t ino;
int mode;
{
if (DOINGSOFTDEP(pvp)) {
softdep_freefile(pvp, ino, mode);
return (0);
}
return (ffs_freefile(pvp, ino, mode));
}
/*
* Do the actual free operation.
* The specified inode is placed back in the free map.
*/
int
ffs_freefile( pvp, ino, mode)
struct vnode *pvp;
ino_t ino;
int mode;
@ -1429,7 +1476,7 @@ ffs_vfree(pvp, ino, mode)
(int)fs->fs_cgsize, NOCRED, &bp);
if (error) {
brelse(bp);
return (0);
return (error);
}
cgp = (struct cg *)bp->b_data;
if (!cg_chkmagic(cgp)) {

View File

@ -31,13 +31,14 @@
* SUCH DAMAGE.
*
* @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
* $Id: ffs_balloc.c,v 1.18 1998/02/04 22:33:31 eivind Exp $
* $Id: ffs_balloc.c,v 1.19 1998/02/06 12:14:14 eivind Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/lock.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <ufs/ufs/quota.h>
@ -53,16 +54,23 @@
* the inode and the logical block number in a file.
*/
int
ffs_balloc(ip, lbn, size, cred, bpp, flags)
ffs_balloc(ap)
struct vop_balloc_args /* {
struct inode *a_ip;
ufs_daddr_t a_lbn;
int a_size;
struct ucred *a_cred;
int a_flags;
struct buf *a_bpp;
} */ *ap;
{
register struct inode *ip;
register ufs_daddr_t lbn;
int size;
struct ucred *cred;
struct buf **bpp;
int flags;
{
register struct fs *fs;
register ufs_daddr_t nb;
struct fs *fs;
ufs_daddr_t nb;
struct buf *bp, *nbp;
struct vnode *vp = ITOV(ip);
struct indir indirs[NIADDR + 2];
@ -70,10 +78,18 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
int deallocated, osize, nsize, num, i, error;
ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1];
*bpp = NULL;
vp = ap->a_vp;
ip = VTOI(vp);
fs = ip->i_fs;
lbn = lblkno(fs, ap->a_startoffset);
size = blkoff(fs, ap->a_startoffset) + ap->a_size;
if (size > fs->fs_bsize)
panic("ffs_balloc: blk too big");
*ap->a_bpp = NULL;
if (lbn < 0)
return (EFBIG);
fs = ip->i_fs;
cred = ap->a_cred;
flags = ap->a_flags;
/*
* If the next write will extend the file into a new block,
@ -89,6 +105,10 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
osize, (int)fs->fs_bsize, cred, &bp);
if (error)
return (error);
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, nb,
dbtofsb(fs, bp->b_blkno), ip->i_db[nb],
fs->fs_bsize, osize, bp);
ip->i_size = smalllblktosize(fs, nb + 1);
ip->i_db[nb] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
@ -110,7 +130,7 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
return (error);
}
bp->b_blkno = fsbtodb(fs, nb);
*bpp = bp;
*ap->a_bpp = bp;
return (0);
}
if (nb != 0) {
@ -132,6 +152,10 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
&ip->i_db[0]), osize, nsize, cred, &bp);
if (error)
return (error);
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, lbn,
dbtofsb(fs, bp->b_blkno), nb,
nsize, osize, bp);
}
} else {
if (ip->i_size < smalllblktosize(fs, lbn + 1))
@ -147,10 +171,13 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
bp->b_blkno = fsbtodb(fs, newb);
if (flags & B_CLRBUF)
vfs_bio_clrbuf(bp);
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, lbn, newb, 0,
nsize, 0, bp);
}
ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
*bpp = bp;
*ap->a_bpp = bp;
return (0);
}
/*
@ -180,12 +207,18 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
bp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(bp);
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
if (error = bwrite(bp))
goto fail;
if (DOINGSOFTDEP(vp)) {
softdep_setup_allocdirect(ip, NDADDR + indirs[0].in_off,
newb, 0, fs->fs_bsize, 0, bp);
bdwrite(bp);
} else {
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
if (error = bwrite(bp))
goto fail;
}
allocib = &ip->i_ib[indirs[0].in_off];
*allocib = nb;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
@ -221,13 +254,19 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(nbp);
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
if (error = bwrite(nbp)) {
brelse(bp);
goto fail;
if (DOINGSOFTDEP(vp)) {
softdep_setup_allocindir_meta(nbp, ip, bp,
indirs[i - 1].in_off, nb);
bdwrite(nbp);
} else {
/*
* Write synchronously so that indirect blocks
* never point at garbage.
*/
if (error = bwrite(nbp)) {
brelse(bp);
goto fail;
}
}
bap[indirs[i - 1].in_off] = nb;
/*
@ -259,6 +298,9 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
nbp->b_blkno = fsbtodb(fs, nb);
if (flags & B_CLRBUF)
vfs_bio_clrbuf(nbp);
if (DOINGSOFTDEP(vp))
softdep_setup_allocindir_page(ip, lbn, bp,
indirs[i].in_off, nb, 0, nbp);
bap[indirs[i].in_off] = nb;
/*
* If required, write synchronously, otherwise use
@ -271,7 +313,7 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
}
*bpp = nbp;
*ap->a_bpp = nbp;
return (0);
}
brelse(bp);
@ -285,7 +327,7 @@ ffs_balloc(ip, lbn, size, cred, bpp, flags)
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
}
*bpp = nbp;
*ap->a_bpp = nbp;
return (0);
fail:
/*

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_extern.h 8.6 (Berkeley) 3/30/95
* $Id: ffs_extern.h,v 1.21 1997/11/22 08:35:45 bde Exp $
* $Id: ffs_extern.h,v 1.22 1998/02/03 21:52:00 bde Exp $
*/
#ifndef _UFS_FFS_EXTERN_H
@ -68,8 +68,7 @@ struct vop_reallocblks_args;
int ffs_alloc __P((struct inode *,
ufs_daddr_t, ufs_daddr_t, int, struct ucred *, ufs_daddr_t *));
int ffs_balloc __P((struct inode *,
ufs_daddr_t, int, struct ucred *, struct buf **, int));
int ffs_balloc __P((struct vop_balloc_args *));
int ffs_blkatoff __P((struct vnode *, off_t, char **, struct buf **));
void ffs_blkfree __P((struct inode *, ufs_daddr_t, long));
ufs_daddr_t ffs_blkpref __P((struct inode *, ufs_daddr_t, int, ufs_daddr_t *));
@ -79,7 +78,9 @@ int ffs_fhtovp __P((struct mount *, struct fid *, struct sockaddr *,
struct vnode **, int *, struct ucred **));
int ffs_flushfiles __P((struct mount *, int, struct proc *));
void ffs_fragacct __P((struct fs *, int, int32_t [], int));
int ffs_freefile __P(( struct vnode *, ino_t, int ));
int ffs_isblock __P((struct fs *, u_char *, ufs_daddr_t));
int ffs_isfreeblock __P((struct fs *, unsigned char *, ufs_daddr_t));
int ffs_mountfs __P((struct vnode *, struct mount *, struct proc *,
struct malloc_type *));
int ffs_mountroot __P((void));
@ -102,4 +103,31 @@ extern vop_t **ffs_vnodeop_p;
extern vop_t **ffs_specop_p;
extern vop_t **ffs_fifoop_p;
/*
* Soft update function prototypes.
*/
void softdep_initialize __P((void));
int softdep_process_worklist __P((struct mount *));
int softdep_mount __P((struct vnode *, struct mount *, struct fs *,
struct ucred *));
int softdep_flushfiles __P((struct mount *, int, struct proc *));
void softdep_update_inodeblock __P((struct inode *, struct buf *, int));
void softdep_load_inodeblock __P((struct inode *));
int softdep_fsync __P((struct vnode *));
void softdep_freefile __P((struct vnode *, ino_t, int));
void softdep_setup_freeblocks __P((struct inode *, off_t));
void softdep_deallocate_dependencies __P((struct buf *));
void softdep_setup_inomapdep __P((struct buf *, struct inode *, ino_t));
void softdep_setup_blkmapdep __P((struct buf *, struct fs *, ufs_daddr_t));
void softdep_setup_allocdirect __P((struct inode *, ufs_lbn_t, ufs_daddr_t,
ufs_daddr_t, long, long, struct buf *));
void softdep_setup_allocindir_meta __P((struct buf *, struct inode *,
struct buf *, int, ufs_daddr_t));
void softdep_setup_allocindir_page __P((struct inode *, ufs_lbn_t,
struct buf *, int, ufs_daddr_t, ufs_daddr_t, struct buf *));
void softdep_disk_io_initiation __P((struct buf *));
void softdep_disk_write_complete __P((struct buf *));
int softdep_sync_metadata __P((struct vop_fsync_args *));
#endif /* !_UFS_FFS_EXTERN_H */

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_inode.c 8.13 (Berkeley) 4/21/95
* $Id: ffs_inode.c,v 1.34 1998/02/06 12:14:14 eivind Exp $
* $Id: ffs_inode.c,v 1.35 1998/03/07 21:36:33 dyson Exp $
*/
#include "opt_quota.h"
@ -87,8 +87,9 @@ ffs_update(vp, access, modify, waitfor)
~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
return (0);
}
if ((ip->i_flag &
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0)
if (((ip->i_flag &
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
(waitfor != MNT_WAIT))
return (0);
/*
* Use a copy of the current time to get consistent timestamps
@ -129,11 +130,15 @@ ffs_update(vp, access, modify, waitfor)
brelse(bp);
return (error);
}
if (DOINGSOFTDEP(vp))
softdep_update_inodeblock(ip, bp, waitfor);
else if (ip->i_effnlink != ip->i_nlink)
panic("ffs_update: bad link cnt");
*((struct dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number)) = ip->i_din;
if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0)
if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0) {
return (bwrite(bp));
else {
} else {
if (bp->b_bufsize == fs->fs_bsize)
bp->b_flags |= B_CLUSTEROK;
bdwrite(bp);
@ -171,6 +176,8 @@ ffs_truncate(vp, length, flags, cred, p)
off_t osize;
oip = VTOI(ovp);
if (oip->i_size == length)
return (0);
fs = oip->i_fs;
if (length < 0)
return (EINVAL);
@ -197,6 +204,31 @@ ffs_truncate(vp, length, flags, cred, p)
if (error)
return (error);
#endif
ovp->v_lasta = ovp->v_clen = ovp->v_cstart = ovp->v_lastw = 0;
if (DOINGSOFTDEP(ovp)) {
if (length > 0) {
/*
* If a file is only partially truncated, then
* we have to clean up the data structures
* describing the allocation past the truncation
* point. Finding and deallocating those structures
* is a lot of work. Since partial truncation occurs
* rarely, we solve the problem by syncing the file
* so that it will have no data structures left.
*/
if ((error = VOP_FSYNC(ovp, cred, MNT_WAIT,
p)) != 0)
return (error);
} else {
#ifdef QUOTA
(void) chkdq(oip, -oip->i_blocks, NOCRED, 0);
#endif
softdep_setup_freeblocks(oip, length);
(void) vinvalbuf(ovp, 0, cred, p, 0, 0);
oip->i_flag |= IN_CHANGE | IN_UPDATE;
return (ffs_update(ovp, &tv, &tv, 0));
}
}
osize = oip->i_size;
/*
* Lengthen the size of the file. We must ensure that the
@ -205,13 +237,15 @@ ffs_truncate(vp, length, flags, cred, p)
*/
if (osize < length) {
vnode_pager_setsize(ovp, length);
#if 0
offset = blkoff(fs, length - 1);
lbn = lblkno(fs, length - 1);
#endif
aflags = B_CLRBUF;
if (flags & IO_SYNC)
aflags |= B_SYNC;
error = ffs_balloc(oip, lbn, offset + 1, cred,
&bp, aflags);
error = VOP_BALLOC(ovp, length - 1, 1,
cred, aflags, &bp);
if (error)
return (error);
oip->i_size = length;
@ -241,9 +275,13 @@ ffs_truncate(vp, length, flags, cred, p)
aflags = B_CLRBUF;
if (flags & IO_SYNC)
aflags |= B_SYNC;
error = ffs_balloc(oip, lbn, offset, cred, &bp, aflags);
if (error)
error = VOP_BALLOC(ovp, length - 1, 1, cred, aflags, &bp);
if (error) {
#if 0 /* kirk's version had this */
vnode_pager_setsize(ovp, (u_long)osize);
#endif
return (error);
}
oip->i_size = length;
size = blksize(fs, oip, lbn);
bzero((char *)bp->b_data + offset, (u_int)(size - offset));

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95
* $Id: ffs_subr.c,v 1.18 1998/02/06 12:14:14 eivind Exp $
* $Id: ffs_subr.c,v 1.19 1998/02/13 00:20:36 bde Exp $
*/
#include <sys/param.h>
@ -190,6 +190,30 @@ ffs_isblock(fs, cp, h)
}
}
/*
* check if a block is free
*/
int
ffs_isfreeblock(fs, cp, h)
struct fs *fs;
unsigned char *cp;
ufs_daddr_t h;
{
switch ((int)fs->fs_frag) {
case 8:
return (cp[h] == 0);
case 4:
return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
case 2:
return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
case 1:
return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
default:
panic("ffs_isfreeblock");
}
}
/*
* take a block out of the map
*/

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
* $Id: ffs_vfsops.c,v 1.74 1998/03/07 14:59:44 bde Exp $
* $Id: ffs_vfsops.c,v 1.75 1998/03/07 21:36:36 dyson Exp $
*/
#include "opt_quota.h"
@ -203,7 +203,11 @@ ffs_mount( mp, path, data, ndp, p)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
err = ffs_flushfiles(mp, flags, p);
if (mp->mnt_flag & MNT_SOFTDEP) {
err = softdep_flushfiles(mp, flags, p);
} else {
err = ffs_flushfiles(mp, flags, p);
}
}
if (!err && (mp->mnt_flag & MNT_RELOAD))
err = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
@ -410,7 +414,10 @@ ffs_reload(mp, cred, p)
* Step 1: invalidate all cached meta-data.
*/
devvp = VFSTOUFS(mp)->um_devvp;
if (vinvalbuf(devvp, 0, cred, p, 0, 0))
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
error = vinvalbuf(devvp, 0, cred, p, 0, 0);
VOP_UNLOCK(devvp, 0, p);
if (error)
panic("ffs_reload: dirty1");
dev = devvp->v_rdev;
@ -516,6 +523,7 @@ ffs_reload(mp, cred, p)
}
ip->i_din = *((struct dinode *)bp->b_data +
ino_to_fsbo(fs, ip->i_number));
ip->i_effnlink = ip->i_nlink;
brelse(bp);
vput(vp);
simple_lock(&mntvnode_slock);
@ -537,10 +545,12 @@ ffs_mountfs(devvp, mp, p, malloctype)
register struct ufsmount *ump;
struct buf *bp;
register struct fs *fs;
struct cg *cgp;
dev_t dev;
struct partinfo dpart;
struct csum cstotal;
caddr_t base, space;
int error, i, blks, size, ronly;
int error, i, cyl, blks, size, ronly;
int32_t *lp;
struct ucred *cred;
u_int64_t maxfilesize; /* XXX */
@ -562,7 +572,10 @@ ffs_mountfs(devvp, mp, p, malloctype)
if (ncount > 1 && devvp != rootvp)
return (EBUSY);
if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
VOP_UNLOCK(devvp, 0, p);
if (error)
return (error);
/*
@ -674,7 +687,7 @@ ffs_mountfs(devvp, mp, p, malloctype)
ump->um_seqinc = fs->fs_frag;
for (i = 0; i < MAXQUOTAS; i++)
ump->um_quotas[i] = NULLVP;
devvp->v_specflags |= SI_MOUNTEDON;
devvp->v_specmountpoint = mp;
ffs_oldfscompat(fs);
/*
@ -700,11 +713,17 @@ ffs_mountfs(devvp, mp, p, malloctype)
if (fs->fs_maxfilesize > maxfilesize) /* XXX */
fs->fs_maxfilesize = maxfilesize; /* XXX */
if (ronly == 0) {
if ((fs->fs_flags & FS_DOSOFTDEP) &&
(error = softdep_mount(devvp, mp, fs, cred)) != 0) {
free(base, M_UFSMNT);
goto out;
}
fs->fs_clean = 0;
(void) ffs_sbupdate(ump, MNT_WAIT);
}
return (0);
out:
devvp->v_specmountpoint = NULL;
if (bp)
brelse(bp);
(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
@ -765,9 +784,13 @@ ffs_unmount(mp, mntflags, p)
if (mntflags & MNT_FORCE) {
flags |= FORCECLOSE;
}
error = ffs_flushfiles(mp, flags, p);
if (error)
return (error);
if (mp->mnt_flag & MNT_SOFTDEP) {
if ((error = softdep_flushfiles(mp, flags, p)) != 0)
return (error);
} else {
if ((error = ffs_flushfiles(mp, flags, p)) != 0)
return (error);
}
ump = VFSTOUFS(mp);
fs = ump->um_fs;
if (fs->fs_ronly == 0) {
@ -778,7 +801,7 @@ ffs_unmount(mp, mntflags, p)
return (error);
}
}
ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
ump->um_devvp->v_specmountpoint = NULL;
vinvalbuf(ump->um_devvp, V_SAVE, NOCRED, p, 0, 0);
error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
@ -824,7 +847,17 @@ ffs_flushfiles(mp, flags, p)
*/
}
#endif
error = vflush(mp, NULLVP, flags);
/*
* Flush all the files.
*/
if ((error = vflush(mp, NULL, flags)) != 0)
return (error);
/*
* Flush filesystem metadata.
*/
vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
error = VOP_FSYNC(ump->um_devvp, p->p_ucred, MNT_WAIT, p);
VOP_UNLOCK(ump->um_devvp, 0, p);
return (error);
}
@ -903,9 +936,9 @@ ffs_sync(mp, waitfor, cred, p)
simple_lock(&vp->v_interlock);
nvp = vp->v_mntvnodes.le_next;
ip = VTOI(vp);
if (((ip->i_flag &
if ((vp->v_type == VNON) || ((ip->i_flag &
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
vp->v_dirtyblkhd.lh_first == NULL) {
((vp->v_dirtyblkhd.lh_first == NULL) || (waitfor == MNT_LAZY))) {
simple_unlock(&vp->v_interlock);
continue;
}
@ -937,21 +970,22 @@ ffs_sync(mp, waitfor, cred, p)
/*
* Force stale file system control information to be flushed.
*/
error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p);
if (error)
allerror = error;
if (waitfor != MNT_LAZY) {
if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
waitfor = MNT_NOWAIT;
vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, p);
if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)
allerror = error;
VOP_UNLOCK(ump->um_devvp, 0, p);
}
#ifdef QUOTA
qsync(mp);
#endif
/*
* Write back modified superblock.
*/
if (fs->fs_fmod != 0) {
fs->fs_fmod = 0;
fs->fs_time = time.tv_sec;
if (error = ffs_sbupdate(ump, waitfor))
allerror = error;
}
if (fs->fs_fmod != 0 && (error = ffs_sbupdate(ump, waitfor)) != 0)
allerror = error;
return (allerror);
}
@ -1060,6 +1094,10 @@ ffs_vget(mp, ino, vpp)
return (error);
}
ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
if (DOINGSOFTDEP(vp))
softdep_load_inodeblock(ip);
else
ip->i_effnlink = ip->i_nlink;
bqrelse(bp);
/*
@ -1157,6 +1195,7 @@ ffs_init(vfsp)
struct vfsconf *vfsp;
{
softdep_initialize();
return (ufs_init(vfsp));
}
@ -1200,6 +1239,8 @@ ffs_sbupdate(mp, waitfor)
if (allerror)
return (allerror);
bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
fs->fs_fmod = 0;
fs->fs_time = time.tv_sec;
bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
/* Restore compatibility to old file systems. XXX */
dfs = (struct fs *)bp->b_data; /* XXX */

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
* $Id: ffs_vnops.c,v 1.42 1998/02/06 12:14:16 eivind Exp $
* $Id: ffs_vnops.c,v 1.43 1998/02/26 06:39:38 msmith Exp $
*/
#include <sys/param.h>
@ -74,6 +74,7 @@ static struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
{ &vop_getpages_desc, (vop_t *) ffs_getpages },
{ &vop_putpages_desc, (vop_t *) ffs_putpages },
{ &vop_read_desc, (vop_t *) ffs_read },
{ &vop_balloc_desc, (vop_t *) ffs_balloc },
{ &vop_reallocblks_desc, (vop_t *) ffs_reallocblks },
{ &vop_write_desc, (vop_t *) ffs_write },
{ NULL, NULL }
@ -120,12 +121,11 @@ ffs_fsync(ap)
struct proc *a_p;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
register struct buf *bp;
struct vnode *vp = ap->a_vp;
struct buf *bp;
struct timeval tv;
struct buf *nbp;
int pass;
int s;
int s, error, passes, skipmeta;
daddr_t lbn;
@ -137,31 +137,45 @@ ffs_fsync(ap)
lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1));
}
pass = 0;
/*
* Flush all dirty buffers associated with a vnode.
*/
passes = NIADDR;
skipmeta = 0;
if (ap->a_waitfor == MNT_WAIT)
skipmeta = 1;
loop:
s = splbio();
loop2:
for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
nbp = bp->b_vnbufs.le_next;
if ((bp->b_flags & B_BUSY) || (pass == 0 && (bp->b_lblkno < 0)))
/*
* First time through on a synchronous call,
* or if it's already scheduled, skip to the next
* buffer
*/
if ((bp->b_flags & B_BUSY) ||
((skipmeta == 1) && (bp->b_lblkno < 0)))
continue;
if ((bp->b_flags & B_DELWRI) == 0)
panic("ffs_fsync: not dirty");
if (((bp->b_vp != vp) || (ap->a_waitfor != MNT_NOWAIT)) ||
((vp->v_type != VREG) && (vp->v_type != VBLK))) {
/*
* If data is outstanding to another vnode, or we were
* asked to wait for everything, or it's not a file or BDEV,
* start the IO on this buffer immediatly.
*/
if (((bp->b_vp != vp) || (ap->a_waitfor == MNT_WAIT)) ||
((vp->v_type != VREG) && (vp->v_type != VBLK))) {
bremfree(bp);
bp->b_flags |= B_BUSY;
splx(s);
/*
* Wait for I/O associated with indirect blocks to complete,
* since there is no way to quickly wait for them below.
* Wait for I/O associated with indirect blocks to
* complete, since there is no way to quickly wait
* for them below.
*/
if ((bp->b_vp == vp) && (ap->a_waitfor == MNT_NOWAIT)) {
if ((bp->b_vp == vp) || (ap->a_waitfor != MNT_WAIT)) {
if (bp->b_flags & B_CLUSTEROK) {
bdwrite(bp);
(void) vfs_bio_awrite(bp);
@ -171,26 +185,30 @@ ffs_fsync(ap)
} else {
(void) bwrite(bp);
}
} else if ((vp->v_type == VREG) && (bp->b_lblkno >= lbn)) {
/*
* If the buffer is for data that has been truncated
* off the file, then throw it away.
*/
bremfree(bp);
bp->b_flags |= B_BUSY | B_INVAL | B_NOCACHE;
brelse(bp);
splx(s);
} else {
vfs_bio_awrite(bp);
splx(s);
}
goto loop;
}
splx(s);
if (pass == 0) {
pass = 1;
goto loop;
/*
* If we were asked to do this synchronously, then go back for
* another pass, this time doing the metadata.
*/
if (skipmeta) {
skipmeta = 0;
goto loop2; /* stay within the splbio() */
}
splx(s);
if (ap->a_waitfor == MNT_WAIT) {
s = splbio();
@ -198,15 +216,38 @@ ffs_fsync(ap)
vp->v_flag |= VBWAIT;
(void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "ffsfsn", 0);
}
/*
* Ensure that any filesystem metatdata associated
* with the vnode has been written.
*/
splx(s);
#ifdef DIAGNOSTIC
if ((error = softdep_sync_metadata(ap)) != 0)
return (error);
s = splbio();
if (vp->v_dirtyblkhd.lh_first) {
vprint("ffs_fsync: dirty", vp);
goto loop;
}
/*
* Block devices associated with filesystems may
* have new I/O requests posted for them even if
* the vnode is locked, so no amount of trying will
* get them clean. Thus we give block devices a
* good effort, then just give up. For all other file
* types, go around and try again until it is clean.
*/
if (passes > 0) {
passes -= 1;
goto loop2;
}
#ifdef DIAGNOSTIC
if (vp->v_type != VBLK)
vprint("ffs_fsync: dirty", vp);
#endif
}
}
gettime(&tv);
return (UFS_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
error = UFS_UPDATE(ap->a_vp, &tv, &tv, (ap->a_waitfor == MNT_WAIT));
if (error)
return (error);
if (DOINGSOFTDEP(vp) && ap->a_waitfor == MNT_WAIT)
error = softdep_fsync(vp);
return (error);
}

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)fs.h 8.13 (Berkeley) 3/21/95
* $Id: fs.h,v 1.11 1997/03/23 20:08:22 guido Exp $
* $Id: fs.h,v 1.12 1997/03/24 03:19:37 bde Exp $
*/
#ifndef _UFS_FFS_FS_H_
@ -222,7 +222,7 @@ struct fs {
int8_t fs_fmod; /* super block modified flag */
int8_t fs_clean; /* file system is clean flag */
int8_t fs_ronly; /* mounted read-only flag */
int8_t fs_flags; /* currently unused flag */
int8_t fs_flags; /* see FS_ flags below */
u_char fs_fsmnt[MAXMNTLEN]; /* name mounted on */
/* these fields retain the current block allocation info */
int32_t fs_cgrotor; /* last cg searched */
@ -254,12 +254,19 @@ struct fs {
#define FS_OKAY 0x7c269d38 /* superblock checksum */
#define FS_42INODEFMT -1 /* 4.2BSD inode format */
#define FS_44INODEFMT 2 /* 4.4BSD inode format */
/*
* Preference for optimization.
*/
#define FS_OPTTIME 0 /* minimize allocation time */
#define FS_OPTSPACE 1 /* minimize disk fragmentation */
/*
* Filesystem flags.
*/
#define FS_UNCLEAN 0x01 /* filesystem not clean at mount */
#define FS_DOSOFTDEP 0x02 /* filesystem using soft dependencies */
/*
* Rotational layout table format types
*/
@ -485,6 +492,11 @@ struct ocg {
(((lbn) >= NDADDR || (dip)->di_size >= smalllblktosize(fs, (lbn) + 1)) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (dip)->di_size))))
#define sblksize(fs, size, lbn) \
(((lbn) >= NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \
? (fs)->fs_bsize \
: (fragroundup(fs, blkoff(fs, (size)))))
/*
* Number of disk sectors per block/fragment; assumes DEV_BSIZE byte

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)inode.h 8.9 (Berkeley) 5/14/95
* $Id: inode.h,v 1.19 1997/12/05 13:43:47 jkh Exp $
* $Id: inode.h,v 1.20 1998/01/30 11:34:02 phk Exp $
*/
#ifndef _UFS_UFS_INODE_H_
@ -45,6 +45,11 @@
#include <sys/lock.h>
#include <ufs/ufs/dinode.h>
/*
* The size of a logical block number.
*/
typedef long ufs_lbn_t;
/*
* This must agree with the definition in <ufs/ufs/dir.h>.
*/
@ -67,6 +72,7 @@ struct inode {
u_int32_t i_flag; /* flags, see below */
dev_t i_dev; /* Device associated with the inode. */
ino_t i_number; /* The identity of the inode. */
int i_effnlink; /* i_nlink when I/O completes */
union { /* Associated filesystem. */
struct fs *fs; /* FFS */
@ -160,6 +166,9 @@ struct indir {
} \
}
/* Determine if soft dependencies are being done */
#define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & MNT_SOFTDEP)
/* This overlays the fid structure (see mount.h). */
struct ufid {
u_int16_t ufid_len; /* Length of structure. */

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_extern.h 8.10 (Berkeley) 5/14/95
* $Id: ufs_extern.h,v 1.21 1997/10/16 11:59:09 phk Exp $
* $Id: ufs_extern.h,v 1.22 1997/10/27 12:50:57 bde Exp $
*/
#ifndef _UFS_UFS_EXTERN_H_
@ -68,12 +68,12 @@ int ufs_checkpath __P((struct inode *, struct inode *, struct ucred *));
void ufs_dirbad __P((struct inode *, doff_t, char *));
int ufs_dirbadentry __P((struct vnode *, struct direct *, int));
int ufs_dirempty __P((struct inode *, ino_t, struct ucred *));
int ufs_direnter __P((struct inode *, struct vnode *,struct componentname *));
int ufs_direnter2 __P((struct vnode *, struct direct *, struct ucred *,
struct proc *));
int ufs_dirremove __P((struct vnode *, struct componentname*));
int ufs_dirrewrite
__P((struct inode *, struct inode *, struct componentname *));
void ufs_makedirentry __P((struct inode *, struct componentname *,
struct direct *));
int ufs_direnter __P((struct vnode *, struct vnode *, struct direct *,
struct componentname *, struct buf *));
int ufs_dirremove __P((struct vnode *, struct inode *, int, int));
int ufs_dirrewrite __P((struct inode *, struct inode *, ino_t, int, int));
int ufs_getlbns __P((struct vnode *, ufs_daddr_t, struct indir *, int *));
struct vnode *
ufs_ihashget __P((dev_t, ino_t));
@ -90,4 +90,17 @@ int ufs_root __P((struct mount *, struct vnode **));
int ufs_start __P((struct mount *, int, struct proc *));
int ufs_vinit __P((struct mount *, vop_t **, vop_t **, struct vnode **));
/*
* Soft update function prototypes.
*/
void softdep_setup_directory_add __P((struct buf *, struct inode *, off_t,
long, struct buf *));
void softdep_change_directoryentry_offset __P((struct inode *, caddr_t,
caddr_t, caddr_t, int));
void softdep_setup_remove __P((struct buf *,struct inode *, struct inode *,
int));
void softdep_setup_directory_change __P((struct buf *, struct inode *,
struct inode *, long, int));
void softdep_increase_linkcnt __P((struct inode *));
#endif /* !_UFS_UFS_EXTERN_H_ */

View File

@ -36,16 +36,22 @@
* SUCH DAMAGE.
*
* @(#)ufs_lookup.c 8.15 (Berkeley) 6/16/95
* $Id: ufs_lookup.c,v 1.20 1998/02/04 22:33:36 eivind Exp $
* $Id: ufs_lookup.c,v 1.21 1998/02/06 12:14:18 eivind Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/namei.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/dir.h>
@ -143,7 +149,12 @@ ufs_lookup(ap)
bp = NULL;
slotoffset = -1;
/*
* XXX there was a soft-update diff about this I couldn't merge.
* I think this was the equiv.
*/
*vpp = NULL;
vdp = ap->a_dvp;
dp = VTOI(vdp);
lockparent = flags & LOCKPARENT;
@ -331,7 +342,7 @@ ufs_lookup(ap)
(nameiop == DELETE &&
(ap->a_cnp->cn_flags & DOWHITEOUT) &&
(ap->a_cnp->cn_flags & ISWHITEOUT))) &&
(flags & ISLASTCN) && dp->i_nlink != 0) {
(flags & ISLASTCN) && dp->i_effnlink != 0) {
/*
* Access for write is interpreted as allowing
* creation of files in the directory.
@ -603,64 +614,66 @@ ufs_dirbadentry(dp, ep, entryoffsetinblock)
}
/*
* Write a directory entry after a call to namei, using the parameters
* that it left in nameidata. The argument ip is the inode which the new
* directory entry will refer to. Dvp is a pointer to the directory to
* be written, which was left locked by namei. Remaining parameters
* (dp->i_offset, dp->i_count) indicate how the space for the new
* entry is to be obtained.
* Construct a new directory entry after a call to namei, using the
* parameters that it left in the componentname argument cnp. The
* argument ip is the inode to which the new directory entry will refer.
*/
int
ufs_direnter(ip, dvp, cnp)
void
ufs_makedirentry(ip, cnp, newdirp)
struct inode *ip;
struct vnode *dvp;
register struct componentname *cnp;
struct componentname *cnp;
struct direct *newdirp;
{
register struct inode *dp;
struct direct newdir;
#ifdef DIAGNOSTIC
if ((cnp->cn_flags & SAVENAME) == 0)
panic("ufs_direnter: missing name");
panic("ufs_makedirentry: missing name");
#endif
dp = VTOI(dvp);
newdir.d_ino = ip->i_number;
newdir.d_namlen = cnp->cn_namelen;
bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
if (!OFSFMT(dvp))
newdir.d_type = IFTODT(ip->i_mode);
newdirp->d_ino = ip->i_number;
newdirp->d_namlen = cnp->cn_namelen;
bcopy(cnp->cn_nameptr, newdirp->d_name, (unsigned)cnp->cn_namelen + 1);
if (ITOV(ip)->v_mount->mnt_maxsymlinklen > 0)
newdirp->d_type = IFTODT(ip->i_mode);
else {
newdir.d_type = 0;
newdirp->d_type = 0;
# if (BYTE_ORDER == LITTLE_ENDIAN)
{ u_char tmp = newdir.d_namlen;
newdir.d_namlen = newdir.d_type;
newdir.d_type = tmp; }
{ u_char tmp = newdirp->d_namlen;
newdirp->d_namlen = newdirp->d_type;
newdirp->d_type = tmp; }
# endif
}
return (ufs_direnter2(dvp, &newdir, cnp->cn_cred, cnp->cn_proc));
}
/*
* Common entry point for directory entry removal used by ufs_direnter
* and ufs_whiteout
* Write a directory entry after a call to namei, using the parameters
* that it left in nameidata. The argument dirp is the new directory
* entry contents. Dvp is a pointer to the directory to be written,
* which was left locked by namei. Remaining parameters (dp->i_offset,
* dp->i_count) indicate how the space for the new entry is to be obtained.
* Non-null bp indicates that a directory is being created (for the
* soft dependency code).
*/
int
ufs_direnter2(dvp, dirp, cr, p)
ufs_direnter(dvp, tvp, dirp, cnp, newdirbp)
struct vnode *dvp;
struct vnode *tvp;
struct direct *dirp;
struct componentname *cnp;
struct buf *newdirbp;
{
struct ucred *cr;
struct proc *p;
{
int newentrysize;
struct inode *dp;
struct buf *bp;
struct iovec aiov;
struct uio auio;
u_int dsize;
struct direct *ep, *nep;
int error, loc, spacefree;
int error, ret, blkoff, loc, spacefree, flags;
char *dirbuf;
p = curproc; /* XXX */
cr = p->p_ucred;
dp = VTOI(dvp);
newentrysize = DIRSIZ(OFSFMT(dvp), dirp);
@ -672,36 +685,55 @@ ufs_direnter2(dvp, dirp, cr, p)
* new entry into a fresh block.
*/
if (dp->i_offset & (DIRBLKSIZ - 1))
panic("ufs_direnter2: newblk");
auio.uio_offset = dp->i_offset;
dirp->d_reclen = DIRBLKSIZ;
auio.uio_resid = newentrysize;
aiov.iov_len = newentrysize;
aiov.iov_base = (caddr_t)dirp;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_rw = UIO_WRITE;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_procp = (struct proc *)0;
error = VOP_WRITE(dvp, &auio, IO_SYNC, cr);
if (DIRBLKSIZ >
VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
/* XXX should grow with balloc() */
panic("ufs_direnter2: frag size");
else if (!error) {
dp->i_size = roundup2(dp->i_size, DIRBLKSIZ);
dp->i_flag |= IN_CHANGE;
panic("ufs_direnter: newblk");
flags = B_CLRBUF;
if (!DOINGSOFTDEP(dvp))
flags |= B_SYNC;
if ((error = VOP_BALLOC(dvp, (off_t)dp->i_offset, DIRBLKSIZ,
cr, flags, &bp)) != 0) {
if (DOINGSOFTDEP(dvp) && newdirbp != NULL)
bdwrite(newdirbp);
return (error);
}
dp->i_size = dp->i_offset + DIRBLKSIZ;
dp->i_flag |= IN_CHANGE | IN_UPDATE;
vnode_pager_setsize(dvp, (u_long)dp->i_size);
dirp->d_reclen = DIRBLKSIZ;
blkoff = dp->i_offset &
(VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_iosize - 1);
bcopy((caddr_t)dirp, (caddr_t)bp->b_data + blkoff,newentrysize);
if (DOINGSOFTDEP(dvp)) {
/*
* Ensure that the entire newly allocated block is a
* valid directory so that future growth within the
* block does not have to ensure that the block is
* written before the inode.
*/
blkoff += DIRBLKSIZ;
while (blkoff < bp->b_bcount) {
((struct direct *)
(bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
blkoff += DIRBLKSIZ;
}
softdep_setup_directory_add(bp, dp, dp->i_offset,
dirp->d_ino, newdirbp);
bdwrite(bp);
} else {
error = VOP_BWRITE(bp);
}
ret = UFS_UPDATE(dvp, &time, &time, !DOINGSOFTDEP(dvp));
if (error == 0)
return (ret);
return (error);
}
/*
* If dp->i_count is non-zero, then namei found space
* for the new entry in the range dp->i_offset to
* dp->i_offset + dp->i_count in the directory.
* To use this space, we may have to compact the entries located
* there, by copying them together towards the beginning of the
* block, leaving the free space in one usable chunk at the end.
* If dp->i_count is non-zero, then namei found space for the new
* entry in the range dp->i_offset to dp->i_offset + dp->i_count
* in the directory. To use this space, we may have to compact
* the entries located there, by copying them together towards the
* beginning of the block, leaving the free space in one usable
* chunk at the end.
*/
/*
@ -717,14 +749,16 @@ ufs_direnter2(dvp, dirp, cr, p)
* Get the block containing the space for the new directory entry.
*/
error = UFS_BLKATOFF(dvp, (off_t)dp->i_offset, &dirbuf, &bp);
if (error)
if (error) {
if (DOINGSOFTDEP(dvp) && newdirbp != NULL)
bdwrite(newdirbp);
return (error);
}
/*
* Find space for the new entry. In the simple case, the entry at
* offset base will have the space. If it does not, then namei
* arranged that compacting the region dp->i_offset to
* dp->i_offset + dp->i_count would yield the
* space.
* dp->i_offset + dp->i_count would yield the space.
*/
ep = (struct direct *)dirbuf;
dsize = DIRSIZ(OFSFMT(dvp), ep);
@ -742,7 +776,11 @@ ufs_direnter2(dvp, dirp, cr, p)
dsize = DIRSIZ(OFSFMT(dvp), nep);
spacefree += nep->d_reclen - dsize;
loc += nep->d_reclen;
bcopy((caddr_t)nep, (caddr_t)ep, dsize);
if (DOINGSOFTDEP(dvp))
softdep_change_directoryentry_offset(dp, dirbuf,
(caddr_t)nep, (caddr_t)ep, dsize);
else
bcopy((caddr_t)nep, (caddr_t)ep, dsize);
}
/*
* Update the pointer fields in the previous entry (if any),
@ -752,26 +790,44 @@ ufs_direnter2(dvp, dirp, cr, p)
(ep->d_ino == WINO &&
bcmp(ep->d_name, dirp->d_name, dirp->d_namlen) == 0)) {
if (spacefree + dsize < newentrysize)
panic("ufs_direnter2: compact1");
panic("ufs_direnter: compact1");
dirp->d_reclen = spacefree + dsize;
} else {
if (spacefree < newentrysize)
panic("ufs_direnter2: compact2");
panic("ufs_direnter: compact2");
dirp->d_reclen = spacefree;
ep->d_reclen = dsize;
ep = (struct direct *)((char *)ep + dsize);
}
bcopy((caddr_t)dirp, (caddr_t)ep, (u_int)newentrysize);
if (dvp->v_mount->mnt_flag & MNT_ASYNC) {
if (DOINGSOFTDEP(dvp)) {
softdep_setup_directory_add(bp, dp,
dp->i_offset + (caddr_t)ep - dirbuf, dirp->d_ino, newdirbp);
bdwrite(bp);
error = 0;
} else {
error = bowrite(bp);
if (dvp->v_mount->mnt_flag & MNT_ASYNC) {
bdwrite(bp);
error = 0;
} else {
error = bowrite(bp);
}
}
dp->i_flag |= IN_CHANGE | IN_UPDATE;
if (!error && dp->i_endoff && dp->i_endoff < dp->i_size)
error = UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr, p);
/*
* If all went well, and the directory can be shortened, proceed
* with the truncation. Note that we have to unlock the inode for
* the entry that we just entered, as the truncation may need to
* lock other inodes which can lead to deadlock if we also hold a
* lock on the newly entered node.
*/
if (error == 0 && dp->i_endoff && dp->i_endoff < dp->i_size) {
if (tvp != NULL)
VOP_UNLOCK(tvp, 0, p);
(void) UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr, p);
if (tvp != NULL)
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, p);
}
return (error);
}
@ -788,18 +844,20 @@ ufs_direnter2(dvp, dirp, cr, p)
* to the size of the previous entry.
*/
int
ufs_dirremove(dvp, cnp)
ufs_dirremove(dvp, ip, flags, isrmdir)
struct vnode *dvp;
struct componentname *cnp;
struct inode *ip;
int flags;
int isrmdir;
{
register struct inode *dp;
struct inode *dp;
struct direct *ep;
struct buf *bp;
int error;
dp = VTOI(dvp);
if (cnp->cn_flags & DOWHITEOUT) {
if (flags & DOWHITEOUT) {
/*
* Whiteout entry: set d_ino to WINO.
*/
@ -808,24 +866,44 @@ ufs_dirremove(dvp, cnp)
return (error);
ep->d_ino = WINO;
ep->d_type = DT_WHT;
error = VOP_BWRITE(bp);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
goto out;
}
if ((error = UFS_BLKATOFF(dvp,
(off_t)(dp->i_offset - dp->i_count), (char **)&ep, &bp)) != 0)
return (error);
if (dp->i_count == 0) {
/*
* First entry in block: set d_ino to zero.
*/
#if 0
error =
UFS_BLKATOFF(dvp, (off_t)dp->i_offset, (char **)&ep, &bp);
if (error)
return (error);
#endif
ep->d_ino = 0;
error = bowrite(bp);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
} else {
/*
* Collapse new free space into previous entry.
*/
ep->d_reclen += dp->i_reclen;
}
out:
if (ip) {
ip->i_effnlink--;
ip->i_flag |= IN_CHANGE;
}
if (DOINGSOFTDEP(dvp)) {
if (ip)
softdep_setup_remove(bp, dp, ip, isrmdir);
bdwrite(bp);
} else {
if (ip)
ip->i_nlink--;
error = bowrite(bp); /* maybe this should be as below? */
}
#if 0
/*
* Collapse new free space into previous entry.
*/
@ -840,6 +918,7 @@ ufs_dirremove(dvp, cnp)
} else {
error = bowrite(bp);
}
#endif
dp->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
}
@ -850,9 +929,11 @@ ufs_dirremove(dvp, cnp)
* set up by a call to namei.
*/
int
ufs_dirrewrite(dp, ip, cnp)
struct inode *dp, *ip;
struct componentname *cnp;
ufs_dirrewrite(dp, oip, newinum, newtype, isrmdir)
struct inode *dp, *oip;
ino_t newinum;
int newtype;
int isrmdir;
{
struct buf *bp;
struct direct *ep;
@ -862,14 +943,22 @@ ufs_dirrewrite(dp, ip, cnp)
error = UFS_BLKATOFF(vdp, (off_t)dp->i_offset, (char **)&ep, &bp);
if (error)
return (error);
ep->d_ino = ip->i_number;
ep->d_ino = newinum;
if (!OFSFMT(vdp))
ep->d_type = IFTODT(ip->i_mode);
if (vdp->v_mount->mnt_flag & MNT_ASYNC) {
ep->d_type = newtype;
oip->i_effnlink--;
oip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vdp)) {
softdep_setup_directory_change(bp, dp, oip, newinum, isrmdir);
bdwrite(bp);
error = 0;
} else {
error = bowrite(bp);
oip->i_nlink--;
if (vdp->v_mount->mnt_flag & MNT_ASYNC) {
bdwrite(bp);
error = 0;
} else {
error = bowrite(bp);
}
}
dp->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
@ -929,7 +1018,7 @@ ufs_dirempty(ip, parentino, cred)
* 1 implies ".", 2 implies ".." if second
* char is also "."
*/
if (namlen == 1)
if (namlen == 1 && dp->d_ino == ip->i_number)
continue;
if (dp->d_name[1] == '.' && dp->d_ino == parentino)
continue;

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_quota.c 8.5 (Berkeley) 5/20/95
* $Id: ufs_quota.c,v 1.18 1998/02/06 12:14:18 eivind Exp $
* $Id: ufs_quota.c,v 1.19 1998/02/09 06:11:12 eivind Exp $
*/
#include <sys/param.h>
@ -425,7 +425,7 @@ quotaon(p, mp, type, fname)
again:
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) {
nextvp = vp->v_mntvnodes.le_next;
if (vp->v_writecount == 0)
if (vp->v_type == VNON || vp->v_writecount == 0)
continue;
if (vget(vp, LK_EXCLUSIVE, p))
goto again;
@ -470,6 +470,8 @@ quotaoff(p, mp, type)
again:
for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nextvp) {
nextvp = vp->v_mntvnodes.le_next;
if (vp->v_type == VNON)
continue;
if (vget(vp, LK_EXCLUSIVE, p))
goto again;
ip = VTOI(vp);
@ -657,6 +659,8 @@ qsync(mp)
if (vp->v_mount != mp)
goto again;
nextvp = vp->v_mntvnodes.le_next;
if (vp->v_type == VNON)
continue;
simple_lock(&vp->v_interlock);
simple_unlock(&mntvnode_slock);
error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95
* $Id: ufs_readwrite.c,v 1.43 1998/02/26 06:39:50 msmith Exp $
* $Id: ufs_readwrite.c,v 1.44 1998/03/07 21:36:42 dyson Exp $
*/
#define BLKSIZE(a, b, c) blksize(a, b, c)
@ -338,10 +338,10 @@ WRITE(ap)
flags |= B_CLRBUF;
else
flags &= ~B_CLRBUF;
error = ffs_balloc(ip,
lbn, blkoffset + xfersize, ap->a_cred, &bp, flags);
if (error)
/* XXX is uio->uio_offset the right thing here? */
error = VOP_BALLOC(vp, uio->uio_offset, xfersize,
ap->a_cred, flags, &bp);
if (error != 0)
break;
if (uio->uio_offset + xfersize > ip->i_size) {

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
* $Id: ufs_vnops.c,v 1.77 1998/02/06 12:14:19 eivind Exp $
* $Id: ufs_vnops.c,v 1.78 1998/02/09 06:11:14 eivind Exp $
*/
#include "opt_quota.h"
@ -59,6 +59,8 @@
#include <sys/poll.h>
#include <vm/vm_zone.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <miscfs/specfs/specdev.h>
#include <miscfs/fifofs/fifo.h>
@ -120,6 +122,18 @@ union _qcvt {
(q) = tmp.qcvt; \
}
/*
* A virgin directory (no blushing please).
*/
static struct dirtemplate mastertemplate = {
0, 12, DT_DIR, 1, ".",
0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
};
static struct odirtemplate omastertemplate = {
0, 12, 1, ".",
0, DIRBLKSIZ - 12, 2, ".."
};
/*
* Create a regular file
*/
@ -273,6 +287,8 @@ ufs_access(ap)
return (error);
#endif
break;
default:
break;
}
}
@ -340,7 +356,7 @@ ufs_getattr(ap)
vap->va_fsid = ip->i_dev;
vap->va_fileid = ip->i_number;
vap->va_mode = ip->i_mode & ~IFMT;
vap->va_nlink = ip->i_nlink;
vap->va_nlink = ip->i_effnlink;
vap->va_uid = ip->i_uid;
vap->va_gid = ip->i_gid;
vap->va_rdev = (dev_t)ip->i_rdev;
@ -444,6 +460,8 @@ ufs_setattr(ap)
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
break;
default:
break;
}
if (error = UFS_TRUNCATE(vp, vap->va_size, 0, cred, p))
return (error);
@ -465,7 +483,7 @@ ufs_setattr(ap)
atimeval.tv_usec = vap->va_atime.tv_nsec / 1000;
mtimeval.tv_sec = vap->va_mtime.tv_sec;
mtimeval.tv_usec = vap->va_mtime.tv_nsec / 1000;
error = UFS_UPDATE(vp, &atimeval, &mtimeval, 1);
error = UFS_UPDATE(vp, &atimeval, &mtimeval, 0);
if (error)
return (error);
}
@ -652,11 +670,7 @@ ufs_remove(ap)
error = EPERM;
goto out;
}
error = ufs_dirremove(dvp, ap->a_cnp);
if (error == 0) {
ip->i_nlink--;
ip->i_flag |= IN_CHANGE;
}
error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
VN_POLLEVENT(vp, POLLNLINK);
VN_POLLEVENT(dvp, POLLWRITE);
out:
@ -685,6 +699,7 @@ ufs_link(ap)
struct proc *p = cnp->cn_proc;
struct inode *ip;
struct timeval tv;
struct direct newdir;
int error;
#ifdef DIAGNOSTIC
@ -711,15 +726,20 @@ ufs_link(ap)
error = EPERM;
goto out1;
}
ip->i_effnlink++;
ip->i_nlink++;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_increase_linkcnt(ip);
gettime(&tv);
error = UFS_UPDATE(vp, &tv, &tv, 1);
error = UFS_UPDATE(vp, &tv, &tv, !DOINGSOFTDEP(vp));
if (!error) {
error = ufs_direnter(ip, tdvp, cnp);
ufs_makedirentry(ip, cnp, &newdir);
error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL);
}
if (error) {
ip->i_effnlink--;
ip->i_nlink--;
ip->i_flag |= IN_CHANGE;
}
@ -770,7 +790,7 @@ ufs_whiteout(ap)
newdir.d_namlen = cnp->cn_namelen;
bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
newdir.d_type = DT_WHT;
error = ufs_direnter2(dvp, &newdir, cnp->cn_cred, cnp->cn_proc);
error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL);
break;
case DELETE:
@ -781,8 +801,10 @@ ufs_whiteout(ap)
#endif
cnp->cn_flags &= ~DOWHITEOUT;
error = ufs_dirremove(dvp, cnp);
error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0);
break;
default:
panic("ufs_whiteout: unknown op");
}
if (cnp->cn_flags & HASBUF) {
zfree(namei_zone, cnp->cn_pnbuf);
@ -834,11 +856,10 @@ ufs_rename(ap)
struct componentname *fcnp = ap->a_fcnp;
struct proc *p = fcnp->cn_proc;
struct inode *ip, *xp, *dp;
struct dirtemplate dirbuf;
struct direct newdir;
struct timeval tv;
int doingdirectory = 0, oldparent = 0, newparent = 0;
int error = 0;
u_char namlen;
#ifdef DIAGNOSTIC
if ((tcnp->cn_flags & HASBUF) == 0 ||
@ -965,10 +986,13 @@ ufs_rename(ap)
* completing our work, the link count
* may be wrong, but correctable.
*/
ip->i_effnlink++;
ip->i_nlink++;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(fvp))
softdep_increase_linkcnt(ip);
gettime(&tv);
if (error = UFS_UPDATE(fvp, &tv, &tv, 1)) {
if (error = UFS_UPDATE(fvp, &tv, &tv, !DOINGSOFTDEP(fvp))) {
VOP_UNLOCK(fvp, 0, p);
goto bad;
}
@ -1027,15 +1051,20 @@ ufs_rename(ap)
error = EMLINK;
goto bad;
}
dp->i_effnlink++;
dp->i_nlink++;
dp->i_flag |= IN_CHANGE;
error = UFS_UPDATE(tdvp, &tv, &tv, 1);
if (DOINGSOFTDEP(tdvp))
softdep_increase_linkcnt(dp);
error = UFS_UPDATE(tdvp, &tv, &tv, !DOINGSOFTDEP(tdvp));
if (error)
goto bad;
}
error = ufs_direnter(ip, tdvp, tcnp);
ufs_makedirentry(ip, tcnp, &newdir);
error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL);
if (error) {
if (doingdirectory && newparent) {
dp->i_effnlink--;
dp->i_nlink--;
dp->i_flag |= IN_CHANGE;
(void)UFS_UPDATE(tdvp, &tv, &tv, 1);
@ -1070,9 +1099,8 @@ ufs_rename(ap)
* (both directories, or both not directories).
*/
if ((xp->i_mode&IFMT) == IFDIR) {
if (! ufs_dirempty
(xp, dp->i_number, tcnp->cn_cred) ||
xp->i_nlink > 2) {
if ((xp->i_effnlink > 2) ||
!ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
error = ENOTEMPTY;
goto bad;
}
@ -1085,40 +1113,37 @@ ufs_rename(ap)
error = EISDIR;
goto bad;
}
error = ufs_dirrewrite(dp, ip, tcnp);
error = ufs_dirrewrite(dp, xp, ip->i_number,
IFTODT(ip->i_mode), doingdirectory);
if (error)
goto bad;
/*
* If the target directory is in the same
* directory as the source directory,
* decrement the link count on the parent
* of the target directory.
*/
if (doingdirectory && !newparent) {
dp->i_nlink--;
if (doingdirectory) {
dp->i_effnlink--;
dp->i_flag |= IN_CHANGE;
xp->i_effnlink--;
xp->i_flag |= IN_CHANGE;
}
VN_POLLEVENT(tdvp, POLLWRITE);
vput(tdvp);
/*
* Adjust the link count of the target to
* reflect the dirrewrite above. If this is
* a directory it is empty and there are
* no links to it, so we can squash the inode and
* any space associated with it. We disallowed
* renaming over top of a directory with links to
* it above, as the remaining link would point to
* a directory without "." or ".." entries.
*/
xp->i_nlink--;
if (doingdirectory) {
if (--xp->i_nlink != 0)
panic("ufs_rename: linked directory");
error = UFS_TRUNCATE(tvp, (off_t)0, IO_SYNC,
tcnp->cn_cred, tcnp->cn_proc);
if (doingdirectory && !DOINGSOFTDEP(tvp)) {
/*
* Truncate inode. The only stuff left in the directory
* is "." and "..". The "." reference is inconsequential
* since we are quashing it. We have removed the "."
* reference and the reference in the parent directory,
* but there may be other hard links. The soft
* dependency code will arrange to do these operations
* after the parent directory entry has been deleted on
* disk, so when running with that code we avoid doing
* them now.
*/
dp->i_nlink--;
xp->i_nlink--;
if ((error = UFS_TRUNCATE(tvp, (off_t)0, IO_SYNC,
tcnp->cn_cred, tcnp->cn_proc)) != 0)
goto bad;
}
xp->i_flag |= IN_CHANGE;
VN_POLLEVENT(tvp, POLLNLINK);
vput(tdvp);
VN_POLLEVENT(tvp, POLLNLINK); /* XXX this right? */
vput(tvp);
xp = NULL;
}
@ -1151,10 +1176,9 @@ ufs_rename(ap)
* changed while the new name has been entered. If the source is
* a file then the entry may have been unlinked or renamed. In
* either case there is no further work to be done. If the source
* is a directory then it cannot have been rmdir'ed; its link
* count of three would cause a rmdir to fail with ENOTEMPTY.
* The IN_RENAME flag ensures that it cannot be moved by another
* rename.
* is a directory then it cannot have been rmdir'ed; the IN_RENAME
* flag ensures that it cannot be moved by another rename or removed
* by a rmdir.
*/
if (xp != ip) {
if (doingdirectory)
@ -1167,44 +1191,11 @@ ufs_rename(ap)
* and ".." set to point to the new parent.
*/
if (doingdirectory && newparent) {
dp->i_nlink--;
dp->i_flag |= IN_CHANGE;
error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
sizeof (struct dirtemplate), (off_t)0,
UIO_SYSSPACE, IO_NODELOCKED,
tcnp->cn_cred, (int *)0, (struct proc *)0);
if (error == 0) {
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (fvp->v_mount->mnt_maxsymlinklen <= 0)
namlen = dirbuf.dotdot_type;
else
namlen = dirbuf.dotdot_namlen;
# else
namlen = dirbuf.dotdot_namlen;
# endif
if (namlen != 2 ||
dirbuf.dotdot_name[0] != '.' ||
dirbuf.dotdot_name[1] != '.') {
ufs_dirbad(xp, (doff_t)12,
"rename: mangled dir");
} else {
dirbuf.dotdot_ino = newparent;
(void) vn_rdwr(UIO_WRITE, fvp,
(caddr_t)&dirbuf,
sizeof (struct dirtemplate),
(off_t)0, UIO_SYSSPACE,
IO_NODELOCKED|IO_SYNC,
tcnp->cn_cred, (int *)0,
(struct proc *)0);
cache_purge(fdvp);
}
}
}
error = ufs_dirremove(fdvp, fcnp);
if (!error) {
xp->i_nlink--;
xp->i_flag |= IN_CHANGE;
xp->i_offset = mastertemplate.dot_reclen;
ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0);
cache_purge(fdvp);
}
error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
xp->i_flag &= ~IN_RENAME;
}
if (dp)
@ -1222,6 +1213,7 @@ ufs_rename(ap)
if (doingdirectory)
ip->i_flag &= ~IN_RENAME;
if (vn_lock(fvp, LK_EXCLUSIVE, p) == 0) {
ip->i_effnlink--;
ip->i_nlink--;
ip->i_flag |= IN_CHANGE;
ip->i_flag &= ~IN_RENAME;
@ -1231,18 +1223,6 @@ ufs_rename(ap)
return (error);
}
/*
* A virgin directory (no blushing please).
*/
static struct dirtemplate mastertemplate = {
0, 12, DT_DIR, 1, { '.', 0 },
0, DIRBLKSIZ - 12, DT_DIR, 2, { '.', '.', 0 }
};
static struct odirtemplate omastertemplate = {
0, 12, 1, { '.', 0 },
0, DIRBLKSIZ - 12, 2, { '.', '.', 0 }
};
/*
* Mkdir system call
*/
@ -1260,7 +1240,9 @@ ufs_mkdir(ap)
register struct componentname *cnp = ap->a_cnp;
register struct inode *ip, *dp;
struct vnode *tvp;
struct buf *bp;
struct dirtemplate dirtemplate, *dtp;
struct direct newdir;
struct timeval tv;
int error, dmode;
@ -1348,25 +1330,31 @@ ufs_mkdir(ap)
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
ip->i_mode = dmode;
tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 2;
ip->i_nlink = 2;
if (DOINGSOFTDEP(tvp))
softdep_increase_linkcnt(ip);
if (cnp->cn_flags & ISWHITEOUT)
ip->i_flags |= UF_OPAQUE;
gettime(&tv);
error = UFS_UPDATE(tvp, &tv, &tv, 1);
/*
* Bump link count in parent directory
* to reflect work done below. Should
* be done before reference is created
* so reparation is possible if we crash.
* Bump link count in parent directory to reflect work done below.
* Should be done before reference is created so cleanup is
* possible if we crash.
*/
dp->i_effnlink++;
dp->i_nlink++;
dp->i_flag |= IN_CHANGE;
error = UFS_UPDATE(dvp, &tv, &tv, 1);
if (DOINGSOFTDEP(dvp))
softdep_increase_linkcnt(dp);
gettime(&tv);
error = UFS_UPDATE(tvp, &tv, &tv, !DOINGSOFTDEP(dvp));
if (error)
goto bad;
/* Initialize directory with "." and ".." from static template. */
/*
* Initialize directory with "." and ".." from static template.
*/
if (dvp->v_mount->mnt_maxsymlinklen > 0
)
dtp = &mastertemplate;
@ -1375,39 +1363,50 @@ ufs_mkdir(ap)
dirtemplate = *dtp;
dirtemplate.dot_ino = ip->i_number;
dirtemplate.dotdot_ino = dp->i_number;
error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (int *)0, (struct proc *)0);
if (error) {
dp->i_nlink--;
dp->i_flag |= IN_CHANGE;
if ((error = VOP_BALLOC(tvp, (off_t)0, DIRBLKSIZ, cnp->cn_cred,
B_CLRBUF, &bp)) != 0)
goto bad;
ip->i_size = DIRBLKSIZ;
ip->i_flag |= IN_CHANGE | IN_UPDATE;
vnode_pager_setsize(tvp, (u_long)ip->i_size);
bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
if ((error = UFS_UPDATE(tvp, &tv, &tv, !DOINGSOFTDEP(tvp))) != 0) {
(void)VOP_BWRITE(bp);
goto bad;
}
if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
else {
ip->i_size = DIRBLKSIZ;
ip->i_flag |= IN_CHANGE;
}
/* Directory set up, now install it's entry in the parent directory. */
error = ufs_direnter(ip, dvp, cnp);
if (error) {
VN_POLLEVENT(dvp, POLLWRITE); /* XXX right place? */
/*
* Directory set up, now install it's entry in the parent directory.
*
* If we are not doing soft dependencies, then we must write out the
* buffer containing the new directory body before entering the new
* name in the parent. If we are doing soft dependencies, then the
* buffer containing the new directory body will be passed to and
* released in the soft dependency code after the code has attached
* an appropriate ordering dependency to the buffer which ensures that
* the buffer is written before the new name is written in the parent.
*/
if (!DOINGSOFTDEP(dvp) && ((error = VOP_BWRITE(bp)) != 0))
goto bad;
ufs_makedirentry(ip, cnp, &newdir);
error = ufs_direnter(dvp, tvp, &newdir, cnp, bp);
bad:
if (error == 0) {
*ap->a_vpp = tvp;
} else {
dp->i_effnlink--;
dp->i_nlink--;
dp->i_flag |= IN_CHANGE;
}
VN_POLLEVENT(dvp, POLLWRITE);
bad:
/*
* No need to do an explicit VOP_TRUNCATE here, vrele will do this
* for us because we set the link count to 0.
*/
if (error) {
/*
* No need to do an explicit VOP_TRUNCATE here, vrele will
* do this for us because we set the link count to 0.
*/
ip->i_effnlink = 0;
ip->i_nlink = 0;
ip->i_flag |= IN_CHANGE;
vput(tvp);
} else
*ap->a_vpp = tvp;
}
out:
zfree(namei_zone, cnp->cn_pnbuf);
vput(dvp);
@ -1435,14 +1434,17 @@ ufs_rmdir(ap)
dp = VTOI(dvp);
/*
* Verify the directory is empty (and valid).
* (Rmdir ".." won't be valid since
* ".." will contain a reference to
* the current directory and thus be
* non-empty.)
* Do not remove a directory that is in the process of being renamed.
* Verify the directory is empty (and valid). Rmdir ".." will not be
* valid since ".." will contain a reference to the current directory
* and thus be non-empty.
*/
error = 0;
if (ip->i_nlink != 2 ||
if (ip->i_flag & IN_RENAME) {
error = EINVAL;
goto out;
}
if (ip->i_effnlink != 2 ||
!ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
error = ENOTEMPTY;
goto out;
@ -1457,34 +1459,36 @@ ufs_rmdir(ap)
* inode. If we crash in between, the directory
* will be reattached to lost+found,
*/
error = ufs_dirremove(dvp, cnp);
error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
if (error)
goto out;
VN_POLLEVENT(dvp, POLLWRITE|POLLNLINK);
dp->i_nlink--;
dp->i_flag |= IN_CHANGE;
cache_purge(dvp);
vput(dvp);
dvp = NULL;
/*
* Truncate inode. The only stuff left
* in the directory is "." and "..". The
* "." reference is inconsequential since
* we're quashing it. The ".." reference
* has already been adjusted above. We've
* removed the "." reference and the reference
* in the parent directory, but there may be
* other hard links so decrement by 2 and
* worry about them later.
* Truncate inode. The only stuff left in the directory is "." and
* "..". The "." reference is inconsequential since we are quashing
* it. We have removed the "." reference and the reference in the
* parent directory, but there may be other hard links. So,
* ufs_dirremove will set the UF_IMMUTABLE flag to ensure that no
* new entries are made. The soft dependency code will arrange to
* do these operations after the parent directory entry has been
* deleted on disk, so when running with that code we avoid doing
* them now.
*/
ip->i_nlink -= 2;
error = UFS_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
cnp->cn_proc);
cache_purge(ITOV(ip));
VN_POLLEVENT(vp, POLLNLINK);
dp->i_effnlink--;
dp->i_flag |= IN_CHANGE;
ip->i_effnlink--;
ip->i_flag |= IN_CHANGE;
if (!DOINGSOFTDEP(vp)) {
dp->i_nlink--;
ip->i_nlink--;
error = UFS_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
cnp->cn_proc);
}
cache_purge(vp);
out:
if (dvp)
vput(dvp);
vput(dvp);
VN_POLLEVENT(vp, POLLNLINK);
vput(vp);
return (error);
}
@ -1974,7 +1978,7 @@ ufs_vinit(mntp, specops, fifoops, vpp)
}
if (ip->i_number == ROOTINO)
vp->v_flag |= VROOT;
vp->v_flag |= VROOT;
/*
* Initialize modrev times
*/
@ -1995,6 +1999,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
struct componentname *cnp;
{
register struct inode *ip, *pdir;
struct direct newdir;
struct timeval tv;
struct vnode *tvp;
int error;
@ -2078,7 +2083,10 @@ ufs_makeinode(mode, dvp, vpp, cnp)
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
ip->i_mode = mode;
tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 1;
ip->i_nlink = 1;
if (DOINGSOFTDEP(tvp))
softdep_increase_linkcnt(ip);
if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
suser(cnp->cn_cred, NULL))
ip->i_mode &= ~ISGID;
@ -2090,10 +2098,11 @@ ufs_makeinode(mode, dvp, vpp, cnp)
* Make sure inode goes to disk before directory entry.
*/
gettime(&tv);
error = UFS_UPDATE(tvp, &tv, &tv, 1);
error = UFS_UPDATE(tvp, &tv, &tv, !DOINGSOFTDEP(tvp));
if (error)
goto bad;
error = ufs_direnter(ip, dvp, cnp);
ufs_makedirentry(ip, cnp, &newdir);
error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL);
if (error)
goto bad;
@ -2110,6 +2119,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
*/
zfree(namei_zone, cnp->cn_pnbuf);
vput(dvp);
ip->i_effnlink = 0;
ip->i_nlink = 0;
ip->i_flag |= IN_CHANGE;
vput(tvp);