With the removal of b_saveaddr in the r285819, b_data must be reset to
b_kvabase when the buffer is reclaimed. Otherwise, if b_data for the mapped buffer was adjusted with the page-offset portion of b_offset, nothing would re-adjust the b_data, which breaks buffer management code which expects page-aligned b_data (see e.g. bpman_qenter(), which skips partial pages). Fix a minor issue with the GB_KVAALLOC requests, which could result in returning the mapped buffer if the reused buffer is mapped and have the right amount of KVA reserved. Improve assertion in the vfs_buf_check_mapped() to catch unmapped buffers which have their b_data incorrectly adjusted with offset. Reported and tested by: pho (previous version) Reviewed by: jeff (previous version) Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
e600320b2a
commit
6fd04eff66
@ -956,6 +956,8 @@ vfs_buf_check_mapped(struct buf *bp)
|
||||
("mapped buf: b_kvabase was not updated %p", bp));
|
||||
KASSERT(bp->b_data != unmapped_buf,
|
||||
("mapped buf: b_data was not updated %p", bp));
|
||||
KASSERT(bp->b_data < unmapped_buf || bp->b_data > unmapped_buf +
|
||||
MAXPHYS, ("b_data + b_offset unmapped %p", bp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -2241,6 +2243,7 @@ getnewbuf_reuse_bp(struct buf *bp, int qindex)
|
||||
bp->b_dirtyoff = bp->b_dirtyend = 0;
|
||||
bp->b_bufobj = NULL;
|
||||
bp->b_pin_count = 0;
|
||||
bp->b_data = bp->b_kvabase;
|
||||
bp->b_fsprivate1 = NULL;
|
||||
bp->b_fsprivate2 = NULL;
|
||||
bp->b_fsprivate3 = NULL;
|
||||
@ -2528,6 +2531,10 @@ getnewbuf(struct vnode *vp, int slpflag, int slptimeo, int size, int maxsize,
|
||||
bp->b_flags |= B_INVAL;
|
||||
brelse(bp);
|
||||
goto restart;
|
||||
} else if ((gbflags & (GB_UNMAPPED | GB_KVAALLOC)) ==
|
||||
(GB_UNMAPPED | GB_KVAALLOC)) {
|
||||
bp->b_data = unmapped_buf;
|
||||
BUF_CHECK_UNMAPPED(bp);
|
||||
}
|
||||
atomic_add_int(&bufreusecnt, 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user