changeset 6036:c98c367c32cb

PSARC 2006/123 Mmap compatibility 5003415 Provide a MAP_NOOVERMAP option for mmap()
author mec
date Tue, 19 Feb 2008 13:14:17 -0800
parents 22dc111db782
children 6b2325d54cab
files usr/src/uts/common/exec/elf/elf.c usr/src/uts/common/fs/cachefs/cachefs_vnops.c usr/src/uts/common/fs/gfs.c usr/src/uts/common/fs/hsfs/hsfs_vnops.c usr/src/uts/common/fs/mntfs/mntvnops.c usr/src/uts/common/fs/nfs/nfs3_vnops.c usr/src/uts/common/fs/nfs/nfs4_vnops.c usr/src/uts/common/fs/nfs/nfs_vnops.c usr/src/uts/common/fs/pcfs/pc_vnops.c usr/src/uts/common/fs/specfs/specvnops.c usr/src/uts/common/fs/tmpfs/tmp_vnops.c usr/src/uts/common/fs/udfs/udf_vnops.c usr/src/uts/common/fs/ufs/ufs_vnops.c usr/src/uts/common/fs/zfs/zfs_vnops.c usr/src/uts/common/io/ksyms.c usr/src/uts/common/io/mem.c usr/src/uts/common/io/smbios.c usr/src/uts/common/os/grow.c usr/src/uts/common/os/schedctl.c usr/src/uts/common/sys/vmsystm.h usr/src/uts/common/vm/seg_dev.c
diffstat 21 files changed, 159 insertions(+), 235 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/exec/elf/elf.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/exec/elf/elf.c	Tue Feb 19 13:14:17 2008 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1106,7 +1106,7 @@
 {
 	Phdr *phdr;
 	int i, prot, error;
-	caddr_t addr;
+	caddr_t addr = NULL;
 	size_t zfodsz;
 	int ptload = 0;
 	int page;
--- a/usr/src/uts/common/fs/cachefs/cachefs_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/cachefs/cachefs_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -8194,18 +8194,10 @@
 	}
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			error = ENOMEM;
-			goto out;
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		goto out;
 	}
 
 	/*
--- a/usr/src/uts/common/fs/gfs.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/gfs.c	Tue Feb 19 13:14:17 2008 -0800
@@ -20,7 +20,7 @@
  */
 /* Portions Copyright 2007 Shivakumar GN */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1022,14 +1022,10 @@
 	 * Find appropriate address if needed, otherwise clear address range.
 	 */
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		map_addr(addrp, len, (offset_t)off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			return (ENOMEM);
-		}
-	} else {
-		(void) as_unmap(as, *addrp, len);
+	rv = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (rv != 0) {
+		as_rangeunlock(as);
+		return (rv);
 	}
 
 	/*
--- a/usr/src/uts/common/fs/hsfs/hsfs_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/hsfs/hsfs_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1814,18 +1814,10 @@
 		return (EAGAIN);
 
 	as_rangelock(as);
-
-	if ((flags & MAP_FIXED) == 0) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			return (ENOMEM);
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		return (error);
 	}
 
 	vn_a.vp = vp;
--- a/usr/src/uts/common/fs/mntfs/mntvnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/mntfs/mntvnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -158,13 +158,13 @@
 			else
 				optinbuf = 1;
 			buf += snprintf(buf, MAX_MNTOPT_STR,
-				"%s", mop->mo_name);
+			    "%s", mop->mo_name);
 			/*
 			 * print option value if there is one
 			 */
 			if (mop->mo_arg != NULL) {
 				buf += snprintf(buf, MAX_MNTOPT_STR, "=%s",
-					mop->mo_arg);
+				    mop->mo_arg);
 			}
 		}
 	}
@@ -445,7 +445,7 @@
 {
 	size_t rlen = roundup(size, PAGESIZE);
 	struct as *as = curproc->p_as;
-	char *addr;
+	char *addr = NULL;
 
 	as_rangelock(as);
 	map_addr(&addr, rlen, 0, 1, 0);
@@ -466,11 +466,11 @@
 {
 	if (snap->mnts_text != NULL)
 		(void) as_unmap(curproc->p_as, snap->mnts_text,
-			roundup(snap->mnts_textsize, PAGESIZE));
+		    roundup(snap->mnts_textsize, PAGESIZE));
 	snap->mnts_textsize = snap->mnts_count = 0;
 	if (snap->mnts_metadata != NULL)
 		(void) as_unmap(curproc->p_as, snap->mnts_metadata,
-			roundup(snap->mnts_metasize, PAGESIZE));
+		    roundup(snap->mnts_metasize, PAGESIZE));
 	snap->mnts_metasize = 0;
 }
 
