diff options
author | 2009-07-28 11:19:43 +0000 | |
---|---|---|
committer | 2009-07-28 11:19:43 +0000 | |
commit | 1ca8e808ccbc4a19c5592d5e6cfce4cc0152186b (patch) | |
tree | e4abb42faff3838e1866187d0ac944e20d449176 | |
parent | Accept and print "Enter" and "Escape" for keys rather than C-m and C-[. (diff) | |
download | wireguard-openbsd-1ca8e808ccbc4a19c5592d5e6cfce4cc0152186b.tar.xz wireguard-openbsd-1ca8e808ccbc4a19c5592d5e6cfce4cc0152186b.zip |
Using the buf pointer returned from incore is a really bad idea.
Even if we know that someone safely holds B_BUSY and will not modify
the buf (as was the case in here), we still need to be sure that
the B_BUSY will not be released while we fiddle with the buf.
In this case, it was not safe, since copyout can sleep and whoever was
writing out the buf could finish the write and release the buf which
could then get recycled or unmapped while we slept. Always acquire
B_BUSY ourselves, even when it might give a minor performance penalty.
thib@ ok
-rw-r--r-- | sys/nfs/nfs_bio.c | 42 |
1 files changed, 12 insertions, 30 deletions
diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c index e5e57617525..215470b5da9 100644 --- a/sys/nfs/nfs_bio.c +++ b/sys/nfs/nfs_bio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_bio.c,v 1.61 2009/07/22 13:02:08 thib Exp $ */ +/* $OpenBSD: nfs_bio.c,v 1.62 2009/07/28 11:19:43 art Exp $ */ /* $NetBSD: nfs_bio.c,v 1.25.4.2 1996/07/08 20:47:04 jtc Exp $ */ /* @@ -170,30 +170,18 @@ nfs_bioread(vp, uio, ioflag, cred) } } - /* - * If the block is in the cache and has the required data - * in a valid region, just copy it out. - * Otherwise, get the block and write back/read in, - * as required. - */ - if ((bp = incore(vp, bn)) && - (bp->b_flags & (B_BUSY | B_WRITEINPROG)) == - (B_BUSY | B_WRITEINPROG)) - got_buf = 0; - else { again: - bp = nfs_getcacheblk(vp, bn, biosize, p); - if (!bp) - return (EINTR); - got_buf = 1; - if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) { - bp->b_flags |= B_READ; - not_readin = 0; - error = nfs_doio(bp, p); - if (error) { - brelse(bp); - return (error); - } + bp = nfs_getcacheblk(vp, bn, biosize, p); + if (!bp) + return (EINTR); + got_buf = 1; + if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) { + bp->b_flags |= B_READ; + not_readin = 0; + error = nfs_doio(bp, p); + if (error) { + brelse(bp); + return (error); } } n = min((unsigned)(biosize - on), uio->uio_resid); @@ -202,12 +190,6 @@ again: n = (int)offdiff; if (not_readin && n > 0) { if (on < bp->b_validoff || (on + n) > bp->b_validend) { - if (!got_buf) { - bp = nfs_getcacheblk(vp, bn, biosize, p); - if (!bp) - return (EINTR); - got_buf = 1; - } bp->b_flags |= B_INVAFTERWRITE; if (bp->b_dirtyend > 0) { if ((bp->b_flags & B_DELWRI) == 0) |