From owner-svn-src-all@FreeBSD.ORG Sat Aug 2 16:10:26 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 03E49D9D; Sat, 2 Aug 2014 16:10:26 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DA65F2FE5; Sat, 2 Aug 2014 16:10:25 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s72GAP9R040973; Sat, 2 Aug 2014 16:10:25 GMT (envelope-from alc@svn.freebsd.org) Received: (from alc@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s72GAPAd040967; Sat, 2 Aug 2014 16:10:25 GMT (envelope-from alc@svn.freebsd.org) Message-Id: <201408021610.s72GAPAd040967@svn.freebsd.org> From: Alan Cox Date: Sat, 2 Aug 2014 16:10:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r269433 - head/sys/vm X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 Aug 2014 16:10:26 -0000 Author: alc Date: Sat Aug 2 16:10:24 2014 New Revision: 269433 URL: http://svnweb.freebsd.org/changeset/base/269433 Log: Handle wiring failures in vm_map_wire() with the new functions pmap_unwire() and vm_object_unwire(). Retire vm_fault_{un,}wire(), since they are no longer used. (See r268327 and r269134 for the motivation behind this change.) Reviewed by: kib Sponsored by: EMC / Isilon Storage Division Modified: head/sys/vm/vm_extern.h head/sys/vm/vm_fault.c head/sys/vm/vm_map.c Modified: head/sys/vm/vm_extern.h ============================================================================== --- head/sys/vm/vm_extern.h Sat Aug 2 15:05:23 2014 (r269432) +++ head/sys/vm/vm_extern.h Sat Aug 2 16:10:24 2014 (r269433) @@ -81,7 +81,6 @@ int vm_fault_hold(vm_map_t map, vm_offse int fault_flags, vm_page_t *m_hold); int vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t addr, vm_size_t len, vm_prot_t prot, vm_page_t *ma, int max_count); -int vm_fault_wire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t); int vm_forkproc(struct thread *, struct proc *, struct thread *, struct vmspace *, int); void vm_waitproc(struct proc *); int vm_mmap(vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, objtype_t, void *, vm_ooffset_t); Modified: head/sys/vm/vm_fault.c ============================================================================== --- head/sys/vm/vm_fault.c Sat Aug 2 15:05:23 2014 (r269432) +++ head/sys/vm/vm_fault.c Sat Aug 2 16:10:24 2014 (r269433) @@ -106,7 +106,6 @@ __FBSDID("$FreeBSD$"); #define PFFOR 4 static int vm_fault_additional_pages(vm_page_t, int, int, vm_page_t *, int *); -static void vm_fault_unwire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t); #define VM_FAULT_READ_BEHIND 8 #define VM_FAULT_READ_MAX (1 + VM_FAULT_READ_AHEAD_MAX) @@ -1155,68 +1154,6 @@ error: } /* - * vm_fault_wire: - * - * Wire down a range of virtual addresses in a map. - */ -int -vm_fault_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, - boolean_t fictitious) -{ - vm_offset_t va; - int rv; - - /* - * We simulate a fault to get the page and enter it in the physical - * map. For user wiring, we only ask for read access on currently - * read-only sections. - */ - for (va = start; va < end; va += PAGE_SIZE) { - rv = vm_fault(map, va, VM_PROT_NONE, VM_FAULT_CHANGE_WIRING); - if (rv) { - if (va != start) - vm_fault_unwire(map, start, va, fictitious); - return (rv); - } - } - return (KERN_SUCCESS); -} - -/* - * vm_fault_unwire: - * - * Unwire a range of virtual addresses in a map. - */ -static void -vm_fault_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, - boolean_t fictitious) -{ - vm_paddr_t pa; - vm_offset_t va; - vm_page_t m; - pmap_t pmap; - - pmap = vm_map_pmap(map); - - /* - * Since the pages are wired down, we must be able to get their - * mappings from the physical map system. - */ - for (va = start; va < end; va += PAGE_SIZE) { - pa = pmap_extract(pmap, va); - if (pa != 0) { - pmap_change_wiring(pmap, va, FALSE); - if (!fictitious) { - m = PHYS_TO_VM_PAGE(pa); - vm_page_lock(m); - vm_page_unwire(m, PQ_ACTIVE); - vm_page_unlock(m); - } - } - } -} - -/* * Routine: * vm_fault_copy_entry * Function: Modified: head/sys/vm/vm_map.c ============================================================================== --- head/sys/vm/vm_map.c Sat Aug 2 15:05:23 2014 (r269432) +++ head/sys/vm/vm_map.c Sat Aug 2 16:10:24 2014 (r269433) @@ -140,6 +140,8 @@ static void vmspace_zdtor(void *mem, int static int vm_map_stack_locked(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize, vm_size_t growsize, vm_prot_t prot, vm_prot_t max, int cow); +static void vm_map_wire_entry_failure(vm_map_t map, vm_map_entry_t entry, + vm_offset_t failed_addr); #define ENTRY_CHARGED(e) ((e)->cred != NULL || \ ((e)->object.vm_object != NULL && (e)->object.vm_object->cred != NULL && \ @@ -2418,6 +2420,42 @@ done: } /* + * vm_map_wire_entry_failure: + * + * Handle a wiring failure on the given entry. + * + * The map should be locked. + */ +static void +vm_map_wire_entry_failure(vm_map_t map, vm_map_entry_t entry, + vm_offset_t failed_addr) +{ + + VM_MAP_ASSERT_LOCKED(map); + KASSERT((entry->eflags & MAP_ENTRY_IN_TRANSITION) != 0 && + entry->wired_count == 1, + ("vm_map_wire_entry_failure: entry %p isn't being wired", entry)); + KASSERT(failed_addr < entry->end, + ("vm_map_wire_entry_failure: entry %p was fully wired", entry)); + + /* + * If any pages at the start of this entry were successfully wired, + * then unwire them. + */ + if (failed_addr > entry->start) { + pmap_unwire(map->pmap, entry->start, failed_addr); + vm_object_unwire(entry->object.vm_object, entry->offset, + failed_addr - entry->start, PQ_ACTIVE); + } + + /* + * Assign an out-of-range value to represent the failure to wire this + * entry. + */ + entry->wired_count = -1; +} + +/* * vm_map_wire: * * Implements both kernel and user wiring. @@ -2427,10 +2465,10 @@ vm_map_wire(vm_map_t map, vm_offset_t st int flags) { vm_map_entry_t entry, first_entry, tmp_entry; - vm_offset_t saved_end, saved_start; + vm_offset_t faddr, saved_end, saved_start; unsigned int last_timestamp; int rv; - boolean_t fictitious, need_wakeup, result, user_wire; + boolean_t need_wakeup, result, user_wire; vm_prot_t prot; if (start == end) @@ -2523,17 +2561,24 @@ vm_map_wire(vm_map_t map, vm_offset_t st entry->wired_count++; saved_start = entry->start; saved_end = entry->end; - fictitious = entry->object.vm_object != NULL && - (entry->object.vm_object->flags & - OBJ_FICTITIOUS) != 0; + /* * Release the map lock, relying on the in-transition * mark. Mark the map busy for fork. */ vm_map_busy(map); vm_map_unlock(map); - rv = vm_fault_wire(map, saved_start, saved_end, - fictitious); + + for (faddr = saved_start; faddr < saved_end; faddr += + PAGE_SIZE) { + /* + * Simulate a fault to get the page and enter + * it into the physical map. + */ + if ((rv = vm_fault(map, faddr, VM_PROT_NONE, + VM_FAULT_CHANGE_WIRING)) != KERN_SUCCESS) + break; + } vm_map_lock(map); vm_map_unbusy(map); if (last_timestamp + 1 != map->timestamp) { @@ -2552,23 +2597,22 @@ vm_map_wire(vm_map_t map, vm_offset_t st first_entry = NULL; entry = tmp_entry; while (entry->end < saved_end) { - if (rv != KERN_SUCCESS) { - KASSERT(entry->wired_count == 1, - ("vm_map_wire: bad count")); - entry->wired_count = -1; - } + /* + * In case of failure, handle entries + * that were not fully wired here; + * fully wired entries are handled + * later. + */ + if (rv != KERN_SUCCESS && + faddr < entry->end) + vm_map_wire_entry_failure(map, + entry, faddr); entry = entry->next; } } last_timestamp = map->timestamp; if (rv != KERN_SUCCESS) { - KASSERT(entry->wired_count == 1, - ("vm_map_wire: bad count")); - /* - * Assign an out-of-range value to represent - * the failure to wire this entry. - */ - entry->wired_count = -1; + vm_map_wire_entry_failure(map, entry, faddr); end = entry->end; goto done; } @@ -2632,6 +2676,10 @@ done: entry->wired_count = 0; } else if (!user_wire || (entry->eflags & MAP_ENTRY_USER_WIRED) == 0) { + /* + * Undo the wiring. Wiring succeeded on this entry + * but failed on a later entry. + */ if (entry->wired_count == 1) vm_map_entry_unwire(map, entry); else