Exemplo n.º 1
0
/*
 * It might happen that the administrator used ifconfig to externally destroy
 * the interface.  In that case, tap_fops_close will be called while
 * tap_detach is already happening.  If we called it again from here, we
 * would dead lock.  TAP_GOING ensures that this situation doesn't happen.
 */
static int
tap_fops_close(file_t *fp)
{
	int unit = fp->f_devunit;
	struct tap_softc *sc;
	int error;

	sc = device_lookup_private(&tap_cd, unit);
	if (sc == NULL)
		return (ENXIO);

	/* tap_dev_close currently always succeeds, but it might not
	 * always be the case. */
	KERNEL_LOCK(1, NULL);
	if ((error = tap_dev_close(sc)) != 0) {
		KERNEL_UNLOCK_ONE(NULL);
		return (error);
	}

	/* Destroy the device now that it is no longer useful,
	 * unless it's already being destroyed. */
	if ((sc->sc_flags & TAP_GOING) != 0) {
		KERNEL_UNLOCK_ONE(NULL);
		return (0);
	}

	error = tap_clone_destroyer(sc->sc_dev);
	KERNEL_UNLOCK_ONE(NULL);
	return error;
}
Exemplo n.º 2
0
/*
 * The clean design of if_clone and autoconf(9) makes that part
 * really straightforward.  The second argument of config_detach
 * means neither QUIET nor FORCED.
 */
static int
tap_clone_destroy(struct ifnet *ifp)
{
	struct tap_softc *sc = ifp->if_softc;

	return tap_clone_destroyer(sc->sc_dev);
}
Exemplo n.º 3
0
/*
 * The clean design of if_clone and autoconf(9) makes that part
 * really straightforward.  The second argument of config_detach
 * means neither QUIET nor FORCED.
 */
static int
tap_clone_destroy(struct ifnet *ifp)
{
	struct tap_softc *sc = ifp->if_softc;
	int error = tap_clone_destroyer(sc->sc_dev);

	if (error == 0)
		atomic_dec_uint(&tap_count);
	return error;
}