tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

vdevgone



Hi,
   I wonder what happens when vdevgone() is called?

The reason I ask is that I have a driver that provides some tty ports. In
the detach function (below), I basically do the following

        0. deregister pmf functions
        1. abort all pending transfers
        2. wait for refcnt to reach zero
        3. vdevgone the vnodes
        4. release all the allocated memory

as per the other USB drivers that I found.

But, since I'm not sure exactly what 'reclaim all the vnodes' (from the
manpage) means, I'm worrying that there is a potential race, eg where a
read() returns an error but is called again instead of close(), or even
what happens if the close() is called after the vdevgone..

should the vdevgone() really be called before the detach_wait() ?
maybe even before the aborts?

iain



int
uhso_detach(device_t self, int flags)
{
        struct uhso_softc *sc = device_private(self);
        struct uhso_port *hp;
        devmajor_t major;
        devminor_t minor;
        unsigned int i;
        int s;

        if (device_pmf_is_registered(self))
                pmf_device_deregister(self);

        for (i = 0; i < UHSO_PORT_MAX; i++) {
                hp = sc->sc_port[i];
                if (hp != NULL)
                        (*hp->hp_abort)(hp);
        }

        s = splusb();
        if (sc->sc_refcnt-- > 0) {
                DPRINTF(1, "waiting for refcnt (%d)..\n", sc->sc_refcnt);
                usb_detach_wait(sc->sc_dev);
        }
        splx(s);

        /* Nuke the vnodes for any open instances (calls close). */
        major = cdevsw_lookup_major(&uhso_cdevsw);
        minor = UHSOMINOR(device_unit(sc->sc_dev), 0);
        vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR);
        minor = UHSOMINOR(device_unit(sc->sc_dev), 0) | UHSO_DIALOUT_MASK;
        vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR);
        minor = UHSOMINOR(device_unit(sc->sc_dev), 0) | UHSO_CALLUNIT_MASK;
        vdevgone(major, minor, minor + UHSO_PORT_MAX, VCHR);

        for (i = 0; i < UHSO_PORT_MAX; i++) {
                hp = sc->sc_port[i];
                if (hp != NULL)
                        (*hp->hp_detach)(hp);
        }

        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);

        return 0;
}




Home | Main Index | Thread Index | Old Index