* Returns true if no I/O is needed to access the * associated VM object. This is like incore except * it also hunts around in the VM system for the data. */
| 3619 | * it also hunts around in the VM system for the data. |
| 3620 | */ |
| 3621 | bool |
| 3622 | inmem(struct vnode * vp, daddr_t blkno) |
| 3623 | { |
| 3624 | vm_object_t obj; |
| 3625 | vm_offset_t toff, tinc, size; |
| 3626 | vm_page_t m, n; |
| 3627 | vm_ooffset_t off; |
| 3628 | int valid; |
| 3629 | |
| 3630 | ASSERT_VOP_LOCKED(vp, "inmem"); |
| 3631 | |
| 3632 | if (incore(&vp->v_bufobj, blkno)) |
| 3633 | return (true); |
| 3634 | if (vp->v_mount == NULL) |
| 3635 | return (false); |
| 3636 | obj = vp->v_object; |
| 3637 | if (obj == NULL) |
| 3638 | return (false); |
| 3639 | |
| 3640 | size = PAGE_SIZE; |
| 3641 | if (size > vp->v_mount->mnt_stat.f_iosize) |
| 3642 | size = vp->v_mount->mnt_stat.f_iosize; |
| 3643 | off = (vm_ooffset_t)blkno * (vm_ooffset_t)vp->v_mount->mnt_stat.f_iosize; |
| 3644 | |
| 3645 | for (toff = 0; toff < vp->v_mount->mnt_stat.f_iosize; toff += tinc) { |
| 3646 | m = vm_page_lookup_unlocked(obj, OFF_TO_IDX(off + toff)); |
| 3647 | recheck: |
| 3648 | if (m == NULL) |
| 3649 | return (false); |
| 3650 | |
| 3651 | tinc = size; |
| 3652 | if (tinc > PAGE_SIZE - ((toff + off) & PAGE_MASK)) |
| 3653 | tinc = PAGE_SIZE - ((toff + off) & PAGE_MASK); |
| 3654 | /* |
| 3655 | * Consider page validity only if page mapping didn't change |
| 3656 | * during the check. |
| 3657 | */ |
| 3658 | valid = vm_page_is_valid(m, |
| 3659 | (vm_offset_t)((toff + off) & PAGE_MASK), tinc); |
| 3660 | n = vm_page_lookup_unlocked(obj, OFF_TO_IDX(off + toff)); |
| 3661 | if (m != n) { |
| 3662 | m = n; |
| 3663 | goto recheck; |
| 3664 | } |
| 3665 | if (!valid) |
| 3666 | return (false); |
| 3667 | } |
| 3668 | return (true); |
| 3669 | } |
| 3670 | |
| 3671 | /* |
| 3672 | * Set the dirty range for a buffer based on the status of the dirty |
no test coverage detected