--- a/usr/src/uts/common/fs/nfs/nfs3_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs3_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -5218,18 +5218,10 @@
 	}
 
 	as_rangelock(as);
-	if (!(flags & MAP_FIXED)) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			error = ENOMEM;
-			goto done;
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		goto done;
 	}
 
 	vn_a.vp = vp;
--- a/usr/src/uts/common/fs/nfs/nfs4_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs4_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -10416,18 +10416,10 @@
 	}
 
 	as_rangelock(as);
-	if (!(flags & MAP_FIXED)) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			error = ENOMEM;
-			goto done;
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		goto done;
 	}
 
 	if (vp->v_type == VREG) {
--- a/usr/src/uts/common/fs/nfs/nfs_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  *	Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
@@ -4314,18 +4314,10 @@
 	}
 
 	as_rangelock(as);
-	if (!(flags & MAP_FIXED)) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			error = ENOMEM;
-			goto done;
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		goto done;
 	}
 
 	vn_a.vp = vp;
--- a/usr/src/uts/common/fs/pcfs/pc_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/pcfs/pc_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1865,17 +1865,10 @@
 		return (ENXIO);
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			return (ENOMEM);
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		return (error);
 	}
 
 	vn_a.vp = vp;
--- a/usr/src/uts/common/fs/specfs/specvnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/specfs/specvnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -2255,21 +2255,11 @@
 	}
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		/*
-		 * Pick an address w/o worrying about
-		 * any vac alignment constraints.
-		 */
-		map_addr(addrp, len, (offset_t)off, 0, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			return (ENOMEM);
-		}
-	} else {
-		/*
-		 * User-specified address; blow away any previous mappings.
-		 */
-		(void) as_unmap(as, *addrp, len);
+	/* Pick an address w/o worrying about any vac alignment constraints. */
+	error = choose_addr(as, addrp, len, off, ADDR_NOVACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		return (error);
 	}
 
 	dev_a.mapfunc = mapfunc;
@@ -2407,18 +2397,10 @@
 			return (ENXIO);
 
 		as_rangelock(as);
-		if ((flags & MAP_FIXED) == 0) {
-			map_addr(addrp, len, off, 1, flags);
-			if (*addrp == NULL) {
-				as_rangeunlock(as);
-				return (ENOMEM);
-			}
-		} else {
-			/*
-			 * User-specified address; blow away any
-			 * previous mappings.
-			 */
-			(void) as_unmap(as, *addrp, len);
+		error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+		if (error != 0) {
+			as_rangeunlock(as);
+			return (error);
 		}
 
 		vn_a.vp = cvp;
--- a/usr/src/uts/common/fs/tmpfs/tmp_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/tmpfs/tmp_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -2174,17 +2174,10 @@
 	}
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		map_addr(addrp, len, (offset_t)off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			return (ENOMEM);
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		return (error);
 	}
 
 	vn_a.vp = vp;
--- a/usr/src/uts/common/fs/udfs/udf_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/udfs/udf_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -2048,18 +2048,10 @@
 	}
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			error = ENOMEM;
-			goto end;
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		goto end;
 	}
 
 	vn_a.vp = vp;
--- a/usr/src/uts/common/fs/ufs/ufs_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/ufs/ufs_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -5601,22 +5601,16 @@
 	}
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			error = ENOMEM;
-			goto out;
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings.
-		 * If we are retrying (because ufs_lockfs_trybegin failed in
-		 * the previous attempt), some other thread could have grabbed
-		 * the same VA range. In that case, we would unmap the valid
-		 * VA range, that is ok.
-		 */
-		(void) as_unmap(as, *addrp, len);
+	/*
+	 * Note that if we are retrying (because ufs_lockfs_trybegin failed in
+	 * the previous attempt), some other thread could have grabbed
+	 * the same VA range if MAP_FIXED is set. In that case, choose_addr
+	 * would unmap the valid VA range, that is ok.
+	 */
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		goto out;
 	}
 
 	/*
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c	Tue Feb 19 13:14:17 2008 -0800
@@ -4108,18 +4108,11 @@
 	}
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		map_addr(addrp, len, off, 1, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			ZFS_EXIT(zfsvfs);
-			return (ENOMEM);
-		}
-	} else {
-		/*
-		 * User specified address - blow away any previous mappings
-		 */
-		(void) as_unmap(as, *addrp, len);
+	error = choose_addr(as, addrp, len, off, ADDR_VACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		ZFS_EXIT(zfsvfs);
+		return (error);
 	}
 
 	vn_a.vp = vp;
