diff options
author | jeff <jeff@FreeBSD.org> | 2013-05-31 00:43:41 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2013-05-31 00:43:41 +0000 |
commit | d7efebc4db8c1b875c915fb1a2759cb9df4f2956 (patch) | |
tree | 47c74a9a8f1d3fbea9e54f402b3cf363e92546a4 /sys/ufs | |
parent | 7c988b2ec361d43cc84f05e89080a923a7101a76 (diff) | |
download | FreeBSD-src-d7efebc4db8c1b875c915fb1a2759cb9df4f2956.zip FreeBSD-src-d7efebc4db8c1b875c915fb1a2759cb9df4f2956.tar.gz |
- Convert the bufobj lock to rwlock.
- Use a shared bufobj lock in getblk() and inmem().
- Convert softdep's lk to rwlock to match the bufobj lock.
- Move INFREECNT to b_flags and protect it with the buf lock.
- Remove unnecessary locking around bremfree() and BKGRDINPROG.
Sponsored by: EMC / Isilon Storage Division
Discussed with: mckusick, kib, mdf
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ffs/ffs_inode.c | 1 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 7 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 121 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 4 |
4 files changed, 67 insertions, 66 deletions
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index 4571a1c..608f876 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/resourcevar.h> +#include <sys/rwlock.h> #include <sys/vmmeter.h> #include <sys/stat.h> diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 0c653c2..9a9c88a 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include <sys/mount.h> #include <sys/resource.h> #include <sys/resourcevar.h> +#include <sys/rwlock.h> #include <sys/vnode.h> #include <geom/geom.h> @@ -2204,10 +2205,8 @@ ffs_bdflush(bo, bp) if (bp_bdskip) { VI_LOCK(devvp); if (!ffs_bp_snapblk(vp, nbp)) { - if (BO_MTX(bo) != VI_MTX(vp)) { - VI_UNLOCK(devvp); - BO_LOCK(bo); - } + VI_UNLOCK(devvp); + BO_LOCK(bo); BUF_UNLOCK(nbp); continue; } diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 0e9248d..9ec7b46 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include <sys/namei.h> #include <sys/priv.h> #include <sys/proc.h> +#include <sys/rwlock.h> #include <sys/stat.h> #include <sys/sysctl.h> #include <sys/syslog.h> @@ -554,7 +555,7 @@ softdep_check_suspend(struct mount *mp, (void) softdep_accdeps; bo = &devvp->v_bufobj; - ASSERT_BO_LOCKED(bo); + ASSERT_BO_WLOCKED(bo); MNT_ILOCK(mp); while (mp->mnt_secondary_writes != 0) { @@ -808,7 +809,7 @@ struct jextent { */ static void softdep_error(char *, int); static void drain_output(struct vnode *); -static struct buf *getdirtybuf(struct buf *, struct mtx *, int); +static struct buf *getdirtybuf(struct buf *, struct rwlock *, int); static void clear_remove(void); static void clear_inodedeps(void); static void unlinked_inodedep(struct mount *, struct inodedep *); @@ -1030,12 +1031,12 @@ static void softdep_disk_write_complete(struct buf *); static void softdep_deallocate_dependencies(struct buf *); static int softdep_count_dependencies(struct buf *bp, int); -static struct mtx lk; -MTX_SYSINIT(softdep_lock, &lk, "Softdep Lock", MTX_DEF); +static struct rwlock lk; +RW_SYSINIT(softdep_lock, &lk, "Softdep Lock"); -#define TRY_ACQUIRE_LOCK(lk) mtx_trylock(lk) -#define ACQUIRE_LOCK(lk) mtx_lock(lk) -#define FREE_LOCK(lk) mtx_unlock(lk) +#define TRY_ACQUIRE_LOCK(lk) rw_try_wlock(lk) +#define ACQUIRE_LOCK(lk) rw_wlock(lk) +#define FREE_LOCK(lk) rw_wunlock(lk) #define BUF_AREC(bp) lockallowrecurse(&(bp)->b_lock) #define BUF_NOREC(bp) lockdisablerecurse(&(bp)->b_lock) @@ -1073,7 +1074,7 @@ worklist_insert(head, item, locked) { if (locked) - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); if (item->wk_state & ONWORKLIST) panic("worklist_insert: %p %s(0x%X) already on list", item, TYPENAME(item->wk_type), item->wk_state); @@ -1088,7 +1089,7 @@ worklist_remove(item, locked) { if (locked) - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); if ((item->wk_state & ONWORKLIST) == 0) panic("worklist_remove: %p %s(0x%X) not on list", item, TYPENAME(item->wk_type), item->wk_state); @@ -1161,7 +1162,7 @@ jwork_move(dst, src) freedep = freedep_merge(WK_FREEDEP(wk), freedep); } - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); while ((wk = LIST_FIRST(src)) != NULL) { WORKLIST_REMOVE(wk); WORKLIST_INSERT(dst, wk); @@ -1212,7 +1213,7 @@ workitem_free(item, type) int type; { struct ufsmount *ump; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); #ifdef DEBUG if (item->wk_state & ONWORKLIST) @@ -1428,7 +1429,7 @@ softdep_flush(void) static void worklist_speedup(void) { - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); if (req_pending == 0) { req_pending = 1; wakeup(&req_pending); @@ -1462,7 +1463,7 @@ add_to_worklist(wk, flags) { struct ufsmount *ump; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); ump = VFSTOUFS(wk->wk_mp); if (wk->wk_state & ONWORKLIST) panic("add_to_worklist: %s(0x%X) already on list", @@ -1604,7 +1605,7 @@ process_removes(vp) struct mount *mp; ino_t inum; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); mp = vp->v_mount; inum = VTOI(vp)->i_number; @@ -1654,7 +1655,7 @@ process_truncates(vp) ino_t inum; int cgwait; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); mp = vp->v_mount; inum = VTOI(vp)->i_number; @@ -1727,7 +1728,7 @@ process_worklist_item(mp, target, flags) int matchcnt; int error; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); KASSERT(mp != NULL, ("process_worklist_item: NULL mp")); /* * If we are being called because of a process doing a @@ -2061,7 +2062,7 @@ pagedep_lookup(mp, bp, ino, lbn, flags, pagedeppp) int ret; int i; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); if (bp) { LIST_FOREACH(wk, &bp->b_dep, wk_list) { if (wk->wk_type == D_PAGEDEP) { @@ -2150,7 +2151,7 @@ inodedep_lookup(mp, inum, flags, inodedeppp) struct inodedep_hashhead *inodedephd; struct fs *fs; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); fs = VFSTOUFS(mp)->um_fs; inodedephd = INODEDEP_HASH(fs, inum); @@ -2704,7 +2705,7 @@ add_to_journal(wk) { struct ufsmount *ump; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); ump = VFSTOUFS(wk->wk_mp); if (wk->wk_state & ONWORKLIST) panic("add_to_journal: %s(0x%X) already on list", @@ -2730,7 +2731,7 @@ remove_from_journal(wk) { struct ufsmount *ump; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); ump = VFSTOUFS(wk->wk_mp); #ifdef SUJ_DEBUG { @@ -2898,7 +2899,7 @@ softdep_prelink(dvp, vp) struct ufsmount *ump; ump = VFSTOUFS(dvp->v_mount); - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); /* * Nothing to do if we have sufficient journal space. * If we currently hold the snapshot lock, we must avoid @@ -4986,7 +4987,7 @@ bmsafemap_lookup(mp, bp, cg, newbmsafemap) struct worklist *wk; struct fs *fs; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); KASSERT(bp != NULL, ("bmsafemap_lookup: missing buffer")); LIST_FOREACH(wk, &bp->b_dep, wk_list) { if (wk->wk_type == D_BMSAFEMAP) { @@ -5257,7 +5258,7 @@ allocdirect_merge(adphead, newadp, oldadp) struct freefrag *freefrag; freefrag = NULL; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); if (newadp->ad_oldblkno != oldadp->ad_newblkno || newadp->ad_oldsize != oldadp->ad_newsize || newadp->ad_offset >= NDADDR) @@ -5718,7 +5719,7 @@ indirdep_lookup(mp, ip, bp) struct fs *fs; ufs2_daddr_t blkno; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); indirdep = NULL; newindirdep = NULL; fs = ip->i_fs; @@ -5797,7 +5798,7 @@ setup_allocindir_phase2(bp, ip, inodedep, aip, lbn) struct freefrag *freefrag; struct mount *mp; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); mp = UFSTOVFS(ip->i_ump); fs = ip->i_fs; if (bp->b_lblkno >= 0) @@ -6130,7 +6131,7 @@ complete_trunc_indir(freework) BUF_UNLOCK(bp); ACQUIRE_LOCK(&lk); } - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); freework->fw_state |= DEPCOMPLETE; TAILQ_REMOVE(&indirdep->ir_trunc, freework, fw_next); /* @@ -6874,7 +6875,7 @@ restart: bp->b_vflags |= BV_SCANNED; continue; } - if ((bp = getdirtybuf(bp, BO_MTX(bo), MNT_WAIT)) == NULL) + if ((bp = getdirtybuf(bp, BO_LOCKPTR(bo), MNT_WAIT)) == NULL) goto restart; BO_UNLOCK(bo); if (deallocate_dependencies(bp, freeblks, blkoff)) @@ -6899,14 +6900,12 @@ cleanrestart: } if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, - BO_MTX(bo)) == ENOLCK) { + BO_LOCKPTR(bo)) == ENOLCK) { BO_LOCK(bo); goto cleanrestart; } bp->b_vflags |= BV_SCANNED; - BO_LOCK(bo); bremfree(bp); - BO_UNLOCK(bo); if (blkoff != 0) { allocbuf(bp, blkoff); bqrelse(bp); @@ -7220,7 +7219,7 @@ free_newblk(newblk) KASSERT(newblk->nb_jnewblk == NULL, ("free_newblk; jnewblk %p still attached", newblk->nb_jnewblk)); - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); newblk_freefrag(newblk); if (newblk->nb_state & ONDEPLIST) LIST_REMOVE(newblk, nb_deps); @@ -7250,7 +7249,7 @@ free_newdirblk(newdirblk) struct diradd *dap; struct worklist *wk; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); WORKLIST_REMOVE(&newdirblk->db_list); /* * If the pagedep is still linked onto the directory buffer @@ -7381,7 +7380,7 @@ check_inode_unwritten(inodedep) struct inodedep *inodedep; { - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); if ((inodedep->id_state & (DEPCOMPLETE | UNLINKED)) != 0 || !LIST_EMPTY(&inodedep->id_dirremhd) || @@ -7429,7 +7428,7 @@ free_inodedep(inodedep) struct inodedep *inodedep; { - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); if ((inodedep->id_state & (ONWORKLIST | UNLINKED)) != 0 || (inodedep->id_state & ALLCOMPLETE) != ALLCOMPLETE || !LIST_EMPTY(&inodedep->id_dirremhd) || @@ -7472,7 +7471,7 @@ freework_freeblock(freework) int bsize; int needj; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); /* * Handle partial truncate separately. */ @@ -8578,7 +8577,7 @@ free_diradd(dap, wkhd) struct inodedep *inodedep; struct mkdir *mkdir, *nextmd; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); LIST_REMOVE(dap, da_pdlist); if (dap->da_state & ONWORKLIST) WORKLIST_REMOVE(&dap->da_list); @@ -9198,7 +9197,7 @@ first_unlinked_inodedep(ump) struct inodedep *inodedep; struct inodedep *idp; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); for (inodedep = TAILQ_LAST(&ump->softdep_unlinked, inodedeplst); inodedep; inodedep = idp) { if ((inodedep->id_state & UNLINKNEXT) == 0) @@ -9247,7 +9246,7 @@ handle_written_sbdep(sbdep, bp) struct mount *mp; struct fs *fs; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); fs = sbdep->sb_fs; mp = UFSTOVFS(sbdep->sb_ump); /* @@ -9289,7 +9288,7 @@ unlinked_inodedep(mp, inodedep) { struct ufsmount *ump; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); if (MOUNTEDSUJ(mp) == 0) return; ump = VFSTOUFS(mp); @@ -9323,7 +9322,7 @@ clear_unlinked_inodedep(inodedep) ino = inodedep->id_ino; error = 0; for (;;) { - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); KASSERT((inodedep->id_state & UNLINKED) != 0, ("clear_unlinked_inodedep: inodedep %p not unlinked", inodedep)); @@ -12444,7 +12443,7 @@ flush_deplist(listhead, waitfor, errorp) struct newblk *newblk; struct buf *bp; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); TAILQ_FOREACH(adp, listhead, ad_next) { newblk = (struct newblk *)adp; if (newblk->nb_jnewblk != NULL) { @@ -12536,7 +12535,7 @@ flush_newblk_dep(vp, mp, lbn) bp = gbincore(bo, lbn); if (bp != NULL) { error = BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL | - LK_INTERLOCK, BO_MTX(bo)); + LK_INTERLOCK, BO_LOCKPTR(bo)); if (error == ENOLCK) { ACQUIRE_LOCK(&lk); continue; /* Slept, retry */ @@ -12922,7 +12921,7 @@ request_cleanup(mp, resource) struct thread *td = curthread; struct ufsmount *ump; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); /* * We never hold up the filesystem syncer or buf daemon. */ @@ -13031,7 +13030,7 @@ clear_remove(void) int error, cnt; ino_t ino; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); for (cnt = 0; cnt <= pagedep_hash; cnt++) { pagedephd = &pagedep_hashtbl[next++]; @@ -13090,7 +13089,7 @@ clear_inodedeps(void) int error, cnt; ino_t firstino, lastino, ino; - mtx_assert(&lk, MA_OWNED); + rw_assert(&lk, RA_WLOCKED); /* * Pick a random inode dependency to be cleared. * We will then gather up all the inodes in its block @@ -13372,57 +13371,57 @@ out: * Return acquired buffer or NULL on failure. */ static struct buf * -getdirtybuf(bp, mtx, waitfor) +getdirtybuf(bp, lock, waitfor) struct buf *bp; - struct mtx *mtx; + struct rwlock *lock; int waitfor; { int error; - mtx_assert(mtx, MA_OWNED); + rw_assert(lock, RA_WLOCKED); if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL) != 0) { if (waitfor != MNT_WAIT) return (NULL); error = BUF_LOCK(bp, - LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, mtx); + LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, lock); /* * Even if we sucessfully acquire bp here, we have dropped - * mtx, which may violates our guarantee. + * lock, which may violates our guarantee. */ if (error == 0) BUF_UNLOCK(bp); else if (error != ENOLCK) panic("getdirtybuf: inconsistent lock: %d", error); - mtx_lock(mtx); + rw_wlock(lock); return (NULL); } if ((bp->b_vflags & BV_BKGRDINPROG) != 0) { - if (mtx == &lk && waitfor == MNT_WAIT) { - mtx_unlock(mtx); + if (lock == &lk && waitfor == MNT_WAIT) { + rw_wunlock(lock); BO_LOCK(bp->b_bufobj); BUF_UNLOCK(bp); if ((bp->b_vflags & BV_BKGRDINPROG) != 0) { bp->b_vflags |= BV_BKGRDWAIT; - msleep(&bp->b_xflags, BO_MTX(bp->b_bufobj), + msleep(&bp->b_xflags, BO_LOCKPTR(bp->b_bufobj), PRIBIO | PDROP, "getbuf", 0); } else BO_UNLOCK(bp->b_bufobj); - mtx_lock(mtx); + rw_wlock(lock); return (NULL); } BUF_UNLOCK(bp); if (waitfor != MNT_WAIT) return (NULL); /* - * The mtx argument must be bp->b_vp's mutex in + * The lock argument must be bp->b_vp's mutex in * this case. */ #ifdef DEBUG_VFS_LOCKS if (bp->b_vp->v_type != VCHR) - ASSERT_BO_LOCKED(bp->b_bufobj); + ASSERT_BO_WLOCKED(bp->b_bufobj); #endif bp->b_vflags |= BV_BKGRDWAIT; - msleep(&bp->b_xflags, mtx, PRIBIO, "getbuf", 0); + rw_sleep(&bp->b_xflags, lock, PRIBIO, "getbuf", 0); return (NULL); } if ((bp->b_flags & B_DELWRI) == 0) { @@ -13454,7 +13453,7 @@ softdep_check_suspend(struct mount *mp, ump = VFSTOUFS(mp); bo = &devvp->v_bufobj; - ASSERT_BO_LOCKED(bo); + ASSERT_BO_WLOCKED(bo); for (;;) { if (!TRY_ACQUIRE_LOCK(&lk)) { @@ -13532,12 +13531,12 @@ drain_output(vp) bo = &vp->v_bufobj; ASSERT_VOP_LOCKED(vp, "drain_output"); - ASSERT_BO_LOCKED(bo); + ASSERT_BO_WLOCKED(bo); while (bo->bo_numoutput) { bo->bo_flag |= BO_WWAIT; msleep((caddr_t)&bo->bo_numoutput, - BO_MTX(bo), PRIBIO + 1, "drainvp", 0); + BO_LOCKPTR(bo), PRIBIO + 1, "drainvp", 0); } } diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index d4c035f..57f092c 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/ioccom.h> #include <sys/malloc.h> #include <sys/mutex.h> +#include <sys/rwlock.h> #include <security/mac/mac_framework.h> @@ -2076,7 +2077,8 @@ ffs_bufwrite(struct buf *bp) return (0); } bp->b_vflags |= BV_BKGRDWAIT; - msleep(&bp->b_xflags, BO_MTX(bp->b_bufobj), PRIBIO, "bwrbg", 0); + msleep(&bp->b_xflags, BO_LOCKPTR(bp->b_bufobj), PRIBIO, + "bwrbg", 0); if (bp->b_vflags & BV_BKGRDINPROG) panic("bufwrite: still writing"); } |