svn commit: r255019 - in projects/camlock/sys/cam: ata scsi

Alexander Motin mav at FreeBSD.org
Thu Aug 29 11:49:54 UTC 2013


Author: mav
Date: Thu Aug 29 11:49:53 2013
New Revision: 255019
URL: http://svnweb.freebsd.org/changeset/base/255019

Log:
  Drop periph (device) locks for da and ada drivers while submitting commands
  for execution. That substantially reduces these locks hold time, removing any
  measurable congestion. While GEOM guaranties that disk won't be closed before
  all requests completed, dropping lock in this place opens hypothetical race
  in case if last request manage to complete before submission call return. If
  periph will be destroyed at that point, it may cause user-after-free panic.
  To cover that case introduce additional per-periph reference counter to make
  close handler wait for all submission threads to get out before dropping
  periph reference and return.
  
  This change removes last measurable lock congestion inside CAM core on my
  test setup.  The only congestion left is inside SIM between request submit
  and completion threads, but avoiding that requires SIM modification and
  depending on specific hardware may be problematic or impossible.
  
  On my present test setup this increases maximum IOPS from 673K to 724K.

Modified:
  projects/camlock/sys/cam/ata/ata_da.c
  projects/camlock/sys/cam/scsi/scsi_da.c

Modified: projects/camlock/sys/cam/ata/ata_da.c
==============================================================================
--- projects/camlock/sys/cam/ata/ata_da.c	Thu Aug 29 11:40:45 2013	(r255018)
+++ projects/camlock/sys/cam/ata/ata_da.c	Thu Aug 29 11:49:53 2013	(r255019)
@@ -153,6 +153,7 @@ struct ada_softc {
 	struct sysctl_oid	*sysctl_tree;
 	struct callout		sendordered_c;
 	struct trim_request	trim_req;
+	int	refcount;
 };
 
 struct ada_quirk_entry {
@@ -671,6 +672,8 @@ adaclose(struct disk *dp)
 
 	softc->flags &= ~ADA_FLAG_OPEN;
 	cam_periph_unhold(periph);
+	while (softc->refcount != 0)
+		cam_periph_sleep(periph, &softc->refcount, PRIBIO, "adaclose", 1);
 	cam_periph_unlock(periph);
 	cam_periph_release(periph);
 	return (0);	
@@ -1639,7 +1642,11 @@ adastart(struct cam_periph *periph, unio
 out:
 		start_ccb->ccb_h.ccb_bp = bp;
 		softc->outstanding_cmds++;
+		softc->refcount++;
+		cam_periph_unlock(periph);
 		xpt_action(start_ccb);
+		cam_periph_lock(periph);
+		softc->refcount--;
 
 		/* May have more work to do, so ensure we stay scheduled */
 		adaschedule(periph);

Modified: projects/camlock/sys/cam/scsi/scsi_da.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_da.c	Thu Aug 29 11:40:45 2013	(r255018)
+++ projects/camlock/sys/cam/scsi/scsi_da.c	Thu Aug 29 11:49:53 2013	(r255019)
@@ -228,6 +228,7 @@ struct da_softc {
 	uint8_t	 unmap_buf[UNMAP_BUF_SIZE];
 	struct scsi_read_capacity_data_long rcaplong;
 	struct callout		mediapoll_c;
+	int	refcount;
 };
 
 #define dadeleteflag(softc, delete_method, enable)			\
@@ -1321,6 +1322,8 @@ daclose(struct disk *dp)
 
 	softc->flags &= ~DA_FLAG_OPEN;
 	cam_periph_unhold(periph);
+	while (softc->refcount != 0)
+		cam_periph_sleep(periph, &softc->refcount, PRIBIO, "daclose", 1);
 	cam_periph_unlock(periph);
 	cam_periph_release(periph);
 	return (0);	
@@ -2313,7 +2316,11 @@ out:
 		}
 
 		start_ccb->ccb_h.ccb_bp = bp;
+		softc->refcount++;
+		cam_periph_unlock(periph);
 		xpt_action(start_ccb);
+		cam_periph_lock(periph);
+		softc->refcount--;
 
 		/* May have more work to do, so ensure we stay scheduled */
 		daschedule(periph);


More information about the svn-src-projects mailing list