Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 May 2011 18:48:01 +0000 (UTC)
From:      Matthew D Fleming <mdf@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r221853 - in head/sys: dev/md dev/null sys vm
Message-ID:  <201105131848.p4DIm1j7079495@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mdf
Date: Fri May 13 18:48:00 2011
New Revision: 221853
URL: http://svn.freebsd.org/changeset/base/221853

Log:
  Usa a globally visible region of zeros for both /dev/zero and the md
  device.  There are likely other kernel uses of "blob of zeros" than can
  be converted.
  
  Reviewed by:	alc
  MFC after:	1 week

Modified:
  head/sys/dev/md/md.c
  head/sys/dev/null/null.c
  head/sys/sys/systm.h
  head/sys/vm/vm_kern.c

Modified: head/sys/dev/md/md.c
==============================================================================
--- head/sys/dev/md/md.c	Fri May 13 18:46:20 2011	(r221852)
+++ head/sys/dev/md/md.c	Fri May 13 18:48:00 2011	(r221853)
@@ -205,9 +205,6 @@ struct md_s {
 	vm_object_t object;
 };
 
-/* Used for BIO_DELETE on MD_VNODE */
-static u_char zero[PAGE_SIZE];
-
 static struct indir *
 new_indir(u_int shift)
 {
@@ -560,7 +557,8 @@ mdstart_vnode(struct md_s *sc, struct bi
 	 * that the two cases end up having very little in common.
 	 */
 	if (bp->bio_cmd == BIO_DELETE) {
-		zerosize = sizeof(zero) - (sizeof(zero) % sc->sectorsize);
+		zerosize = ZERO_REGION_SIZE -
+		    (ZERO_REGION_SIZE % sc->sectorsize);
 		auio.uio_iov = &aiov;
 		auio.uio_iovcnt = 1;
 		auio.uio_offset = (vm_ooffset_t)bp->bio_offset;
@@ -573,7 +571,7 @@ mdstart_vnode(struct md_s *sc, struct bi
 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 		error = 0;
 		while (auio.uio_offset < end) {
-			aiov.iov_base = zero;
+			aiov.iov_base = __DECONST(void *, zero_region);
 			aiov.iov_len = end - auio.uio_offset;
 			if (aiov.iov_len > zerosize)
 				aiov.iov_len = zerosize;

Modified: head/sys/dev/null/null.c
==============================================================================
--- head/sys/dev/null/null.c	Fri May 13 18:46:20 2011	(r221852)
+++ head/sys/dev/null/null.c	Fri May 13 18:48:00 2011	(r221853)
@@ -65,8 +65,6 @@ static struct cdevsw zero_cdevsw = {
 	.d_flags =	D_MMAP_ANON,
 };
 
-static void *zbuf;
-
 /* ARGSUSED */
 static int
 null_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
@@ -95,10 +93,19 @@ null_ioctl(struct cdev *dev __unused, u_
 static int
 zero_read(struct cdev *dev __unused, struct uio *uio, int flags __unused)
 {
+	void *zbuf;
+	ssize_t len;
 	int error = 0;
 
-	while (uio->uio_resid > 0 && error == 0)
-		error = uiomove(zbuf, MIN(uio->uio_resid, PAGE_SIZE), uio);
+	KASSERT(uio->uio_rw == UIO_READ,
+	    ("Can't be in %s for write", __func__));
+	zbuf = __DECONST(void *, zero_region);
+	while (uio->uio_resid > 0 && error == 0) {
+		len = uio->uio_resid;
+		if (len > ZERO_REGION_SIZE)
+			len = ZERO_REGION_SIZE;
+		error = uiomove(zbuf, len, uio);
+	}
 
 	return (error);
 }
@@ -111,7 +118,6 @@ null_modevent(module_t mod __unused, int
 	case MOD_LOAD:
 		if (bootverbose)
 			printf("null: <null device, zero device>\n");
-		zbuf = (void *)malloc(PAGE_SIZE, M_TEMP, M_WAITOK | M_ZERO);
 		null_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &null_cdevsw, 0,
 		    NULL, UID_ROOT, GID_WHEEL, 0666, "null");
 		zero_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &zero_cdevsw, 0,
@@ -121,7 +127,6 @@ null_modevent(module_t mod __unused, int
 	case MOD_UNLOAD:
 		destroy_dev(null_dev);
 		destroy_dev(zero_dev);
-		free(zbuf, M_TEMP);
 		break;
 
 	case MOD_SHUTDOWN:

Modified: head/sys/sys/systm.h
==============================================================================
--- head/sys/sys/systm.h	Fri May 13 18:46:20 2011	(r221852)
+++ head/sys/sys/systm.h	Fri May 13 18:48:00 2011	(r221853)
@@ -125,6 +125,9 @@ extern char static_hints[];	/* by config
 
 extern char **kenvp;
 
+extern const void *zero_region;	/* address space maps to a zeroed page	*/
+#define	ZERO_REGION_SIZE	(2048 * 1024)
+
 /*
  * General function declarations.
  */

Modified: head/sys/vm/vm_kern.c
==============================================================================
--- head/sys/vm/vm_kern.c	Fri May 13 18:46:20 2011	(r221852)
+++ head/sys/vm/vm_kern.c	Fri May 13 18:48:00 2011	(r221853)
@@ -91,6 +91,9 @@ vm_map_t exec_map=0;
 vm_map_t pipe_map;
 vm_map_t buffer_map=0;
 
+const void *zero_region;
+CTASSERT((ZERO_REGION_SIZE & PAGE_MASK) == 0);
+
 /*
  *	kmem_alloc_nofault:
  *
@@ -527,6 +530,35 @@ kmem_free_wakeup(map, addr, size)
 	vm_map_unlock(map);
 }
 
+static void
+kmem_init_zero_region(void)
+{
+	vm_offset_t addr;
+	vm_page_t m;
+	unsigned int i;
+	int error;
+
+	/* Allocate virtual address space. */
+	addr = kmem_alloc_nofault(kernel_map, ZERO_REGION_SIZE);
+
+	/* Allocate a page and zero it. */
+	m = vm_page_alloc(NULL, OFF_TO_IDX(addr - VM_MIN_KERNEL_ADDRESS),
+	    VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
+	if ((m->flags & PG_ZERO) == 0)
+		pmap_zero_page(m);
+
+	/* Map the address space to the page. */
+	for (i = 0; i < ZERO_REGION_SIZE; i += PAGE_SIZE)
+		pmap_qenter(addr + i, &m, 1);
+
+	/* Protect it r/o. */
+	error = vm_map_protect(kernel_map, addr, addr + ZERO_REGION_SIZE,
+	    VM_PROT_READ, TRUE);
+	KASSERT(error == 0, ("error=%d", error));
+
+	zero_region = (const void *)addr;
+}
+
 /*
  * 	kmem_init:
  *
@@ -555,6 +587,8 @@ kmem_init(start, end)
 	    start, VM_PROT_ALL, VM_PROT_ALL, MAP_NOFAULT);
 	/* ... and ending with the completion of the above `insert' */
 	vm_map_unlock(m);
+
+	kmem_init_zero_region();
 }
 
 #ifdef DIAGNOSTIC



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105131848.p4DIm1j7079495>