diff --git a/sys/ufs/lfs/lfs.h b/sys/ufs/lfs/lfs.h index 85ce4486d364..aa6d7d8eb356 100644 --- a/sys/ufs/lfs/lfs.h +++ b/sys/ufs/lfs/lfs.h @@ -1,4 +1,4 @@ -/* $NetBSD: lfs.h,v 1.58 2003/03/15 06:58:49 perseant Exp $ */ +/* $NetBSD: lfs.h,v 1.59 2003/03/21 06:16:53 perseant Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -284,8 +284,9 @@ extern struct lfs_log_entry lfs_log[LFS_LOGLENGTH]; * How to find out whether a vnode had dirty buffers or pages, * to know whether it needs to retain IN_MODIFIED after a write. */ -int lfs_checkifempty(struct vnode *); -#define VPISEMPTY(vp) lfs_checkifempty(vp) +#define VPISEMPTY(vp) (LIST_EMPTY(&(vp)->v_dirtyblkhd) && \ + !((vp)->v_flag & VONWORKLST)) + /* * WRITEINPROG does not use VPISEMPTY because any dirty pages will * have been given buffer headers, if they are "in progress". diff --git a/sys/ufs/lfs/lfs_segment.c b/sys/ufs/lfs/lfs_segment.c index 9e3987d217f9..667bb6f6e04f 100644 --- a/sys/ufs/lfs/lfs_segment.c +++ b/sys/ufs/lfs/lfs_segment.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_segment.c,v 1.113 2003/03/20 14:17:21 yamt Exp $ */ +/* $NetBSD: lfs_segment.c,v 1.114 2003/03/21 06:16:54 perseant Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.113 2003/03/20 14:17:21 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.114 2003/03/21 06:16:54 perseant Exp $"); #define ivndebug(vp,str) printf("ino %d: %s\n",VTOI(vp)->i_number,(str)) @@ -538,7 +538,7 @@ lfs_segwrite(struct mount *mp, int flags) struct vnode *vp; SEGUSE *segusep; daddr_t ibno; - int do_ckp, did_ckp, error, i; + int do_ckp, did_ckp, error, i, s; int writer_set = 0; int dirty; int redo; @@ -676,6 +676,7 @@ lfs_segwrite(struct mount *mp, int flags) * for other parts of the Ifile to be dirty after the loop * above, since we hold the segment lock. */ + s = splbio(); if (LIST_EMPTY(&vp->v_dirtyblkhd)) { LFS_CLR_UINO(ip, IN_ALLMOD); } @@ -690,6 +691,7 @@ lfs_segwrite(struct mount *mp, int flags) } } #endif + splx(s); } else { (void) lfs_writeseg(fs, sp); } @@ -2187,14 +2189,10 @@ lfs_cluster_aiodone(struct buf *bp) * the locked list to be written again. */ vp = tbp->b_vp; + if ((tbp->b_flags & (B_LOCKED | B_DELWRI)) == B_LOCKED) LFS_UNLOCK_BUF(tbp); -#if 0 - else if (vp != devvp) - printf("dirtied while busy?! bp %p, ino %d, lbn %d\n", - tbp, vp ? VTOI(vp)->i_number : -1, - tbp->b_lblkno); -#endif + tbp->b_flags &= ~B_GATHERED; LFS_BCLEAN_LOG(fs, tbp); diff --git a/sys/ufs/lfs/lfs_vfsops.c b/sys/ufs/lfs/lfs_vfsops.c index 1bbece0891b7..185cef14593e 100644 --- a/sys/ufs/lfs/lfs_vfsops.c +++ b/sys/ufs/lfs/lfs_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vfsops.c,v 1.108 2003/03/21 06:09:08 yamt Exp $ */ +/* $NetBSD: lfs_vfsops.c,v 1.109 2003/03/21 06:16:55 perseant Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.108 2003/03/21 06:09:08 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.109 2003/03/21 06:16:55 perseant Exp $"); #if defined(_KERNEL_OPT) #include "opt_quota.h" @@ -1345,6 +1345,7 @@ lfs_unmount(struct mount *mp, int mntflags, struct proc *p) struct ufsmount *ump; struct lfs *fs; int error, flags, ronly; + int s; flags = 0; if (mntflags & MNT_FORCE) @@ -1373,13 +1374,10 @@ lfs_unmount(struct mount *mp, int mntflags, struct proc *p) return (error); if ((error = VFS_SYNC(mp, 1, p->p_ucred, p)) != 0) return (error); + s = splbio(); if (LIST_FIRST(&fs->lfs_ivnode->v_dirtyblkhd)) panic("lfs_unmount: still dirty blocks on ifile vnode"); - - /* Explicitly write the superblock, to update serial and pflags */ - fs->lfs_pflags |= LFS_PF_CLEAN; - lfs_writesuper(fs, fs->lfs_sboffs[0]); - lfs_writesuper(fs, fs->lfs_sboffs[1]); + splx(s); /* Comment on ifile size if it has become too large */ if (!(fs->lfs_flags & LFS_WARNED)) { @@ -1396,14 +1394,17 @@ lfs_unmount(struct mount *mp, int mntflags, struct proc *p) bufpages / LFS_MAX_BYTES); } + /* Explicitly write the superblock, to update serial and pflags */ + fs->lfs_pflags |= LFS_PF_CLEAN; + lfs_writesuper(fs, fs->lfs_sboffs[0]); + lfs_writesuper(fs, fs->lfs_sboffs[1]); + while (fs->lfs_iocount) + tsleep(&fs->lfs_iocount, PRIBIO + 1, "lfs_umount", 0); + /* Finish with the Ifile, now that we're done with it */ vrele(fs->lfs_ivnode); vgone(fs->lfs_ivnode); - /* Wait for superblock writes to complete */ - while (fs->lfs_iocount) - tsleep(&fs->lfs_iocount, PRIBIO + 1, "lfs_umount", 0); - ronly = !fs->lfs_ronly; if (ump->um_devvp->v_type != VBAD) ump->um_devvp->v_specmountpoint = NULL; diff --git a/sys/ufs/lfs/lfs_vnops.c b/sys/ufs/lfs/lfs_vnops.c index 726d09a58c44..4aca0fcb72a4 100644 --- a/sys/ufs/lfs/lfs_vnops.c +++ b/sys/ufs/lfs/lfs_vnops.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vnops.c,v 1.96 2003/03/15 06:58:51 perseant Exp $ */ +/* $NetBSD: lfs_vnops.c,v 1.97 2003/03/21 06:16:56 perseant Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.96 2003/03/15 06:58:51 perseant Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.97 2003/03/21 06:16:56 perseant Exp $"); #include #include @@ -361,6 +361,15 @@ lfs_inactive(void *v) lfs_unmark_vnode(ap->a_vp); + /* + * The Ifile is only ever inactivated on unmount. + * Streamline this process by not giving it more dirty blocks. + */ + if (VTOI(ap->a_vp)->i_number == LFS_IFILE_INUM) { + LFS_CLR_UINO(VTOI(ap->a_vp), IN_ALLMOD); + return 0; + } + return ufs_inactive(v); } @@ -914,7 +923,11 @@ lfs_close(void *v) struct inode *ip = VTOI(vp); struct timespec ts; - if (vp->v_usecount > 1) { + if (vp == ip->i_lfs->lfs_ivnode && + vp->v_mount->mnt_flag & MNT_UNMOUNT) + return 0; + + if (vp->v_usecount > 1 && vp != ip->i_lfs->lfs_ivnode) { TIMEVAL_TO_TIMESPEC(&time, &ts); LFS_ITIMES(ip, &ts, &ts, &ts); } @@ -1311,6 +1324,10 @@ lfs_getpages(void *v) int a_flags; } */ *ap = v; + if (VTOI(ap->a_vp)->i_number == LFS_IFILE_INUM && + (ap->a_access_type & VM_PROT_WRITE) != 0) { + return EPERM; + } if ((ap->a_access_type & VM_PROT_WRITE) != 0) { LFS_SET_UINO(VTOI(ap->a_vp), IN_MODIFIED); } @@ -1857,61 +1874,6 @@ lfs_putpages(void *v) return error; } -/* - * Find out whether the vnode has any blocks or pages waiting to be written. - * We used to just check LIST_EMPTY(&vp->v_dirtyblkhd), but there is not - * presently as simple a mechanism for the page cache. - */ -int -lfs_checkifempty(struct vnode *vp) -{ - struct vm_page *pg; - struct buf *bp; - int r, s; - - if (vp->v_type != VREG || VTOI(vp)->i_number == LFS_IFILE_INUM) - return LIST_EMPTY(&vp->v_dirtyblkhd); - - /* - * For vnodes with pages it is a little more complex. - * Pages that have been written (i.e. are "clean" for our purposes) - * might be in seemingly dirty buffers, so we have to troll - * looking for indirect block buffers as well as pages. - */ - simple_lock(&vp->v_interlock); - s = splbio(); - for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; - bp = LIST_NEXT(bp, b_vnbufs)) { - if (bp->b_lblkno < 0) { - splx(s); - simple_unlock(&vp->v_interlock); - return 0; - } - } - splx(s); - - /* - * Run through the page list to find dirty pages. - * Right now I just walk the memq. - */ - pg = TAILQ_FIRST(&vp->v_uobj.memq); - r = 1; - while(pg) { - if ((pg->flags & PG_CLEAN) == 0 || pmap_is_modified(pg)) { - r = 0; - break; - } - pg = TAILQ_NEXT(pg, listq); - } -#if 0 - if (r != !(vp->v_flag & VONWORKLST)) { - printf("nope, VONWORKLST isn't good enough!\n"); - } -#endif - simple_unlock(&vp->v_interlock); - return r; -} - /* * Return the last logical file offset that should be written for this file * if we're doing a write that ends at "size". If writing, we need to know