fix a locking botch. PR/38415 from Wolfgang Solfrank.

This commit is contained in:
yamt 2008-04-26 13:44:00 +00:00
parent fe3dc8ad88
commit fb0cfeb7dd
2 changed files with 15 additions and 8 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: uvm_map.c,v 1.252 2008/03/04 09:32:01 yamt Exp $ */
/* $NetBSD: uvm_map.c,v 1.253 2008/04/26 13:44:00 yamt Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.252 2008/03/04 09:32:01 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.253 2008/04/26 13:44:00 yamt Exp $");
#include "opt_ddb.h"
#include "opt_uvmhist.h"
@ -2430,7 +2430,7 @@ uvm_map_reserve(struct vm_map *map, vsize_t size,
int
uvm_map_replace(struct vm_map *map, vaddr_t start, vaddr_t end,
struct vm_map_entry *newents, int nnewents)
struct vm_map_entry *newents, int nnewents, struct vm_map_entry **oldentryp)
{
struct vm_map_entry *oldent, *last;
@ -2537,7 +2537,7 @@ uvm_map_replace(struct vm_map *map, vaddr_t start, vaddr_t end,
* now we can free the old blank entry and return.
*/
uvm_mapent_free(oldent);
*oldentryp = oldent;
return (true);
}
@ -2566,6 +2566,7 @@ uvm_map_extract(struct vm_map *srcmap, vaddr_t start, vsize_t len,
vaddr_t dstaddr, end, newend, oldoffset, fudge, orig_fudge;
struct vm_map_entry *chain, *endchain, *entry, *orig_entry, *newentry,
*deadentry, *oldentry;
struct vm_map_entry *resentry = NULL; /* a dummy reservation entry */
vsize_t elen;
int nchain, error, copy_ok;
UVMHIST_FUNC("uvm_map_extract"); UVMHIST_CALLED(maphist);
@ -2765,7 +2766,7 @@ uvm_map_extract(struct vm_map *srcmap, vaddr_t start, vsize_t len,
if (srcmap == dstmap || vm_map_lock_try(dstmap) == true) {
copy_ok = 1;
if (!uvm_map_replace(dstmap, dstaddr, dstaddr+len, chain,
nchain)) {
nchain, &resentry)) {
if (srcmap != dstmap)
vm_map_unlock(dstmap);
error = EIO;
@ -2852,7 +2853,7 @@ uvm_map_extract(struct vm_map *srcmap, vaddr_t start, vsize_t len,
if (copy_ok == 0) {
vm_map_lock(dstmap);
error = uvm_map_replace(dstmap, dstaddr, dstaddr+len, chain,
nchain);
nchain, &resentry);
vm_map_unlock(dstmap);
if (error == false) {
@ -2861,6 +2862,9 @@ uvm_map_extract(struct vm_map *srcmap, vaddr_t start, vsize_t len,
}
}
if (resentry != NULL)
uvm_mapent_free(resentry);
uvm_map_check(srcmap, "map_extract src leave");
uvm_map_check(dstmap, "map_extract dst leave");
@ -2876,6 +2880,9 @@ bad2: /* src already unlocked */
uvm_unmap_detach(chain,
(flags & UVM_EXTRACT_QREF) ? AMAP_REFALL : 0);
if (resentry != NULL)
uvm_mapent_free(resentry);
uvm_map_check(srcmap, "map_extract src err leave");
uvm_map_check(dstmap, "map_extract dst err leave");

View File

@ -1,4 +1,4 @@
/* $NetBSD: uvm_map.h,v 1.60 2008/01/08 13:10:01 yamt Exp $ */
/* $NetBSD: uvm_map.h,v 1.61 2008/04/26 13:44:00 yamt Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@ -316,7 +316,7 @@ bool uvm_map_lookup_entry(struct vm_map *, vaddr_t,
struct vm_map_entry **);
void uvm_map_reference(struct vm_map *);
int uvm_map_replace(struct vm_map *, vaddr_t, vaddr_t,
struct vm_map_entry *, int);
struct vm_map_entry *, int, struct vm_map_entry **);
int uvm_map_reserve(struct vm_map *, vsize_t, vaddr_t, vsize_t,
vaddr_t *, uvm_flag_t);
void uvm_map_setup(struct vm_map *, vaddr_t, vaddr_t, int);