summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2008-08-29 04:39:46 +0000
committerscottl <scottl@FreeBSD.org>2008-08-29 04:39:46 +0000
commit743ae14c809633e69d2ef724ef9ec1d47c62f73f (patch)
tree1b77c21367fd5648d99df6852bb2f8afcd4020fb /sys/cam
parenta85de0848e0fa376e2251aeb571e7f98b7752f94 (diff)
downloadFreeBSD-src-743ae14c809633e69d2ef724ef9ec1d47c62f73f.zip
FreeBSD-src-743ae14c809633e69d2ef724ef9ec1d47c62f73f.tar.gz
Fix a locking mistake in daopen(). If the open fails, which can happen
because the media was removed, the periph would get its refcount dropped and ultimately freed before getting unlocked. This created a dangling pointer that was easy to trip over. This fixes a common source of crashes with removaable media, but problems remain and will get tracked down.
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/scsi/scsi_da.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 3831091..f63a9b0 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -674,18 +674,19 @@ daopen(struct disk *dp)
softc->disk->d_fwheads = softc->params.heads;
softc->disk->d_devstat->block_size = softc->params.secsize;
softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
- }
-
- if (error == 0) {
+
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
(softc->quirks & DA_Q_NO_PREVENT) == 0)
daprevent(periph, PR_PREVENT);
- } else {
+ } else
softc->flags &= ~DA_FLAG_OPEN;
- cam_periph_release(periph);
- }
+
cam_periph_unhold(periph);
cam_periph_unlock(periph);
+
+ if (error != 0) {
+ cam_periph_release(periph);
+ }
return (error);
}
OpenPOWER on IntegriCloud