summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-09-22 19:23:48 +0000
committerkib <kib@FreeBSD.org>2013-09-22 19:23:48 +0000
commit46dd93739bb63f7f7791e941da58c8c7c43572bb (patch)
tree802ceeb7850fde430eb773152eb503c5d231fb0a /sys/kern/vfs_bio.c
parentc4b7751552a7ca56d5a3824e2a56cd9f00731b88 (diff)
downloadFreeBSD-src-46dd93739bb63f7f7791e941da58c8c7c43572bb.zip
FreeBSD-src-46dd93739bb63f7f7791e941da58c8c7c43572bb.tar.gz
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 (marius)
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index ea8a002..5219d35 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_UPGRADE | LK_NOWAIT);
+ }
+ 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++;
OpenPOWER on IntegriCloud