Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 26 Dec 2015 11:10:45 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r292746 - stable/10/sys/dev/md
Message-ID:  <201512261110.tBQBAjDh092404@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Dec 26 11:10:44 2015
New Revision: 292746
URL: https://svnweb.freebsd.org/changeset/base/292746

Log:
  MFC r292128:
  In md(4) over vnode, correct handling of the unaligned unmapped io
  requests which page alignment + size is greater than MAXPHYS. Split
  request up to the size of io which fits into pbuf KVA with alignment,
  and retry if a part of the bio is left unprocessed.

Modified:
  stable/10/sys/dev/md/md.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/md/md.c
==============================================================================
--- stable/10/sys/dev/md/md.c	Sat Dec 26 09:16:05 2015	(r292745)
+++ stable/10/sys/dev/md/md.c	Sat Dec 26 11:10:44 2015	(r292746)
@@ -825,8 +825,8 @@ mdstart_vnode(struct md_s *sc, struct bi
 	struct buf *pb;
 	bus_dma_segment_t *vlist;
 	struct thread *td;
-	off_t len, zerosize;
-	int ma_offs;
+	off_t iolen, len, zerosize;
+	int ma_offs, npages;
 
 	switch (bp->bio_cmd) {
 	case BIO_READ:
@@ -847,6 +847,7 @@ mdstart_vnode(struct md_s *sc, struct bi
 	pb = NULL;
 	piov = NULL;
 	ma_offs = bp->bio_ma_offset;
+	len = bp->bio_length;
 
 	/*
 	 * VNODE I/O
@@ -879,7 +880,6 @@ mdstart_vnode(struct md_s *sc, struct bi
 		auio.uio_iovcnt = howmany(bp->bio_length, zerosize);
 		piov = malloc(sizeof(*piov) * auio.uio_iovcnt, M_MD, M_WAITOK);
 		auio.uio_iov = piov;
-		len = bp->bio_length;
 		while (len > 0) {
 			piov->iov_base = __DECONST(void *, zero_region);
 			piov->iov_len = len;
@@ -893,7 +893,6 @@ mdstart_vnode(struct md_s *sc, struct bi
 		piov = malloc(sizeof(*piov) * bp->bio_ma_n, M_MD, M_WAITOK);
 		auio.uio_iov = piov;
 		vlist = (bus_dma_segment_t *)bp->bio_data;
-		len = bp->bio_length;
 		while (len > 0) {
 			piov->iov_base = (void *)(uintptr_t)(vlist->ds_addr +
 			    ma_offs);
@@ -909,11 +908,20 @@ mdstart_vnode(struct md_s *sc, struct bi
 		piov = auio.uio_iov;
 	} else if ((bp->bio_flags & BIO_UNMAPPED) != 0) {
 		pb = getpbuf(&md_vnode_pbuf_freecnt);
-		pmap_qenter((vm_offset_t)pb->b_data, bp->bio_ma, bp->bio_ma_n);
-		aiov.iov_base = (void *)((vm_offset_t)pb->b_data + ma_offs);
-		aiov.iov_len = bp->bio_length;
+		bp->bio_resid = len;
+unmapped_step:
+		npages = atop(min(MAXPHYS, round_page(len + (ma_offs &
+		    PAGE_MASK))));
+		iolen = min(ptoa(npages) - (ma_offs & PAGE_MASK), len);
+		KASSERT(iolen > 0, ("zero iolen"));
+		pmap_qenter((vm_offset_t)pb->b_data,
+		    &bp->bio_ma[atop(ma_offs)], npages);
+		aiov.iov_base = (void *)((vm_offset_t)pb->b_data +
+		    (ma_offs & PAGE_MASK));
+		aiov.iov_len = iolen;
 		auio.uio_iov = &aiov;
 		auio.uio_iovcnt = 1;
+		auio.uio_resid = iolen;
 	} else {
 		aiov.iov_base = bp->bio_data;
 		aiov.iov_len = bp->bio_length;
@@ -937,15 +945,21 @@ mdstart_vnode(struct md_s *sc, struct bi
 		vn_finished_write(mp);
 	}
 
-	if (pb) {
-		pmap_qremove((vm_offset_t)pb->b_data, bp->bio_ma_n);
+	if (pb != NULL) {
+		pmap_qremove((vm_offset_t)pb->b_data, npages);
+		if (error == 0) {
+			len -= iolen;
+			bp->bio_resid -= iolen;
+			ma_offs += iolen;
+			if (len > 0)
+				goto unmapped_step;
+		}
 		relpbuf(pb, &md_vnode_pbuf_freecnt);
 	}
 
-	if (piov != NULL)
-		free(piov, M_MD);
-
-	bp->bio_resid = auio.uio_resid;
+	free(piov, M_MD);
+	if (pb == NULL)
+		bp->bio_resid = auio.uio_resid;
 	return (error);
 }
 



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