Fixes to the softdep code from Ethan Solomita <ethan@geocast.com>.

* Fix buffer ordering when it has dependencies.
* Alleviate memory problems.
* Deal with some recursive vnode locks (sigh).
* Fix other bugs.
This commit is contained in:
fvdl 2000-02-14 22:00:21 +00:00
parent b5df4bcc84
commit fe39281ea4
12 changed files with 571 additions and 291 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_vnops.c,v 1.38 1999/08/31 12:30:36 bouyer Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.39 2000/02/14 22:00:21 fvdl Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -596,3 +596,31 @@ vn_closefile(fp, p)
return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
fp->f_cred, p));
}
/*
* Enable LK_CANRECURSE on lock. Return prior status.
*/
u_int
vn_setrecurse(vp)
struct vnode *vp;
{
struct lock *lkp = &vp->v_lock;
u_int retval = lkp->lk_flags & LK_CANRECURSE;
lkp->lk_flags |= LK_CANRECURSE;
return retval;
}
/*
* Called when done with locksetrecurse.
*/
void
vn_restorerecurse(vp, flags)
struct vnode *vp;
u_int flags;
{
struct lock *lkp = &vp->v_lock;
lkp->lk_flags &= ~LK_CANRECURSE;
lkp->lk_flags |= flags;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.h,v 1.40 2000/02/14 20:12:02 thorpej Exp $ */
/* $NetBSD: buf.h,v 1.41 2000/02/14 22:00:22 fvdl Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@ -160,6 +160,8 @@ extern struct bio_ops {
void (*io_deallocate) __P((struct buf *));
int (*io_fsync) __P((struct vnode *));
int (*io_sync) __P((struct mount *));
void (*io_movedeps) __P((struct buf *, struct buf *));
int (*io_countdeps) __P((struct buf *, int));
} bioops;
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: vnode.h,v 1.68 2000/01/20 19:06:14 wrstuden Exp $ */
/* $NetBSD: vnode.h,v 1.69 2000/02/14 22:00:22 fvdl Exp $ */
/*
* Copyright (c) 1989, 1993
@ -513,6 +513,8 @@ int vn_ioctl __P((struct file *fp, u_long com, caddr_t data,
int vn_fcntl __P((struct file *fp, u_int com, caddr_t data,
struct proc *p));
int vn_lock __P((struct vnode *vp, int flags));
u_int vn_setrecurse __P((struct vnode *vp));
void vn_restorerecurse __P((struct vnode *vp, u_int flags));
int vn_open __P((struct nameidata *ndp, int fmode, int cmode));
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,

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_alloc.c,v 1.30 1999/11/15 18:49:13 fvdl Exp $ */
/* $NetBSD: ffs_alloc.c,v 1.31 2000/02/14 22:00:22 fvdl Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -682,7 +682,7 @@ ffs_blkpref(ip, lbn, indx, bap)
fs = ip->i_fs;
if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
if (lbn < NDADDR) {
if (lbn < NDADDR + NINDIR(fs)) {
cg = ino_to_cg(fs, ip->i_number);
return (fs->fs_fpg * cg + fs->fs_frag);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_balloc.c,v 1.15 1999/11/15 18:49:13 fvdl Exp $ */
/* $NetBSD: ffs_balloc.c,v 1.16 2000/02/14 22:00:22 fvdl Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -348,7 +348,15 @@ fail:
/*
* If we have failed part way through block allocation, we
* have to deallocate any indirect blocks that we have allocated.
* We have to fsync the file before we start to get rid of all
* of its dependencies so that we do not leave them dangling.
* We have to sync it at the end so that the soft updates code
* does not find any untracked changes. Although this is really
* slow, running out of disk space is not expected to be a common
* occurence. The error return from fsync is ignored as we already
* have an error to return to the user.
*/
(void) VOP_FSYNC(vp, cred, MNT_WAIT, curproc);
for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) {
ffs_blkfree(ip, *blkp, fs->fs_bsize);
deallocated += fs->fs_bsize;
@ -365,5 +373,6 @@ fail:
ip->i_ffs_blocks -= btodb(deallocated);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
}
(void) VOP_FSYNC(vp, cred, MNT_WAIT, curproc);
return (error);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_extern.h,v 1.13 1999/11/15 18:49:13 fvdl Exp $ */
/* $NetBSD: ffs_extern.h,v 1.14 2000/02/14 22:00:22 fvdl Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -141,16 +141,13 @@ __END_DECLS
* Soft dependency 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((void *));
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,
@ -159,8 +156,6 @@ 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 *));
void softdep_fsync_mountdev __P((struct vnode *));
int softdep_sync_metadata __P((void *));

View File

@ -192,11 +192,11 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
}
void
softdep_increase_linkcnt(ip)
softdep_change_linkcnt(ip)
struct inode *ip;
{
panic("softdep_increase_linkcnt called");
panic("softdep_change_linkcnt called");
}
void
@ -217,15 +217,6 @@ softdep_update_inodeblock(ip, bp, waitfor)
panic("softdep_update_inodeblock called");
}
int
softdep_fsync(vp)
struct vnode *vp;
{
panic("softdep_fsync called");
return (EIO);
}
void
softdep_fsync_mountdev(vp)
struct vnode *vp;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_vfsops.c,v 1.56 1999/12/10 14:36:04 drochner Exp $ */
/* $NetBSD: ffs_vfsops.c,v 1.57 2000/02/14 22:00:23 fvdl Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@ -886,9 +886,11 @@ loop:
simple_lock(&vp->v_interlock);
nvp = vp->v_mntvnodes.le_next;
ip = VTOI(vp);
if ((vp->v_type == VNON || (ip->i_flag &
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0) &&
(vp->v_dirtyblkhd.lh_first == NULL || waitfor == MNT_LAZY)){
if (vp->v_type == VNON ||
((ip->i_flag &
(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
vp->v_dirtyblkhd.lh_first == NULL))
{
simple_unlock(&vp->v_interlock);
continue;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_extern.h,v 1.21 1999/11/15 18:49:15 fvdl Exp $ */
/* $NetBSD: ufs_extern.h,v 1.22 2000/02/14 22:00:23 fvdl Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -171,6 +171,6 @@ 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 *));
void softdep_change_linkcnt __P((struct inode *));
__END_DECLS

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_lookup.c,v 1.27 1999/11/15 18:49:15 fvdl Exp $ */
/* $NetBSD: ufs_lookup.c,v 1.28 2000/02/14 22:00:23 fvdl Exp $ */
/*
* Copyright (c) 1989, 1993
@ -491,7 +491,11 @@ found:
*vpp = vdp;
return (0);
}
if (flags & ISDOTDOT)
VOP_UNLOCK(vdp, 0); /* race to get the inode */
error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp);
if (flags & ISDOTDOT)
vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY);
if (error)
return (error);
/*
@ -531,7 +535,11 @@ found:
*/
if (dp->i_number == dp->i_ino)
return (EISDIR);
if (flags & ISDOTDOT)
VOP_UNLOCK(vdp, 0); /* race to get the inode */
error = VFS_VGET(vdp->v_mount, dp->i_ino, &tdp);
if (flags & ISDOTDOT)
vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY);
if (error)
return (error);
*vpp = tdp;
@ -970,17 +978,19 @@ ufs_dirremove(dvp, ip, flags, isrmdir)
+ dp->i_reclen, UFS_MPNEEDSWAP(dvp->v_mount));
}
out:
if (ip) {
ip->i_ffs_effnlink--;
ip->i_flag |= IN_CHANGE;
}
if (DOINGSOFTDEP(dvp)) {
if (ip)
if (ip) {
ip->i_ffs_effnlink--;
softdep_change_linkcnt(ip);
softdep_setup_remove(bp, dp, ip, isrmdir);
}
bdwrite(bp);
} else {
if (ip)
if (ip) {
ip->i_ffs_effnlink--;
ip->i_ffs_nlink--;
ip->i_flag |= IN_CHANGE;
}
error = VOP_BWRITE(bp);
}
dp->i_flag |= IN_CHANGE | IN_UPDATE;
@ -1011,12 +1021,13 @@ ufs_dirrewrite(dp, oip, newinum, newtype, isrmdir)
if (vdp->v_mount->mnt_maxsymlinklen > 0)
ep->d_type = newtype;
oip->i_ffs_effnlink--;
oip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vdp)) {
softdep_change_linkcnt(oip);
softdep_setup_directory_change(bp, dp, oip, newinum, isrmdir);
bdwrite(bp);
} else {
oip->i_ffs_nlink--;
oip->i_flag |= IN_CHANGE;
error = VOP_BWRITE(bp);
}
dp->i_flag |= IN_CHANGE | IN_UPDATE;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ufs_vnops.c,v 1.61 1999/12/13 19:07:21 wrstuden Exp $ */
/* $NetBSD: ufs_vnops.c,v 1.62 2000/02/14 22:00:23 fvdl Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993, 1995
@ -675,7 +675,7 @@ ufs_link(v)
ip->i_ffs_nlink++;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_increase_linkcnt(ip);
softdep_change_linkcnt(ip);
error = VOP_UPDATE(vp, NULL, NULL, !DOINGSOFTDEP(vp));
if (!error) {
ufs_makedirentry(ip, cnp, &newdir);
@ -685,6 +685,8 @@ ufs_link(v)
ip->i_ffs_effnlink--;
ip->i_ffs_nlink--;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_change_linkcnt(ip);
}
FREE(cnp->cn_pnbuf, M_NAMEI);
out1:
@ -912,7 +914,7 @@ abortit:
ip->i_ffs_effnlink++;
ip->i_ffs_nlink++;
if (DOINGSOFTDEP(fvp))
softdep_increase_linkcnt(ip);
softdep_change_linkcnt(ip);
ip->i_flag |= IN_CHANGE;
if ((error = VOP_UPDATE(fvp, NULL, NULL, !DOINGSOFTDEP(fvp))) != 0) {
VOP_UNLOCK(fvp, 0);
@ -975,12 +977,14 @@ abortit:
dp->i_ffs_nlink++;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_increase_linkcnt(dp);
softdep_change_linkcnt(dp);
if ((error = VOP_UPDATE(tdvp, NULL, NULL,
!DOINGSOFTDEP(tdvp))) != 0) {
dp->i_ffs_effnlink--;
dp->i_ffs_nlink--;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(dp);
goto bad;
}
}
@ -991,6 +995,8 @@ abortit:
dp->i_ffs_effnlink--;
dp->i_ffs_nlink--;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(dp);
(void)VOP_UPDATE(tdvp, NULL, NULL, 1);
}
goto bad;
@ -1043,10 +1049,12 @@ abortit:
if (doingdirectory) {
if (!newparent) {
dp->i_ffs_effnlink--;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(dp);
}
xp->i_ffs_effnlink--;
xp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(xp);
}
if (doingdirectory && !DOINGSOFTDEP(tvp)) {
/*
@ -1060,9 +1068,12 @@ abortit:
* disk, so when running with that code we avoid doing
* them now.
*/
if (!newparent)
if (!newparent) {
dp->i_ffs_nlink--;
dp->i_flag |= IN_CHANGE;
}
xp->i_ffs_nlink--;
xp->i_flag |= IN_CHANGE;
if ((error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
tcnp->cn_cred, tcnp->cn_proc)))
goto bad;
@ -1136,9 +1147,11 @@ out:
if (doingdirectory)
ip->i_flag &= ~IN_RENAME;
if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
ip->i_ffs_nlink--;
ip->i_ffs_effnlink--;
ip->i_ffs_nlink--;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(fvp))
softdep_change_linkcnt(ip);
vput(fvp);
} else
vrele(fvp);
@ -1206,10 +1219,10 @@ ufs_mkdir(v)
ip->i_ffs_effnlink = 2;
ip->i_ffs_nlink = 2;
if (DOINGSOFTDEP(tvp))
softdep_increase_linkcnt(ip);
softdep_change_linkcnt(ip);
if (cnp->cn_flags & ISWHITEOUT)
ip->i_ffs_flags |= UF_OPAQUE;
error = VOP_UPDATE(tvp, NULL, NULL, !DOINGSOFTDEP(tvp));
error = VOP_UPDATE(tvp, NULL, NULL, MNT_WAIT);
/*
* Bump link count in parent directory to reflect work done below.
@ -1220,7 +1233,7 @@ ufs_mkdir(v)
dp->i_ffs_nlink++;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(dvp))
softdep_increase_linkcnt(dp);
softdep_change_linkcnt(dp);
if ((error = VOP_UPDATE(dvp, NULL, NULL, !DOINGSOFTDEP(dvp))) != 0)
goto bad;
@ -1295,6 +1308,8 @@ bad:
dp->i_ffs_effnlink--;
dp->i_ffs_nlink--;
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(dvp))
softdep_change_linkcnt(dp);
/*
* No need to do an explicit VOP_TRUNCATE here, vrele will
* do this for us because we set the link count to 0.
@ -1302,6 +1317,8 @@ bad:
ip->i_ffs_effnlink = 0;
ip->i_ffs_nlink = 0;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
vput(tvp);
}
out:
@ -1366,26 +1383,35 @@ ufs_rmdir(v)
* inode. If we crash in between, the directory
* will be reattached to lost+found,
*/
if ((error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1)) != 0)
dp->i_ffs_effnlink--;
ip->i_ffs_effnlink--;
if (DOINGSOFTDEP(vp)) {
softdep_change_linkcnt(dp);
softdep_change_linkcnt(ip);
}
error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
if (error) {
dp->i_ffs_effnlink++;
ip->i_ffs_effnlink++;
if (DOINGSOFTDEP(vp)) {
softdep_change_linkcnt(dp);
softdep_change_linkcnt(ip);
}
goto out;
}
cache_purge(dvp);
/*
* Truncate inode. The only stuff left in the directory is "." and
* "..". The "." reference is inconsequential since we're quashing
* it. We've removed the "." reference and the reference in the
* parent directory, but there may be other hard links. The soft
* update 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.
* it. 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_ffs_effnlink--;
dp->i_flag |= IN_CHANGE;
ip->i_ffs_effnlink--;
ip->i_flag |= IN_CHANGE;
if (!DOINGSOFTDEP(vp)) {
dp->i_ffs_nlink--;
dp->i_flag |= IN_CHANGE;
ip->i_ffs_nlink--;
ip->i_flag |= IN_CHANGE;
error = VOP_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
cnp->cn_proc);
}
@ -1972,7 +1998,7 @@ ufs_makeinode(mode, dvp, vpp, cnp)
ip->i_ffs_effnlink = 1;
ip->i_ffs_nlink = 1;
if (DOINGSOFTDEP(tvp))
softdep_increase_linkcnt(ip);
softdep_change_linkcnt(ip);
if ((ip->i_ffs_mode & ISGID) &&
!groupmember(ip->i_ffs_gid, cnp->cn_cred) &&
suser(cnp->cn_cred, NULL))
@ -2005,6 +2031,8 @@ bad:
ip->i_ffs_effnlink = 0;
ip->i_ffs_nlink = 0;
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(ip);
vput(tvp);
return (error);
}