Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/ufs/ffs/ffs_vnops.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/ufs/ffs/ffs_vnops.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.86.4.5 retrieving revision 1.86.4.10 diff -u -p -r1.86.4.5 -r1.86.4.10 --- src/sys/ufs/ffs/ffs_vnops.c 2007/06/08 14:18:16 1.86.4.5 +++ src/sys/ufs/ffs/ffs_vnops.c 2007/08/24 23:28:45 1.86.4.10 @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_vnops.c,v 1.86.4.5 2007/06/08 14:18:16 ad Exp $ */ +/* $NetBSD: ffs_vnops.c,v 1.86.4.10 2007/08/24 23:28:45 ad Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.86.4.5 2007/06/08 14:18:16 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.86.4.10 2007/08/24 23:28:45 ad Exp $"); #include #include @@ -101,16 +101,16 @@ const struct vnodeopv_entry_desc ffs_vno { &vop_abortop_desc, ufs_abortop }, /* abortop */ { &vop_inactive_desc, ufs_inactive }, /* inactive */ { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ - { &vop_lock_desc, ufs_lock }, /* lock */ - { &vop_unlock_desc, ufs_unlock }, /* unlock */ + { &vop_lock_desc, ffs_lock }, /* lock */ + { &vop_unlock_desc, ffs_unlock }, /* unlock */ { &vop_bmap_desc, ufs_bmap }, /* bmap */ { &vop_strategy_desc, ufs_strategy }, /* strategy */ { &vop_print_desc, ufs_print }, /* print */ - { &vop_islocked_desc, ufs_islocked }, /* islocked */ + { &vop_islocked_desc, ffs_islocked }, /* islocked */ { &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ { &vop_advlock_desc, ufs_advlock }, /* advlock */ { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ - { &vop_getpages_desc, ffs_getpages }, /* getpages */ + { &vop_getpages_desc, genfs_getpages }, /* getpages */ { &vop_putpages_desc, genfs_putpages }, /* putpages */ { &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ { &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ @@ -156,12 +156,12 @@ const struct vnodeopv_entry_desc ffs_spe { &vop_abortop_desc, spec_abortop }, /* abortop */ { &vop_inactive_desc, ufs_inactive }, /* inactive */ { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ - { &vop_lock_desc, ufs_lock }, /* lock */ - { &vop_unlock_desc, ufs_unlock }, /* unlock */ + { &vop_lock_desc, ffs_lock }, /* lock */ + { &vop_unlock_desc, ffs_unlock }, /* unlock */ { &vop_bmap_desc, spec_bmap }, /* bmap */ { &vop_strategy_desc, spec_strategy }, /* strategy */ { &vop_print_desc, ufs_print }, /* print */ - { &vop_islocked_desc, ufs_islocked }, /* islocked */ + { &vop_islocked_desc, ffs_islocked }, /* islocked */ { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ { &vop_advlock_desc, spec_advlock }, /* advlock */ { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ @@ -211,12 +211,12 @@ const struct vnodeopv_entry_desc ffs_fif { &vop_abortop_desc, fifo_abortop }, /* abortop */ { &vop_inactive_desc, ufs_inactive }, /* inactive */ { &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ - { &vop_lock_desc, ufs_lock }, /* lock */ - { &vop_unlock_desc, ufs_unlock }, /* unlock */ + { &vop_lock_desc, ffs_lock }, /* lock */ + { &vop_unlock_desc, ffs_unlock }, /* unlock */ { &vop_bmap_desc, fifo_bmap }, /* bmap */ { &vop_strategy_desc, fifo_strategy }, /* strategy */ { &vop_print_desc, ufs_print }, /* print */ - { &vop_islocked_desc, ufs_islocked }, /* islocked */ + { &vop_islocked_desc, ffs_islocked }, /* islocked */ { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ { &vop_advlock_desc, fifo_advlock }, /* advlock */ { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ @@ -290,29 +290,26 @@ ffs_fsync(void *v) if (error) goto out; - mutex_enter(&bqueue_lock); + mutex_enter(&bufcache_lock); for (i = 0; i < num; i++) { if ((bp = incore(vp, ia[i].in_lbn)) == NULL) continue; - mutex_enter(&bp->b_interlock); - if ((bp->b_flags & (B_BUSY | B_DELWRI)) != B_DELWRI) { - mutex_exit(&bp->b_interlock); + if ((bp->b_cflags & BC_BUSY) != 0 || + (bp->b_oflags & BO_DELWRI) == 0) continue; - } - bp->b_flags |= B_BUSY | B_VFLUSH; - mutex_exit(&bp->b_interlock); - mutex_exit(&bqueue_lock); + bp->b_cflags |= BC_BUSY | BC_VFLUSH; + mutex_exit(&bufcache_lock); bawrite(bp); - mutex_enter(&bqueue_lock); + mutex_enter(&bufcache_lock); } - mutex_exit(&bqueue_lock); + mutex_exit(&bufcache_lock); } if (ap->a_flags & FSYNC_WAIT) { - mutex_enter(&global_v_numoutput_lock); + mutex_enter(&vp->v_interlock); while (vp->v_numoutput > 0) - cv_wait(&vp->v_outputcv, &global_v_numoutput_lock); - mutex_exit(&global_v_numoutput_lock); + cv_wait(&vp->v_cv, &vp->v_interlock); + mutex_exit(&vp->v_interlock); } error = ffs_update(vp, NULL, NULL, @@ -354,15 +351,16 @@ ffs_full_fsync(void *v) (vp->v_specmountpoint->mnt_flag & MNT_SOFTDEP)) softdep_fsync_mountdev(vp); + mutex_enter(&vp->v_interlock); + inodedeps_only = DOINGSOFTDEP(vp) && (ap->a_flags & FSYNC_RECLAIM) - && vp->v_uobj.uo_npages == 0 && LIST_EMPTY(&vp->v_dirtyblkhd); + && UVM_OBJ_IS_CLEAN(&vp->v_uobj) && LIST_EMPTY(&vp->v_dirtyblkhd); /* * Flush all dirty data associated with a vnode. */ if (vp->v_type == VREG || vp->v_type == VBLK) { - mutex_enter(&vp->v_interlock); error = VOP_PUTPAGES(vp, 0, 0, PGO_ALLPAGES | PGO_CLEANIT | ((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0) | (fstrans_getstate(vp->v_mount) == FSTRANS_SUSPENDING ? @@ -370,34 +368,31 @@ ffs_full_fsync(void *v) if (error) { return error; } - } + } else + mutex_exit(&vp->v_interlock); passes = NIADDR + 1; skipmeta = 0; if (ap->a_flags & FSYNC_WAIT) skipmeta = 1; + mutex_enter(&bufcache_lock); + mutex_enter(&vp->v_interlock); loop: LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) { - mutex_enter(&bp->b_interlock); - bp->b_flags &= ~B_SCANNED; - mutex_exit(&bp->b_interlock); + bp->b_cflags &= ~BC_SCANNED; } for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { nbp = LIST_NEXT(bp, b_vnbufs); - mutex_enter(&bp->b_interlock); - if (bp->b_flags & (B_BUSY | B_SCANNED)) { - mutex_exit(&bp->b_interlock); + if (bp->b_cflags & (BC_BUSY | BC_SCANNED)) continue; - } - if ((bp->b_flags & B_DELWRI) == 0) + if ((bp->b_oflags & BO_DELWRI) == 0) panic("ffs_fsync: not dirty"); - if (skipmeta && bp->b_lblkno < 0) { - mutex_exit(&bp->b_interlock); + if (skipmeta && bp->b_lblkno < 0) continue; - } - bp->b_flags |= B_BUSY | B_VFLUSH | B_SCANNED; - mutex_exit(&bp->b_interlock); + mutex_exit(&vp->v_interlock); + bp->b_cflags |= BC_BUSY | BC_VFLUSH | BC_SCANNED; + mutex_exit(&bufcache_lock); /* * On our final pass through, do all I/O synchronously * so that we can find out if our flush is failing @@ -408,21 +403,24 @@ loop: else if ((error = bwrite(bp)) != 0) return (error); /* - * Since we may have slept during the I/O, we need + * Since we unlocked during the I/O, we need * to start from a known point. */ + mutex_enter(&bufcache_lock); + mutex_enter(&vp->v_interlock); nbp = LIST_FIRST(&vp->v_dirtyblkhd); } if (skipmeta) { skipmeta = 0; goto loop; } + mutex_exit(&bufcache_lock); + if (ap->a_flags & FSYNC_WAIT) { - mutex_enter(&global_v_numoutput_lock); while (vp->v_numoutput) { - cv_wait(&vp->v_outputcv, &global_v_numoutput_lock); + cv_wait(&vp->v_cv, &vp->v_interlock); } - mutex_exit(&global_v_numoutput_lock); + mutex_exit(&vp->v_interlock); /* * Ensure that any filesystem metadata associated @@ -449,7 +447,8 @@ loop: vprint("ffs_fsync: dirty", vp); #endif } - } + } else + mutex_exit(&vp->v_interlock); if (inodedeps_only) waitfor = 0; @@ -512,6 +511,7 @@ ffs_reclaim(void *v) return (0); } +#if 0 int ffs_getpages(void *v) { @@ -546,6 +546,7 @@ ffs_getpages(void *v) } return genfs_getpages(v); } +#endif /* * Return the last logical file offset that should be written for this file @@ -723,3 +724,70 @@ ffs_deleteextattr(void *v) /* XXX Not implemented for UFS2 file systems. */ return (EOPNOTSUPP); } + +/* + * Lock the node. + */ +int +ffs_lock(void *v) +{ + struct vop_lock_args /* { + struct vnode *a_vp; + int a_flags; + } */ *ap = v; + struct vnode *vp = ap->a_vp; + struct mount *mp = vp->v_mount; + + /* + * Fake lock during file system suspension. + */ + if ((vp->v_type == VREG || vp->v_type == VDIR) && + fstrans_is_owner(mp) && + fstrans_getstate(mp) == FSTRANS_SUSPENDING) { + if ((ap->a_flags & LK_INTERLOCK) != 0) + mutex_exit(&vp->v_interlock); + return 0; + } + return (lockmgr(vp->v_vnlock, ap->a_flags, &vp->v_interlock)); +} + +/* + * Unlock the node. + */ +int +ffs_unlock(void *v) +{ + struct vop_unlock_args /* { + struct vnode *a_vp; + int a_flags; + } */ *ap = v; + struct vnode *vp = ap->a_vp; + struct mount *mp = vp->v_mount; + + /* + * Fake unlock during file system suspension. + */ + if ((vp->v_type == VREG || vp->v_type == VDIR) && + fstrans_is_owner(mp) && + fstrans_getstate(mp) == FSTRANS_SUSPENDING) { + if ((ap->a_flags & LK_INTERLOCK) != 0) + mutex_exit(&vp->v_interlock); + return 0; + } + return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE, + &vp->v_interlock)); +} + +/* + * Return whether or not the node is locked. + */ +int +ffs_islocked(void *v) +{ + struct vop_islocked_args /* { + struct vnode *a_vp; + } */ *ap = v; + struct vnode *vp = ap->a_vp; + + return (lockstatus(vp->v_vnlock)); +}