diff options
author | kib <kib@FreeBSD.org> | 2013-09-29 18:04:57 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2013-09-29 18:04:57 +0000 |
commit | e309fe770fe53eebe5dca3f8d640a68a853a4bde (patch) | |
tree | b194cd8fdd4ee00888a5194a6145747276b23b61 /sys/kern/vfs_bio.c | |
parent | 632f1d29f39402167db9069d25e9bdc974b29c88 (diff) | |
download | FreeBSD-src-e309fe770fe53eebe5dca3f8d640a68a853a4bde.zip FreeBSD-src-e309fe770fe53eebe5dca3f8d640a68a853a4bde.tar.gz |
Reimplement r255797 using LK_TRYUPGRADE.
The r255797 was:
Increase the chance of the buffer write from the bufdaemon helper
context to succeed. If the locked vnode which owns the buffer to be
written is shared locked, try the non-blocking upgrade of the lock to
exclusive.
PR: kern/178997
Reported and tested by: Klaus Weber <fbsd-bugs-2013-1@unix-admin.de>
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Approved by: re (glebius)
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r-- | sys/kern/vfs_bio.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index ea8a002..8787f51 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -2624,6 +2624,8 @@ flushbufqueues(struct vnode *lvp, int target, int flushdeps) int hasdeps; int flushed; int queue; + int error; + bool unlock; flushed = 0; queue = QUEUE_DIRTY; @@ -2699,7 +2701,16 @@ flushbufqueues(struct vnode *lvp, int target, int flushdeps) BUF_UNLOCK(bp); continue; } - if (vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_CANRECURSE) == 0) { + if (lvp == NULL) { + unlock = true; + error = vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT); + } else { + ASSERT_VOP_LOCKED(vp, "getbuf"); + unlock = false; + error = VOP_ISLOCKED(vp) == LK_EXCLUSIVE ? 0 : + vn_lock(vp, LK_TRYUPGRADE); + } + if (error == 0) { mtx_unlock(&bqdirty); CTR3(KTR_BUF, "flushbufqueue(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); @@ -2711,7 +2722,8 @@ flushbufqueues(struct vnode *lvp, int target, int flushdeps) notbufdflushes++; } vn_finished_write(mp); - VOP_UNLOCK(vp, 0); + if (unlock) + VOP_UNLOCK(vp, 0); flushwithdeps += hasdeps; flushed++; |