aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2023-03-24 21:12:21 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2023-03-25 22:55:29 +0000
commit28f957b8b3a22086927451fee89789fdf596260b (patch)
treea8c766b46acc203f5778a701d238947d91178f31
parent0e71f4f77c016b4087106e7c58b958667df8e1b2 (diff)
downloadsrc-28f957b8b3a22086927451fee89789fdf596260b.tar.gz
src-28f957b8b3a22086927451fee89789fdf596260b.zip
vnode_pager_input: return runningbufspace back
Both vnode_pager_input_smlfs() and vnode_pager_generic_getpages() increment runningbufspace, but also both delegate io completion handling on the pbuf to either plain bdone() or filesystem-specific strategy routine. Accidentally, for e.g. UFS it is g_vfs_strategy()/g_vfs_done(). The later calls bufdone() which handles runningbufspace reclamation. For plain bdone() io done handler, nothing would return accounted b_runningbufspace back. Do it in the new helper vnode_pager_input_bdone(), as well as in vnode_pager_generic_getpages_done() explicitly. Note that potential multiple calls to runningbufwakeup() for the same pbuf or buf completion are safe. runningbufwakeup() clears accounting for the buffer, so second and later calls are nop. The problem was found due to tarfs using small vnode pager input but not g_vfs_strategy(). Reported by: des Reviewed by: markj, sjg Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D39263
-rw-r--r--sys/vm/vnode_pager.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 56caf75d7f90..6103daaf13c2 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -640,6 +640,13 @@ vnode_pager_addr(struct vnode *vp, vm_ooffset_t address, daddr_t *rtaddress,
return (err);
}
+static void
+vnode_pager_input_bdone(struct buf *bp)
+{
+ runningbufwakeup(bp);
+ bdone(bp);
+}
+
/*
* small block filesystem vnode pager input
*/
@@ -686,7 +693,7 @@ vnode_pager_input_smlfs(vm_object_t object, vm_page_t m)
/* build a minimal buffer header */
bp->b_iocmd = BIO_READ;
- bp->b_iodone = bdone;
+ bp->b_iodone = vnode_pager_input_bdone;
KASSERT(bp->b_rcred == NOCRED, ("leaking read ucred"));
KASSERT(bp->b_wcred == NOCRED, ("leaking write ucred"));
bp->b_rcred = crhold(curthread->td_ucred);
@@ -1204,6 +1211,8 @@ vnode_pager_generic_getpages_done(struct buf *bp)
error = (bp->b_ioflags & BIO_ERROR) != 0 ? bp->b_error : 0;
object = bp->b_vp->v_object;
+ runningbufwakeup(bp);
+
if (error == 0 && bp->b_bcount != bp->b_npages * PAGE_SIZE) {
if (!buf_mapped(bp)) {
bp->b_data = bp->b_kvabase;