git: b19740f4ce7a - main - swap_pager: lock vnode in swapdev_strategy()

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 25 Nov 2021 19:35:10 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=b19740f4ce7a542783f87de2fee48476a7801d86

commit b19740f4ce7a542783f87de2fee48476a7801d86
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-11-24 11:26:46 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-11-25 19:34:50 +0000

    swap_pager: lock vnode in swapdev_strategy()
    
    VOP_STRATEGY() requires locked vnode.  Note that we lock the swap vnode
    while pages are busy, but this would only cause real LoR if pages belong
    to the swap vnode, which must not be the case for correct use.
    
    Reported and tested by: peterj
    Reviewed by:    markj
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D33119
---
 sys/vm/swap_pager.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 880e2a1894df..6daedd02649d 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -3043,16 +3043,19 @@ swapdev_strategy(struct buf *bp, struct swdevt *sp)
 	vp2 = sp->sw_id;
 	vhold(vp2);
 	if (bp->b_iocmd == BIO_WRITE) {
+		vn_lock(vp2, LK_EXCLUSIVE | LK_RETRY);
 		if (bp->b_bufobj)
 			bufobj_wdrop(bp->b_bufobj);
 		bufobj_wref(&vp2->v_bufobj);
+	} else {
+		vn_lock(vp2, LK_SHARED | LK_RETRY);
 	}
 	if (bp->b_bufobj != &vp2->v_bufobj)
 		bp->b_bufobj = &vp2->v_bufobj;
 	bp->b_vp = vp2;
 	bp->b_iooffset = dbtob(bp->b_blkno);
 	bstrategy(bp);
-	return;
+	VOP_UNLOCK(vp2);
 }
 
 static void