diff options
| author | dyoung <dyoung@NetBSD.org> | 2009-04-03 21:31:08 +0000 |
|---|---|---|
| committer | dyoung <dyoung@NetBSD.org> | 2009-04-03 21:31:08 +0000 |
| commit | 211e21b653284b9e3e73b113efe786fd3b640c3f (patch) | |
| tree | d1924f4e35fee2f5b82de9502b4a4d07f2cc35d2 /sys/dev | |
| parent | 5e464841abc2cc507cc03043e254716018fce789 (diff) | |
Stop dereferencing a dangling device_t pointer and crashing: skip the
drives flagged DRIVE_ATAPI in atabus_activate(,DVACT_DEACTIVATE) just as
we skip them in atabus_detach() and in atabus_childdetched().
Make atabus_detach() parallel attachment more closely by calling
config_detach() on the child chp->ata_drives[i] instead of on
chp->ch_drive[i].drv_softc. Assert that ata_drives[i] and
ch_drive[i].drv_softc are equal, and set them both to NULL in
atabus_childdetached().
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/ata/ata.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c index c338d497377..d674c3061da 100644 --- a/sys/dev/ata/ata.c +++ b/sys/dev/ata/ata.c @@ -1,4 +1,4 @@ -/* $NetBSD: ata.c,v 1.103 2009/04/02 00:09:32 dyoung Exp $ */ +/* $NetBSD: ata.c,v 1.104 2009/04/03 21:31:08 dyoung Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.103 2009/04/02 00:09:32 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.104 2009/04/03 21:31:08 dyoung Exp $"); #include "opt_ata.h" @@ -498,6 +498,8 @@ atabus_activate(device_t self, enum devact act) } for (i = 0; i < chp->ch_ndrive; i++) { + if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI) + continue; if ((dev = chp->ch_drive[i].drv_softc) != NULL) { ATADEBUG_PRINT(("atabus_activate: %s: " "deactivating %s\n", device_xname(self), @@ -557,6 +559,7 @@ atabus_detach(device_t self, int flags) error = config_detach(dev, flags); if (error) goto out; + KASSERT(chp->atapibus == NULL); } /* @@ -565,20 +568,23 @@ atabus_detach(device_t self, int flags) for (i = 0; i < chp->ch_ndrive; i++) { if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI) continue; - if ((dev = chp->ch_drive[i].drv_softc) != NULL) { - ATADEBUG_PRINT(("atabus_detach: %s: detaching %s\n", - device_xname(self), device_xname(dev)), + if ((dev = chp->ata_drives[i]) != NULL) { + ATADEBUG_PRINT(("%s.%d: %s: detaching %s\n", __func__, + __LINE__, device_xname(self), device_xname(dev)), DEBUG_DETACH); + KASSERT(chp->ch_drive[i].drv_softc == + chp->ata_drives[i]); error = config_detach(dev, flags); if (error) goto out; + KASSERT(chp->ata_drives[i] == NULL); } } out: #ifdef ATADEBUG if (dev != NULL && error != 0) - ATADEBUG_PRINT(("atabus_detach: %s: error %d detaching %s\n", + ATADEBUG_PRINT(("%s: %s: error %d detaching %s\n", __func__, device_xname(self), error, device_xname(dev)), DEBUG_DETACH); #endif /* ATADEBUG */ @@ -589,6 +595,7 @@ atabus_detach(device_t self, int flags) void atabus_childdetached(device_t self, device_t child) { + bool found = false; struct atabus_softc *sc = device_private(self); struct ata_channel *chp = sc->sc_chan; int i; @@ -598,7 +605,7 @@ atabus_childdetached(device_t self, device_t child) */ if (child == chp->atapibus) { chp->atapibus = NULL; - return; + found = true; } /* @@ -607,14 +614,19 @@ atabus_childdetached(device_t self, device_t child) for (i = 0; i < chp->ch_ndrive; i++) { if (chp->ch_drive[i].drive_flags & DRIVE_ATAPI) continue; - if (child == chp->ch_drive[i].drv_softc) { + if (child == chp->ata_drives[i]) { + KASSERT(chp->ata_drives[i] == + chp->ch_drive[i].drv_softc); + chp->ata_drives[i] = NULL; chp->ch_drive[i].drv_softc = NULL; chp->ch_drive[i].drive_flags = 0; - return; + found = true; } } - aprint_error_dev(self, "unknown child %p", (const void *)child); + if (!found) + panic("%s: unknown child %p", device_xname(self), + (const void *)child); } CFATTACH_DECL3_NEW(atabus, sizeof(struct atabus_softc), |
