* Uses the page mnew as a replacement for an existing page at index * pindex which must be already present in the object. * * Both pages must be exclusively busied on enter. The old page is * unbusied on exit. * * A return value of true means mold is now free. If this is not the * final ref and the caller does not hold a wire reference it may not * continue to access the page. */
| 1834 | * continue to access the page. |
| 1835 | */ |
| 1836 | static bool |
| 1837 | vm_page_replace_hold(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex, |
| 1838 | vm_page_t mold) |
| 1839 | { |
| 1840 | vm_page_t mret; |
| 1841 | bool dropped; |
| 1842 | |
| 1843 | VM_OBJECT_ASSERT_WLOCKED(object); |
| 1844 | vm_page_assert_xbusied(mold); |
| 1845 | KASSERT(mnew->object == NULL && (mnew->ref_count & VPRC_OBJREF) == 0, |
| 1846 | ("vm_page_replace: page %p already in object", mnew)); |
| 1847 | |
| 1848 | /* |
| 1849 | * This function mostly follows vm_page_insert() and |
| 1850 | * vm_page_remove() without the radix, object count and vnode |
| 1851 | * dance. Double check such functions for more comments. |
| 1852 | */ |
| 1853 | |
| 1854 | mnew->object = object; |
| 1855 | mnew->pindex = pindex; |
| 1856 | atomic_set_int(&mnew->ref_count, VPRC_OBJREF); |
| 1857 | mret = vm_radix_replace(&object->rtree, mnew); |
| 1858 | KASSERT(mret == mold, |
| 1859 | ("invalid page replacement, mold=%p, mret=%p", mold, mret)); |
| 1860 | KASSERT((mold->oflags & VPO_UNMANAGED) == |
| 1861 | (mnew->oflags & VPO_UNMANAGED), |
| 1862 | ("vm_page_replace: mismatched VPO_UNMANAGED")); |
| 1863 | |
| 1864 | /* Keep the resident page list in sorted order. */ |
| 1865 | TAILQ_INSERT_AFTER(&object->memq, mold, mnew, listq); |
| 1866 | TAILQ_REMOVE(&object->memq, mold, listq); |
| 1867 | mold->object = NULL; |
| 1868 | |
| 1869 | /* |
| 1870 | * The object's resident_page_count does not change because we have |
| 1871 | * swapped one page for another, but the generation count should |
| 1872 | * change if the page is dirty. |
| 1873 | */ |
| 1874 | if (pmap_page_is_write_mapped(mnew)) |
| 1875 | vm_object_set_writeable_dirty(object); |
| 1876 | dropped = vm_page_drop(mold, VPRC_OBJREF) == VPRC_OBJREF; |
| 1877 | vm_page_xunbusy(mold); |
| 1878 | |
| 1879 | return (dropped); |
| 1880 | } |
| 1881 | |
| 1882 | void |
| 1883 | vm_page_replace(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex, |
no test coverage detected