Move the syncer linkage from vnode to bufobj.
This is not quite a perfect separation: the syncer still think it knows that everything is a vnode.
This commit is contained in:
parent
d83b7498a4
commit
20eba72f53
@ -193,11 +193,11 @@ int prtactive;
|
||||
*/
|
||||
static int syncer_delayno;
|
||||
static long syncer_mask;
|
||||
LIST_HEAD(synclist, vnode);
|
||||
LIST_HEAD(synclist, bufobj);
|
||||
static struct synclist *syncer_workitem_pending;
|
||||
/*
|
||||
* The sync_mtx protects:
|
||||
* vp->v_synclist
|
||||
* bo->bo_synclist
|
||||
* sync_vnode_count
|
||||
* syncer_delayno
|
||||
* syncer_state
|
||||
@ -831,6 +831,7 @@ getnewvnode(tag, mp, vops, vpp)
|
||||
VI_LOCK(vp);
|
||||
vp->v_dd = vp;
|
||||
bo = &vp->v_bufobj;
|
||||
bo->bo_private = vp;
|
||||
bo->bo_mtx = &vp->v_interlock;
|
||||
vp->v_vnlock = &vp->v_lock;
|
||||
lockinit(vp->v_vnlock, PVFS, tag, VLKTIMEOUT, LK_NOPAUSE);
|
||||
@ -927,8 +928,8 @@ vinvalbuf(vp, flags, cred, td, slpflag, slptimeo)
|
||||
|
||||
ASSERT_VOP_LOCKED(vp, "vinvalbuf");
|
||||
|
||||
VI_LOCK(vp);
|
||||
bo = &vp->v_bufobj;
|
||||
BO_LOCK(bo);
|
||||
if (flags & V_SAVE) {
|
||||
error = bufobj_wwait(bo, slpflag, slptimeo);
|
||||
if (error) {
|
||||
@ -1397,39 +1398,39 @@ brelvp(struct buf *bp)
|
||||
/*
|
||||
* Delete from old vnode list, if on one.
|
||||
*/
|
||||
vp = bp->b_vp;
|
||||
VI_LOCK(vp);
|
||||
vp = bp->b_vp; /* XXX */
|
||||
bo = bp->b_bufobj;
|
||||
BO_LOCK(bo);
|
||||
if (bp->b_xflags & (BX_VNDIRTY | BX_VNCLEAN))
|
||||
buf_vlist_remove(bp);
|
||||
if ((vp->v_iflag & VI_ONWORKLST) && bo->bo_dirty.bv_cnt == 0) {
|
||||
vp->v_iflag &= ~VI_ONWORKLST;
|
||||
if ((bo->bo_flag & BO_ONWORKLST) && bo->bo_dirty.bv_cnt == 0) {
|
||||
bo->bo_flag &= ~BO_ONWORKLST;
|
||||
mtx_lock(&sync_mtx);
|
||||
LIST_REMOVE(vp, v_synclist);
|
||||
LIST_REMOVE(bo, bo_synclist);
|
||||
syncer_worklist_len--;
|
||||
mtx_unlock(&sync_mtx);
|
||||
}
|
||||
vdropl(vp);
|
||||
bp->b_vp = NULL;
|
||||
bp->b_bufobj = NULL;
|
||||
VI_UNLOCK(vp);
|
||||
BO_UNLOCK(bo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an item to the syncer work queue.
|
||||
*/
|
||||
static void
|
||||
vn_syncer_add_to_worklist(struct vnode *vp, int delay)
|
||||
vn_syncer_add_to_worklist(struct bufobj *bo, int delay)
|
||||
{
|
||||
int slot;
|
||||
|
||||
ASSERT_VI_LOCKED(vp, "vn_syncer_add_to_worklist");
|
||||
ASSERT_BO_LOCKED(bo);
|
||||
|
||||
mtx_lock(&sync_mtx);
|
||||
if (vp->v_iflag & VI_ONWORKLST)
|
||||
LIST_REMOVE(vp, v_synclist);
|
||||
if (bo->bo_flag & BO_ONWORKLST)
|
||||
LIST_REMOVE(bo, bo_synclist);
|
||||
else {
|
||||
vp->v_iflag |= VI_ONWORKLST;
|
||||
bo->bo_flag |= BO_ONWORKLST;
|
||||
syncer_worklist_len++;
|
||||
}
|
||||
|
||||
@ -1437,7 +1438,7 @@ vn_syncer_add_to_worklist(struct vnode *vp, int delay)
|
||||
delay = syncer_maxdelay - 2;
|
||||
slot = (syncer_delayno + delay) & syncer_mask;
|
||||
|
||||
LIST_INSERT_HEAD(&syncer_workitem_pending[slot], vp, v_synclist);
|
||||
LIST_INSERT_HEAD(&syncer_workitem_pending[slot], bo, bo_synclist);
|
||||
mtx_unlock(&sync_mtx);
|
||||
}
|
||||
|
||||
@ -1474,6 +1475,7 @@ sched_sync(void)
|
||||
struct synclist *next;
|
||||
struct synclist *slp;
|
||||
struct vnode *vp;
|
||||
struct bufobj *bo;
|
||||
struct mount *mp;
|
||||
long starttime;
|
||||
struct thread *td = FIRST_THREAD_IN_PROC(updateproc);
|
||||
@ -1549,16 +1551,17 @@ sched_sync(void)
|
||||
last_work_seen = syncer_delayno;
|
||||
if (net_worklist_len > 0 && syncer_state == SYNCER_FINAL_DELAY)
|
||||
syncer_state = SYNCER_SHUTTING_DOWN;
|
||||
while ((vp = LIST_FIRST(slp)) != NULL) {
|
||||
while ((bo = LIST_FIRST(slp)) != NULL) {
|
||||
vp = bo->bo_private; /* XXX */
|
||||
if (VOP_ISLOCKED(vp, NULL) != 0 ||
|
||||
vn_start_write(vp, &mp, V_NOWAIT) != 0) {
|
||||
LIST_REMOVE(vp, v_synclist);
|
||||
LIST_INSERT_HEAD(next, vp, v_synclist);
|
||||
LIST_REMOVE(bo, bo_synclist);
|
||||
LIST_INSERT_HEAD(next, bo, bo_synclist);
|
||||
continue;
|
||||
}
|
||||
if (VI_TRYLOCK(vp) == 0) {
|
||||
LIST_REMOVE(vp, v_synclist);
|
||||
LIST_INSERT_HEAD(next, vp, v_synclist);
|
||||
LIST_REMOVE(bo, bo_synclist);
|
||||
LIST_INSERT_HEAD(next, bo, bo_synclist);
|
||||
vn_finished_write(mp);
|
||||
continue;
|
||||
}
|
||||
@ -1575,14 +1578,14 @@ sched_sync(void)
|
||||
VOP_UNLOCK(vp, 0, td);
|
||||
vn_finished_write(mp);
|
||||
VI_LOCK(vp);
|
||||
if ((vp->v_iflag & VI_ONWORKLST) != 0) {
|
||||
if ((bo->bo_flag & BO_ONWORKLST) != 0) {
|
||||
/*
|
||||
* Put us back on the worklist. The worklist
|
||||
* routine will remove us from our current
|
||||
* position and then add us back in at a later
|
||||
* position.
|
||||
*/
|
||||
vn_syncer_add_to_worklist(vp, syncdelay);
|
||||
vn_syncer_add_to_worklist(bo, syncdelay);
|
||||
}
|
||||
vdropl(vp);
|
||||
VI_UNLOCK(vp);
|
||||
@ -1759,7 +1762,7 @@ reassignbuf(struct buf *bp)
|
||||
* of clean buffers.
|
||||
*/
|
||||
if (bp->b_flags & B_DELWRI) {
|
||||
if ((vp->v_iflag & VI_ONWORKLST) == 0) {
|
||||
if ((bo->bo_flag & BO_ONWORKLST) == 0) {
|
||||
switch (vp->v_type) {
|
||||
case VDIR:
|
||||
delay = dirdelay;
|
||||
@ -1770,18 +1773,18 @@ reassignbuf(struct buf *bp)
|
||||
default:
|
||||
delay = filedelay;
|
||||
}
|
||||
vn_syncer_add_to_worklist(vp, delay);
|
||||
vn_syncer_add_to_worklist(bo, delay);
|
||||
}
|
||||
buf_vlist_add(bp, bo, BX_VNDIRTY);
|
||||
} else {
|
||||
buf_vlist_add(bp, bo, BX_VNCLEAN);
|
||||
|
||||
if ((vp->v_iflag & VI_ONWORKLST) && bo->bo_dirty.bv_cnt == 0) {
|
||||
if ((bo->bo_flag & BO_ONWORKLST) && bo->bo_dirty.bv_cnt == 0) {
|
||||
mtx_lock(&sync_mtx);
|
||||
LIST_REMOVE(vp, v_synclist);
|
||||
LIST_REMOVE(bo, bo_synclist);
|
||||
syncer_worklist_len--;
|
||||
mtx_unlock(&sync_mtx);
|
||||
vp->v_iflag &= ~VI_ONWORKLST;
|
||||
bo->bo_flag &= ~BO_ONWORKLST;
|
||||
}
|
||||
}
|
||||
VI_UNLOCK(vp);
|
||||
@ -3329,7 +3332,8 @@ vfs_allocate_syncvnode(mp)
|
||||
next = start;
|
||||
}
|
||||
VI_LOCK(vp);
|
||||
vn_syncer_add_to_worklist(vp, syncdelay > 0 ? next % syncdelay : 0);
|
||||
vn_syncer_add_to_worklist(&vp->v_bufobj,
|
||||
syncdelay > 0 ? next % syncdelay : 0);
|
||||
/* XXX - vn_syncer_add_to_worklist() also grabs and drops sync_mtx. */
|
||||
mtx_lock(&sync_mtx);
|
||||
sync_vnode_count++;
|
||||
@ -3355,6 +3359,7 @@ sync_fsync(ap)
|
||||
struct mount *mp = syncvp->v_mount;
|
||||
struct thread *td = ap->a_td;
|
||||
int error, asyncflag;
|
||||
struct bufobj *bo;
|
||||
|
||||
/*
|
||||
* We only need to do something if this is a lazy evaluation.
|
||||
@ -3365,9 +3370,10 @@ sync_fsync(ap)
|
||||
/*
|
||||
* Move ourselves to the back of the sync list.
|
||||
*/
|
||||
VI_LOCK(syncvp);
|
||||
vn_syncer_add_to_worklist(syncvp, syncdelay);
|
||||
VI_UNLOCK(syncvp);
|
||||
bo = &syncvp->v_bufobj;
|
||||
BO_LOCK(bo);
|
||||
vn_syncer_add_to_worklist(bo, syncdelay);
|
||||
BO_UNLOCK(bo);
|
||||
|
||||
/*
|
||||
* Walk the list of vnodes pushing all that are dirty and
|
||||
@ -3421,16 +3427,18 @@ sync_reclaim(ap)
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct bufobj *bo;
|
||||
|
||||
VI_LOCK(vp);
|
||||
bo = &vp->v_bufobj;
|
||||
vp->v_mount->mnt_syncer = NULL;
|
||||
if (vp->v_iflag & VI_ONWORKLST) {
|
||||
if (bo->bo_flag & BO_ONWORKLST) {
|
||||
mtx_lock(&sync_mtx);
|
||||
LIST_REMOVE(vp, v_synclist);
|
||||
LIST_REMOVE(bo, bo_synclist);
|
||||
syncer_worklist_len--;
|
||||
sync_vnode_count--;
|
||||
mtx_unlock(&sync_mtx);
|
||||
vp->v_iflag &= ~VI_ONWORKLST;
|
||||
bo->bo_flag &= ~BO_ONWORKLST;
|
||||
}
|
||||
VI_UNLOCK(vp);
|
||||
|
||||
|
@ -48,6 +48,7 @@ struct buf;
|
||||
struct bufobj;
|
||||
struct mount;
|
||||
struct vnode;
|
||||
struct uio;
|
||||
|
||||
/*
|
||||
* To avoid including <ufs/ffs/softdep.h>
|
||||
@ -398,6 +399,7 @@ struct cluster_save {
|
||||
static __inline int
|
||||
bwrite(struct buf *bp)
|
||||
{
|
||||
|
||||
KASSERT(bp->b_bufobj != NULL, ("bwrite: no bufobj bp=%p", bp));
|
||||
KASSERT(bp->b_bufobj->bo_ops != NULL, ("bwrite: no bo_ops bp=%p", bp));
|
||||
KASSERT(bp->b_bufobj->bo_ops->bop_write != NULL,
|
||||
@ -408,6 +410,7 @@ bwrite(struct buf *bp)
|
||||
static __inline void
|
||||
bstrategy(struct buf *bp)
|
||||
{
|
||||
|
||||
KASSERT(bp->b_bufobj != NULL, ("bwrite: no bufobj bp=%p", bp));
|
||||
KASSERT(bp->b_bufobj->bo_ops != NULL, ("bwrite: no bo_ops bp=%p", bp));
|
||||
KASSERT(bp->b_bufobj->bo_ops->bop_strategy != NULL,
|
||||
@ -481,8 +484,6 @@ extern int bufpages; /* Number of memory pages in the buffer pool. */
|
||||
extern struct buf *swbuf; /* Swap I/O buffer headers. */
|
||||
extern int nswbuf; /* Number of swap I/O buffer headers. */
|
||||
|
||||
struct uio;
|
||||
|
||||
caddr_t kern_vfs_bio_buffer_alloc(caddr_t v, long physmem_est);
|
||||
void bufinit(void);
|
||||
void bwillwrite(void);
|
||||
|
@ -85,8 +85,15 @@ struct bufobj {
|
||||
struct buf_ops *bo_ops; /* - Buffer operations */
|
||||
int bo_bsize; /* - Block size for i/o */
|
||||
struct vm_object *bo_object; /* v Place to store VM object */
|
||||
LIST_ENTRY(bufobj) bo_synclist; /* S dirty vnode list */
|
||||
void *bo_private; /* private pointer */
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX BO_ONWORKLST could be replaced with a check for NULL list elements
|
||||
* in v_synclist.
|
||||
*/
|
||||
#define BO_ONWORKLST (1 << 0) /* On syncer work-list */
|
||||
#define BO_WWAIT (1 << 1) /* Wait for output to complete */
|
||||
|
||||
#define BO_LOCK(bo) \
|
||||
@ -111,5 +118,3 @@ int bufobj_wwait(struct bufobj *bo, int slpflag, int timeo);
|
||||
|
||||
#endif /* defined(_KERNEL) || defined(_KVM_VNODE) */
|
||||
#endif /* _SYS_BUFOBJ_H_ */
|
||||
|
||||
|
||||
|
@ -130,7 +130,6 @@ struct vnode {
|
||||
} v_un;
|
||||
TAILQ_ENTRY(vnode) v_freelist; /* f vnode freelist */
|
||||
TAILQ_ENTRY(vnode) v_nmntvnodes; /* m vnodes for mount point */
|
||||
LIST_ENTRY(vnode) v_synclist; /* S dirty vnode list */
|
||||
enum vtype v_type; /* u vnode type */
|
||||
const char *v_tag; /* u type of underlying data */
|
||||
void *v_data; /* u private data for fs */
|
||||
@ -224,11 +223,6 @@ struct xvnode {
|
||||
#define VI_FREE 0x0100 /* This vnode is on the freelist */
|
||||
#define VI_OBJDIRTY 0x0400 /* object might be dirty */
|
||||
#define VI_DOINGINACT 0x0800 /* VOP_INACTIVE is in progress */
|
||||
/*
|
||||
* XXX VI_ONWORKLST could be replaced with a check for NULL list elements
|
||||
* in v_synclist.
|
||||
*/
|
||||
#define VI_ONWORKLST 0x0200 /* On syncer work-list */
|
||||
|
||||
#define VV_ROOT 0x0001 /* root of its filesystem */
|
||||
#define VV_ISTTY 0x0002 /* vnode represents a tty */
|
||||
|
Loading…
x
Reference in New Issue
Block a user