diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 945d95d9a7aa..dd112980f08e 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -373,7 +373,7 @@ bufcountwakeup(void) * for earlier writes to complete and generally returns before the * caller's write has reached the device. */ -static __inline void +void waitrunningbufspace(void) { diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 6ef4f0f86554..a3dde53a008a 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -478,6 +478,7 @@ extern int cluster_pbuf_freecnt; /* Number of pbufs for clusters */ extern int vnode_pbuf_freecnt; /* Number of pbufs for vnode pager */ void runningbufwakeup(struct buf *); +void waitrunningbufspace(void); caddr_t kern_vfs_bio_buffer_alloc(caddr_t v, long physmem_est); void bufinit(void); void bwillwrite(void); diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 3e7e2311f0e0..5c62d02ff362 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -1969,6 +1969,7 @@ ffs_copyonwrite(devvp, bp) struct vnode *vp = 0; ufs2_daddr_t lbn, blkno, *snapblklist; int lower, upper, mid, indiroff, snapshot_locked = 0, error = 0; + int launched_async_io, prev_norunningbuf; if (td->td_pflags & TDP_COWINPROGRESS) panic("ffs_copyonwrite: recursive call"); @@ -1997,6 +1998,8 @@ ffs_copyonwrite(devvp, bp) VI_UNLOCK(devvp); return (0); } + launched_async_io = 0; + prev_norunningbuf = td->td_pflags & TDP_NORUNNINGBUF; /* * Since I/O on bp isn't yet in progress and it may be blocked * for a long time waiting on snaplk, back it out of @@ -2101,6 +2104,8 @@ ffs_copyonwrite(devvp, bp) bawrite(cbp); if (dopersistence && ip->i_effnlink > 0) (void) ffs_syncvnode(vp, MNT_WAIT); + else + launched_async_io = 1; continue; } /* @@ -2111,6 +2116,8 @@ ffs_copyonwrite(devvp, bp) bawrite(cbp); if (dopersistence && ip->i_effnlink > 0) (void) ffs_syncvnode(vp, MNT_WAIT); + else + launched_async_io = 1; break; } savedcbp = cbp; @@ -2125,12 +2132,17 @@ ffs_copyonwrite(devvp, bp) bawrite(savedcbp); if (dopersistence && VTOI(vp)->i_effnlink > 0) (void) ffs_syncvnode(vp, MNT_WAIT); + else + launched_async_io = 1; } if (snapshot_locked) { lockmgr(vp->v_vnlock, LK_RELEASE, NULL, td); - td->td_pflags &= ~TDP_NORUNNINGBUF; + td->td_pflags = (td->td_pflags & ~TDP_NORUNNINGBUF) | + prev_norunningbuf; } else VI_UNLOCK(devvp); + if (launched_async_io && (td->td_pflags & TDP_NORUNNINGBUF)) + waitrunningbufspace(); /* * I/O on bp will now be started, so count it in runningbufspace. */