Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Dec 2019 20:41:55 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356042 - head/sys/cam
Message-ID:  <201912232041.xBNKft9X038446@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Dec 23 20:41:55 2019
New Revision: 356042
URL: https://svnweb.freebsd.org/changeset/base/356042

Log:
  Make pass(4) handle misaligned buffers of MAXPHYS size.
  
  Since we are already using malloc()+copyin()/copyout() for smaller data
  blocks, and since new asynchronous API does it always, I see no reason
  to keep this ugly artificial size/alignment limitation in old API.
  
  Tape applications suffer enough from the MAXPHYS limitations by itself,
  and additional alignment requirement, often halving effectively usable
  block size, does not help.
  
  It would be good to use unmapped I/O here instead, but it require some
  HBA drivers polishing first to support non-BIO unmapped buffers.
  
  MFC after:	2 weeks
  Sponsored by:	iXsystems, Inc.

Modified:
  head/sys/cam/cam_periph.c

Modified: head/sys/cam/cam_periph.c
==============================================================================
--- head/sys/cam/cam_periph.c	Mon Dec 23 20:23:02 2019	(r356041)
+++ head/sys/cam/cam_periph.c	Mon Dec 23 20:41:55 2019	(r356042)
@@ -786,6 +786,7 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_ma
 	u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
 	u_int32_t lengths[CAM_PERIPH_MAXMAPS];
 	u_int32_t dirs[CAM_PERIPH_MAXMAPS];
+	bool misaligned[CAM_PERIPH_MAXMAPS];
 
 	bzero(mapinfo, sizeof(*mapinfo));
 	if (maxmap == 0)
@@ -897,6 +898,12 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_ma
 	 * have to unmap any previously mapped buffers.
 	 */
 	for (i = 0; i < numbufs; i++) {
+		if (lengths[i] > maxmap) {
+			printf("cam_periph_mapmem: attempt to map %lu bytes, "
+			       "which is greater than %lu\n",
+			       (long)(lengths[i]), (u_long)maxmap);
+			return (E2BIG);
+		}
 
 		/*
 		 * The userland data pointer passed in may not be page
@@ -906,15 +913,8 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_ma
 		 * whatever extra space is necessary to make it to the page
 		 * boundary.
 		 */
-		if ((lengths[i] +
-		    (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)) > maxmap){
-			printf("cam_periph_mapmem: attempt to map %lu bytes, "
-			       "which is greater than %lu\n",
-			       (long)(lengths[i] +
-			       (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK)),
-			       (u_long)maxmap);
-			return(E2BIG);
-		}
+		misaligned[i] = (lengths[i] +
+		    (((vm_offset_t)(*data_ptrs[i])) & PAGE_MASK) > MAXPHYS);
 	}
 
 	/*
@@ -938,7 +938,7 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_ma
 		 * small allocations malloc is backed by UMA, and so much
 		 * cheaper on SMP systems.
 		 */
-		if (lengths[i] <= periph_mapmem_thresh &&
+		if ((lengths[i] <= periph_mapmem_thresh || misaligned[i]) &&
 		    ccb->ccb_h.func_code != XPT_MMC_IO) {
 			*data_ptrs[i] = malloc(lengths[i], M_CAMPERIPH,
 			    M_WAITOK);



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