Revert r173708's modifications to vm_object_page_remove().

Assume that a vnode is mapped shared and mlocked(), and then the vnode
is truncated, or truncated and then again extended past the mapping
point EOF.  Truncation removes the pages past the truncation point,
and if pages are later created at this range, they are not properly
mapped into the mlocked region, and their wiring count is wrong.

The revert leaves the invalidated but wired pages on the object queue,
which means that the pages are found by vm_object_unwire() when the
mapped range is munlock()ed, and reused by the buffer cache when the
vnode is extended again.

The changes in r173708 were required since then vm_map_unwire() looked
at the page tables to find the page to unwire.  This is no longer
needed with the vm_object_unwire() introduction, which follows the
objects shadow chain.

Also eliminate OBJPR_NOTWIRED flag for vm_object_page_remove(), which
is now redundand, we do not remove wired pages.

Reported by:	trasz, Dmitry Sivachenko <trtrmitya@gmail.com>
Suggested and reviewed by:	alc
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
kib 2015-07-25 18:29:06 +00:00
parent c0e1a0d3a9
commit 3df958c236
2 changed files with 5 additions and 24 deletions

View File

@ -1063,9 +1063,9 @@ vm_object_sync(vm_object_t object, vm_ooffset_t offset, vm_size_t size,
*/
flags = OBJPR_NOTMAPPED;
else if (old_msync)
flags = OBJPR_NOTWIRED;
flags = 0;
else
flags = OBJPR_CLEANONLY | OBJPR_NOTWIRED;
flags = OBJPR_CLEANONLY;
vm_object_page_remove(object, OFF_TO_IDX(offset),
OFF_TO_IDX(offset + size + PAGE_MASK), flags);
}
@ -1894,7 +1894,6 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end,
int options)
{
vm_page_t p, next;
int wirings;
VM_OBJECT_ASSERT_WLOCKED(object);
KASSERT((object->flags & OBJ_UNMANAGED) == 0 ||
@ -1928,15 +1927,9 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end,
VM_OBJECT_WLOCK(object);
goto again;
}
if ((wirings = p->wire_count) != 0 &&
(wirings = pmap_page_wired_mappings(p)) != p->wire_count) {
if ((options & (OBJPR_NOTWIRED | OBJPR_NOTMAPPED)) ==
0) {
if (p->wire_count != 0) {
if ((options & OBJPR_NOTMAPPED) == 0)
pmap_remove_all(p);
/* Account for removal of wired mappings. */
if (wirings != 0)
p->wire_count -= wirings;
}
if ((options & OBJPR_CLEANONLY) == 0) {
p->valid = 0;
vm_page_undirty(p);
@ -1957,19 +1950,8 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end,
if (p->dirty)
goto next;
}
if ((options & OBJPR_NOTMAPPED) == 0) {
if ((options & OBJPR_NOTWIRED) != 0 && wirings != 0)
goto next;
if ((options & OBJPR_NOTMAPPED) == 0)
pmap_remove_all(p);
/* Account for removal of wired mappings. */
if (wirings != 0) {
KASSERT(p->wire_count == wirings,
("inconsistent wire count %d %d %p",
p->wire_count, wirings, p));
p->wire_count = 0;
atomic_subtract_int(&vm_cnt.v_wire_count, 1);
}
}
vm_page_free(p);
next:
vm_page_unlock(p);

View File

@ -207,7 +207,6 @@ struct vm_object {
*/
#define OBJPR_CLEANONLY 0x1 /* Don't remove dirty pages. */
#define OBJPR_NOTMAPPED 0x2 /* Don't unmap pages. */
#define OBJPR_NOTWIRED 0x4 /* Don't remove wired pages. */
TAILQ_HEAD(object_q, vm_object);