Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Mar 2013 07:50:47 +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: r248868 - in head/sys/cam: . ata scsi
Message-ID:  <201303290750.r2T7olaE099325@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Fri Mar 29 07:50:47 2013
New Revision: 248868
URL: http://svnweb.freebsd.org/changeset/base/248868

Log:
  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:
  head/sys/cam/ata/ata_da.c
  head/sys/cam/cam_periph.h
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c	Fri Mar 29 06:32:39 2013	(r248867)
+++ head/sys/cam/ata/ata_da.c	Fri Mar 29 07:50:47 2013	(r248868)
@@ -1835,7 +1835,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. */
@@ -1889,7 +1889,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. */
@@ -1962,7 +1962,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: head/sys/cam/cam_periph.h
==============================================================================
--- head/sys/cam/cam_periph.h	Fri Mar 29 06:32:39 2013	(r248867)
+++ head/sys/cam/cam_periph.h	Fri Mar 29 07:50:47 2013	(r248868)
@@ -183,6 +183,8 @@ void		cam_periph_freeze_after_event(stru
 					      u_int duration_ms);
 int		cam_periph_error(union ccb *ccb, cam_flags camflags,
 				 u_int32_t sense_flags, union ccb *save_ccb);
+void		xpt_lock_buses(void);
+void		xpt_unlock_buses(void);
 
 static __inline void
 cam_periph_lock(struct cam_periph *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: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c	Fri Mar 29 06:32:39 2013	(r248867)
+++ head/sys/cam/scsi/scsi_da.c	Fri Mar 29 07:50:47 2013	(r248868)
@@ -2848,7 +2848,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?201303290750.r2T7olaE099325>