Page MenuHomeFreeBSD

D45571.diff
No OneTemporary

D45571.diff

diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -4002,9 +4002,15 @@
/*
* With GB_NOCREAT we must be sure about not finding the buffer
* as it may have been reassigned during unlocked lookup.
+ * If BO_NONSTERILE is still unset, no reassign has occurred.
*/
- if ((flags & GB_NOCREAT) != 0)
+ if ((flags & GB_NOCREAT) != 0) {
+ /* Ensure bo_flag is loaded after gbincore_unlocked. */
+ atomic_thread_fence_acq();
+ if ((bo->bo_flag & BO_NONSTERILE) == 0)
+ return (EEXIST);
goto loop;
+ }
goto newbuf_unlocked;
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -3207,6 +3207,16 @@
bp, bp->b_vp, bp->b_flags);
BO_LOCK(bo);
+ if ((bo->bo_flag & BO_NONSTERILE) == 0) {
+ /*
+ * Coordinate with getblk's unlocked lookup. Make
+ * BO_NONSTERILE visible before the first reassignbuf produces
+ * any side effect. This could be outside the bo lock if we
+ * used a separate atomic flag field.
+ */
+ bo->bo_flag |= BO_NONSTERILE;
+ atomic_thread_fence_rel();
+ }
buf_vlist_remove(bp);
/*
diff --git a/sys/sys/bufobj.h b/sys/sys/bufobj.h
--- a/sys/sys/bufobj.h
+++ b/sys/sys/bufobj.h
@@ -116,6 +116,7 @@
#define BO_WWAIT (1 << 1) /* Wait for output to complete */
#define BO_DEAD (1 << 2) /* Dead; only with INVARIANTS */
#define BO_NOBUFS (1 << 3) /* No bufs allowed */
+#define BO_NONSTERILE (1 << 4) /* Ever called reassignbuf() */
#define BO_LOCKPTR(bo) (&(bo)->bo_lock)
#define BO_LOCK(bo) rw_wlock(BO_LOCKPTR((bo)))

File Metadata

Mime Type
text/plain
Expires
Thu, Jan 16, 1:43 PM (20 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15826168
Default Alt Text
D45571.diff (1 KB)

Event Timeline