Author: cem
Date: Fri Jul 31 00:07:01 2020
New Revision: 363721
URL: https://svnweb.freebsd.org/changeset/base/363721

Log:
  getblk: Avoid sleeping on wrong buf in lockless path
  
  If the buffer identity changed during lookup, sleeping could introduce a
  lock order reversal.  Since we do not know if the identity changed until we
  get the lock, we must try-lock (LK_NOWAIT) only.  EINTR and ERESTART error
  handling becomes irrelevant, as we no longer sleep.
  
  Reported by:  kib
  Reviewed by:  kib
  X-MFC-With:   r363482
  Sponsored by: Dell EMC Isilon
  Differential Revision:        https://reviews.freebsd.org/D25898

Modified:
  head/sys/kern/vfs_bio.c

Modified: head/sys/kern/vfs_bio.c
==============================================================================
--- head/sys/kern/vfs_bio.c     Thu Jul 30 23:54:25 2020        (r363720)
+++ head/sys/kern/vfs_bio.c     Fri Jul 31 00:07:01 2020        (r363721)
@@ -3844,7 +3844,7 @@ getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkn
        struct buf *bp;
        struct bufobj *bo;
        daddr_t d_blkno;
-       int bsize, error, maxsize, vmio, lockflags;
+       int bsize, error, maxsize, vmio;
        off_t offset;
 
        CTR3(KTR_BUF, "getblk(%p, %ld, %d)", vp, (long)blkno, size);
@@ -3865,14 +3865,9 @@ getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkn
        if (bp == NULL)
                goto newbuf_unlocked;
 
-       lockflags = LK_EXCLUSIVE | LK_SLEEPFAIL |
-           ((flags & GB_LOCK_NOWAIT) ? LK_NOWAIT : 0);
-
-       error = BUF_TIMELOCK(bp, lockflags, NULL, "getblku", slpflag,
-           slptimeo);
-       if (error == EINTR || error == ERESTART)
-               return (error);
-       else if (error != 0)
+       error = BUF_TIMELOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL, "getblku", 0,
+           0);
+       if (error != 0)
                goto loop;
 
        /* Verify buf identify has not changed since lookup. */
@@ -3886,6 +3881,8 @@ loop:
        BO_RLOCK(bo);
        bp = gbincore(bo, blkno);
        if (bp != NULL) {
+               int lockflags;
+
                /*
                 * Buffer is in-core.  If the buffer is not busy nor managed,
                 * it must be on a queue.
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to