--- a/usr/src/uts/common/io/ksyms.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/io/ksyms.c	Tue Feb 19 13:14:17 2008 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -167,7 +166,7 @@
 static char *
 ksyms_asmap(struct as *as, size_t rlen)
 {
-	char *addr;
+	char *addr = NULL;
 
 	as_rangelock(as);
 	map_addr(&addr, rlen, 0, 1, 0);
@@ -223,7 +222,7 @@
 	ksyms_buflist_hdr_t hdr;
 	bzero(&hdr, sizeof (struct ksyms_buflist_hdr));
 	list_create(&hdr.blist, PAGESIZE,
-				offsetof(ksyms_buflist_t, buflist_node));
+	    offsetof(ksyms_buflist_t, buflist_node));
 
 	ASSERT(getminor(*devp) == 0);
 
@@ -345,7 +344,7 @@
 		return (ENOTSUP);
 
 	if (off < 0 || len <= 0 || off > kip->ksyms_size ||
-		len > kip->ksyms_size - off)
+	    len > kip->ksyms_size - off)
 		return (EINVAL);
 
 	rlen = roundup(len, PAGESIZE);
--- a/usr/src/uts/common/io/mem.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/io/mem.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -826,24 +826,15 @@
 	minor = getminor(dev);
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		/*
-		 * No need to worry about vac alignment on /dev/zero
-		 * since this is a "clone" object that doesn't yet exist.
-		 */
-		map_addr(addrp, len, (offset_t)off,
-		    (minor == M_MEM) || (minor == M_KMEM), flags);
-
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			return (ENOMEM);
-		}
-	} else {
-		/*
-		 * User specified address -
-		 * Blow away any previous mappings.
-		 */
-		(void) as_unmap(as, *addrp, len);
+	/*
+	 * No need to worry about vac alignment on /dev/zero
+	 * since this is a "clone" object that doesn't yet exist.
+	 */
+	error = choose_addr(as, addrp, len, off,
+	    (minor == M_MEM) || (minor == M_KMEM), flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		return (error);
 	}
 
 	switch (minor) {
--- a/usr/src/uts/common/io/smbios.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/io/smbios.c	Tue Feb 19 13:14:17 2008 -0800
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -21,7 +20,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -171,7 +170,7 @@
 	smb_clone_t *cp = &smb_clones[getminor(dev)];
 
 	size_t alen = P2ROUNDUP(len, PAGESIZE);
-	caddr_t addr;
+	caddr_t addr = NULL;
 
 	iovec_t iov;
 	uio_t uio;
--- a/usr/src/uts/common/os/grow.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/os/grow.c	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -230,7 +230,7 @@
 	 */
 	nva = (caddr_t)P2ROUNDUP((uintptr_t)nva, pgsz);
 	ova = (caddr_t)P2ROUNDUP((uintptr_t)(p->p_brkbase + p->p_brksize),
-		PAGESIZE);
+	    PAGESIZE);
 
 	if ((nva < p->p_brkbase) || (size > p->p_brksize &&
 	    size > as_rctl)) {
@@ -490,6 +490,40 @@
 }
 
 /*
+ * Find address for user to map.
+ * If MAP_FIXED is not specified, we can pick any address we want, but we will
+ * first try the value in *addrp if it is non-NULL.  Thus this is implementing
+ * a way to try and get a preferred address.
+ */
+int
+choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off,
+    int vacalign, uint_t flags)
+{
+	caddr_t basep = (caddr_t)(uintptr_t)((uintptr_t)*addrp & PAGEMASK);
+	size_t lenp = len;
+
+	ASSERT(AS_ISCLAIMGAP(as));	/* searches should be serialized */
+	if (flags & MAP_FIXED) {
+		(void) as_unmap(as, *addrp, len);
+		return (0);
+	} else if (basep != NULL && ((flags & MAP_ALIGN) == 0) &&
+	    !as_gap(as, len, &basep, &lenp, 0, *addrp)) {
+		/* User supplied address was available */
+		*addrp = basep;
+	} else {
+		/*
+		 * No user supplied address or the address supplied was not
+		 * available.
+		 */
+		map_addr(addrp, len, off, vacalign, flags);
+	}
+	if (*addrp == NULL)
+		return (ENOMEM);
+	return (0);
+}
+
+
+/*
  * Used for MAP_ANON - fast way to get anonymous pages
  */
 static int
