Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Apr 2013 09:40:35 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r249610 - in stable/9/sys/cam: . ata scsi
Message-ID:  <201304180940.r3I9eZW0093262@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Thu Apr 18 09:40:34 2013
New Revision: 249610
URL: http://svnweb.freebsd.org/changeset/base/249610

Log:
  MFC r248868, r248874:
  Implement CAM_PERIPH_FOREACH() macro, safely iterating over the list of
  driver's periphs, acquiring and releaseing periph references while doing it.
  
  Use it to iterate over the lists of ada and da periphs when flushing caches
  and putting devices to sleep on shutdown and suspend.  Previous code could
  panic in theory if some device disappear in the middle of the process.

Modified:
  stable/9/sys/cam/ata/ata_da.c
  stable/9/sys/cam/cam_periph.h
  stable/9/sys/cam/scsi/scsi_da.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/cam/ata/ata_da.c
==============================================================================
--- stable/9/sys/cam/ata/ata_da.c	Thu Apr 18 09:03:06 2013	(r249609)
+++ stable/9/sys/cam/ata/ata_da.c	Thu Apr 18 09:40:34 2013	(r249610)
@@ -1827,7 +1827,7 @@ adaflush(void)
 	struct ada_softc *softc;
 	int error;
 
-	TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
+	CAM_PERIPH_FOREACH(periph, &adadriver) {
 		union ccb ccb;
 
 		/* If we paniced with lock held - not recurse here. */
@@ -1881,7 +1881,7 @@ adaspindown(uint8_t cmd, int flags)
 	struct ada_softc *softc;
 	int error;
 
-	TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
+	CAM_PERIPH_FOREACH(periph, &adadriver) {
 		union ccb ccb;
 
 		/* If we paniced with lock held - not recurse here. */
@@ -1954,7 +1954,7 @@ adaresume(void *arg)
 	if (ada_spindown_suspend == 0)
 		return;
 
-	TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
+	CAM_PERIPH_FOREACH(periph, &adadriver) {
 		cam_periph_lock(periph);
 		softc = (struct ada_softc *)periph->softc;
 		/*

Modified: stable/9/sys/cam/cam_periph.h
==============================================================================
--- stable/9/sys/cam/cam_periph.h	Thu Apr 18 09:03:06 2013	(r249609)
+++ stable/9/sys/cam/cam_periph.h	Thu Apr 18 09:40:34 2013	(r249610)
@@ -36,6 +36,8 @@
 
 #ifdef _KERNEL
 
+#include <cam/cam_xpt.h>
+
 struct devstat;
 
 extern struct cam_periph *xpt_periph;
@@ -209,5 +211,42 @@ cam_periph_sleep(struct cam_periph *peri
 	return (msleep(chan, periph->sim->mtx, priority, wmesg, timo));
 }
 
+static inline struct cam_periph *
+cam_periph_acquire_first(struct periph_driver *driver)
+{
+	struct cam_periph *periph;
+
+	xpt_lock_buses();
+	periph = TAILQ_FIRST(&driver->units);
+	while (periph != NULL && (periph->flags & CAM_PERIPH_INVALID) != 0)
+		periph = TAILQ_NEXT(periph, unit_links);
+	if (periph != NULL)
+		periph->refcount++;
+	xpt_unlock_buses();
+	return (periph);
+}
+
+static inline struct cam_periph *
+cam_periph_acquire_next(struct cam_periph *pperiph)
+{
+	struct cam_periph *periph = pperiph;
+
+	mtx_assert(pperiph->sim->mtx, MA_NOTOWNED);
+	xpt_lock_buses();
+	do {
+		periph = TAILQ_NEXT(periph, unit_links);
+	} while (periph != NULL && (periph->flags & CAM_PERIPH_INVALID) != 0);
+	if (periph != NULL)
+		periph->refcount++;
+	xpt_unlock_buses();
+	cam_periph_release(pperiph);
+	return (periph);
+}
+
+#define CAM_PERIPH_FOREACH(periph, driver)				\
+	for ((periph) = cam_periph_acquire_first(driver);		\
+	    (periph) != NULL;						\
+	    (periph) = cam_periph_acquire_next(periph))
+
 #endif /* _KERNEL */
 #endif /* _CAM_CAM_PERIPH_H */

Modified: stable/9/sys/cam/scsi/scsi_da.c
==============================================================================
--- stable/9/sys/cam/scsi/scsi_da.c	Thu Apr 18 09:03:06 2013	(r249609)
+++ stable/9/sys/cam/scsi/scsi_da.c	Thu Apr 18 09:40:34 2013	(r249610)
@@ -2836,7 +2836,7 @@ dashutdown(void * arg, int howto)
 	struct da_softc *softc;
 	int error;
 
-	TAILQ_FOREACH(periph, &dadriver.units, unit_links) {
+	CAM_PERIPH_FOREACH(periph, &dadriver) {
 		union ccb ccb;
 
 		cam_periph_lock(periph);



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