Fix getblk() with GB_NOCREAT returning false-negatives.
It is possible for a buf to be reassigned between the dirty and clean lists while gbincore_unlocked() looks in each list. Avoid creating a buffer in that case and fallback to a locked lookup. This fixes a regression from r363482. More discussion on potential improvements to the clean and dirty lists handling is in the review. Reviewed by: cem, kib, markj, vangyzen, rlibby Reported by: Suraj.Raju at dell.com Submitted by: Suraj.Raju at dell.com, cem, [based on both] MFC after: 2 weeks Sponsored by: Dell EMC Differential Revision: https://reviews.freebsd.org/D28375
This commit is contained in:
parent
ae257282ae
commit
c926114f2f
@ -3888,8 +3888,15 @@ getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, int slpflag,
|
||||
|
||||
/* Attempt lockless lookup first. */
|
||||
bp = gbincore_unlocked(bo, blkno);
|
||||
if (bp == NULL)
|
||||
if (bp == NULL) {
|
||||
/*
|
||||
* With GB_NOCREAT we must be sure about not finding the buffer
|
||||
* as it may have been reassigned during unlocked lookup.
|
||||
*/
|
||||
if ((flags & GB_NOCREAT) != 0)
|
||||
goto loop;
|
||||
goto newbuf_unlocked;
|
||||
}
|
||||
|
||||
error = BUF_TIMELOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL, "getblku", 0,
|
||||
0);
|
||||
|
Loading…
Reference in New Issue
Block a user