@@ -497,6 +531,7 @@
     offset_t pos)
 {
 	struct segvn_crargs vn_a;
+	int error;
 
 	if (((PROT_ALL & uprot) != uprot))
 		return (EACCES);
@@ -523,16 +558,15 @@
 		default:
 			return (ENOMEM);
 		}
-		(void) as_unmap(as, *addrp, len);
-	} else {
-		/*
-		 * No need to worry about vac alignment for anonymous
-		 * pages since this is a "clone" object that doesn't
-		 * yet exist.
-		 */
-		map_addr(addrp, len, pos, 0, flags);
-		if (*addrp == NULL)
-			return (ENOMEM);
+	}
+	/*
+	 * No need to worry about vac alignment for anonymous
+	 * pages since this is a "clone" object that doesn't
+	 * yet exist.
+	 */
+	error = choose_addr(as, addrp, len, pos, ADDR_NOVACALIGN, flags);
+	if (error != 0) {
+		return (error);
 	}
 
 	/*
@@ -602,7 +636,7 @@
 
 		/* alignment needs to be a power of 2 >= page size */
 		if (((uintptr_t)*addrp < PAGESIZE && (uintptr_t)*addrp != 0) ||
-			!ISP2((uintptr_t)*addrp))
+		    !ISP2((uintptr_t)*addrp))
 			return (EINVAL);
 	}
 	/*
--- a/usr/src/uts/common/os/schedctl.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/os/schedctl.c	Tue Feb 19 13:14:17 2008 -0800
@@ -556,7 +556,7 @@
 static int
 schedctl_map(struct anon_map *amp, caddr_t *uaddrp, caddr_t kaddr)
 {
-	caddr_t addr;
+	caddr_t addr = NULL;
 	struct as *as = curproc->p_as;
 	struct segvn_crargs vn_a;
 	int error;
--- a/usr/src/uts/common/sys/vmsystm.h	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/sys/vmsystm.h	Tue Feb 19 13:14:17 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -113,6 +113,12 @@
 #define	MAPPGSZC_STACK	0x04
 #define	MAPPGSZC_HEAP	0x08
 
+/*
+ * vacalign values for choose_addr
+ */
+#define	ADDR_NOVACALIGN	0
+#define	ADDR_VACALIGN	1
+
 struct as;
 struct page;
 struct anon;
@@ -133,6 +139,8 @@
     int memcntl);
 extern	uint_t map_pgszcvec(caddr_t addr, size_t size, uintptr_t off, int flags,
     int type, int memcntl);
+extern int choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off,
+    int vacalign, uint_t flags);
 extern	void map_addr(caddr_t *addrp, size_t len, offset_t off, int vacalign,
     uint_t flags);
 extern	int map_addr_vacalign_check(caddr_t, u_offset_t);
--- a/usr/src/uts/common/vm/seg_dev.c	Tue Feb 19 10:33:55 2008 -0800
+++ b/usr/src/uts/common/vm/seg_dev.c	Tue Feb 19 13:14:17 2008 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -2439,21 +2439,11 @@
 	}
 
 	as_rangelock(as);
-	if ((flags & MAP_FIXED) == 0) {
-		/*
-		 * Pick an address w/o worrying about
-		 * any vac alignment constraints.
-		 */
-		map_addr(addrp, len, ptob(pfn), 0, flags);
-		if (*addrp == NULL) {
-			as_rangeunlock(as);
-			return (ENOMEM);
-		}
-	} else {
-		/*
-		 * User-specified address; blow away any previous mappings.
-		 */
-		(void) as_unmap(as, *addrp, len);
+	/* Pick an address w/o worrying about any vac alignment constraints. */
+	error = choose_addr(as, addrp, len, ptob(pfn), ADDR_NOVACALIGN, flags);
+	if (error != 0) {
+		as_rangeunlock(as);
+		return (error);
 	}
 
 	dev_a.mapfunc = mapfunc;