| 1761 | } |
| 1762 | |
| 1763 | static void |
| 1764 | vm_object_collapse_scan(vm_object_t object) |
| 1765 | { |
| 1766 | vm_object_t backing_object; |
| 1767 | vm_page_t next, p, pp; |
| 1768 | vm_pindex_t backing_offset_index, new_pindex; |
| 1769 | |
| 1770 | VM_OBJECT_ASSERT_WLOCKED(object); |
| 1771 | VM_OBJECT_ASSERT_WLOCKED(object->backing_object); |
| 1772 | |
| 1773 | backing_object = object->backing_object; |
| 1774 | backing_offset_index = OFF_TO_IDX(object->backing_object_offset); |
| 1775 | |
| 1776 | /* |
| 1777 | * Our scan |
| 1778 | */ |
| 1779 | for (p = TAILQ_FIRST(&backing_object->memq); p != NULL; p = next) { |
| 1780 | next = TAILQ_NEXT(p, listq); |
| 1781 | new_pindex = p->pindex - backing_offset_index; |
| 1782 | |
| 1783 | /* |
| 1784 | * Check for busy page |
| 1785 | */ |
| 1786 | if (vm_page_tryxbusy(p) == 0) { |
| 1787 | next = vm_object_collapse_scan_wait(object, p); |
| 1788 | continue; |
| 1789 | } |
| 1790 | |
| 1791 | KASSERT(object->backing_object == backing_object, |
| 1792 | ("vm_object_collapse_scan: backing object mismatch %p != %p", |
| 1793 | object->backing_object, backing_object)); |
| 1794 | KASSERT(p->object == backing_object, |
| 1795 | ("vm_object_collapse_scan: object mismatch %p != %p", |
| 1796 | p->object, backing_object)); |
| 1797 | |
| 1798 | if (p->pindex < backing_offset_index || |
| 1799 | new_pindex >= object->size) { |
| 1800 | if (backing_object->type == OBJT_SWAP) |
| 1801 | swap_pager_freespace(backing_object, p->pindex, |
| 1802 | 1); |
| 1803 | |
| 1804 | KASSERT(!pmap_page_is_mapped(p), |
| 1805 | ("freeing mapped page %p", p)); |
| 1806 | if (vm_page_remove(p)) |
| 1807 | vm_page_free(p); |
| 1808 | continue; |
| 1809 | } |
| 1810 | |
| 1811 | if (!vm_page_all_valid(p)) { |
| 1812 | KASSERT(!pmap_page_is_mapped(p), |
| 1813 | ("freeing mapped page %p", p)); |
| 1814 | if (vm_page_remove(p)) |
| 1815 | vm_page_free(p); |
| 1816 | continue; |
| 1817 | } |
| 1818 | |
| 1819 | pp = vm_page_lookup(object, new_pindex); |
| 1820 | if (pp != NULL && vm_page_tryxbusy(pp) == 0) { |
no test coverage detected