FreeBSD/sys/geom/concat/g_concat.c
/*
 * Add disk to given device.
 */
Add disk to given device.
Add disk to given device .
static int
g_concat_add_disk(struct g_concat_softc *sc, struct g_provider *pp, u_int no)
{
	struct g_concat_disk *disk;
	struct g_consumer *cp, *fcp;
	struct g_geom *gp;
	int error;
	g_topology_assert();
	if (no >= sc->sc_ndisks)
		return (EINVAL);
	disk = &sc->sc_disks[no];
	if (disk->d_consumer != NULL)
		return (EEXIST);
	gp = sc->sc_geom;
	fcp = LIST_FIRST(&gp->consumer);
	cp = g_new_consumer(gp);
	cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
	error = g_attach(cp, pp);
	if (error != 0) {
		g_destroy_consumer(cp);
		return (error);
	}
	if (fcp != NULL && (fcp->acr > 0 || fcp->acw > 0 || fcp->ace > 0)) {
		error = g_access(cp, fcp->acr, fcp->acw, fcp->ace);
		if (error != 0) {
			g_detach(cp);
			g_destroy_consumer(cp);
			return (error);
		}
	}
	if (sc->sc_type == G_CONCAT_TYPE_AUTOMATIC) {
		struct g_concat_metadata md;
		error = g_concat_read_metadata(cp, &md);
		if (error != 0)
			goto fail;
		if (strcmp(md.md_magic, G_CONCAT_MAGIC) != 0 ||
		    strcmp(md.md_name, sc->sc_name) != 0 ||
		    md.md_id != sc->sc_id) {
			G_CONCAT_DEBUG(0, "Metadata on %s changed.", pp->name);
			goto fail;
		}
	}
	cp->private = disk;
	disk->d_consumer = cp;
	disk->d_softc = sc;
	disk->d_start = 0;	
	disk->d_end = 0;	
	disk->d_removed = 0;
	G_CONCAT_DEBUG(0, "Disk %s attached to %s.", pp->name, sc->sc_name);
	g_concat_check_and_run(sc);
	return (0);
fail:
	if (fcp != NULL && (fcp->acr > 0 || fcp->acw > 0 || fcp->ace > 0))
		g_access(cp, -fcp->acr, -fcp->acw, -fcp->ace);
	g_detach(cp);
	g_destroy_consumer(cp);
	return (error);
}
static int g_concat_add_disk ( struct g_concat_softc * sc , struct g_provider * pp , u_int no ) { struct g_concat_disk * disk ; struct g_consumer * cp , * fcp ; struct g_geom * gp ; int error ; g_topology_assert ( ) ; if ( no >= sc -> sc_ndisks ) return ( EINVAL ) ; disk = & sc -> sc_disks [ no ] ; if ( disk -> d_consumer != NULL ) return ( EEXIST ) ; gp = sc -> sc_geom ; fcp = LIST_FIRST ( & gp -> consumer ) ; cp = g_new_consumer ( gp ) ; cp -> flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE ; error = g_attach ( cp , pp ) ; if ( error != 0 ) { g_destroy_consumer ( cp ) ; return ( error ) ; } if ( fcp != NULL && ( fcp -> acr > 0 || fcp -> acw > 0 || fcp -> ace > 0 ) ) { error = g_access ( cp , fcp -> acr , fcp -> acw , fcp -> ace ) ; if ( error != 0 ) { g_detach ( cp ) ; g_destroy_consumer ( cp ) ; return ( error ) ; } } if ( sc -> sc_type == G_CONCAT_TYPE_AUTOMATIC ) { struct g_concat_metadata md ; error = g_concat_read_metadata ( cp , & md ) ; if ( error != 0 ) goto fail ; if ( strcmp ( md . md_magic , G_CONCAT_MAGIC ) != 0 || strcmp ( md . md_name , sc -> sc_name ) != 0 || md . md_id != sc -> sc_id ) { G_CONCAT_DEBUG ( 0 , " " , pp -> name ) ; goto fail ; } } cp -> private = disk ; disk -> d_consumer = cp ; disk -> d_softc = sc ; disk -> d_start = 0 ; disk -> d_end = 0 ; disk -> d_removed = 0 ; G_CONCAT_DEBUG ( 0 , " " , pp -> name , sc -> sc_name ) ; g_concat_check_and_run ( sc ) ; return ( 0 ) ; fail : if ( fcp != NULL && ( fcp -> acr > 0 || fcp -> acw > 0 || fcp -> ace > 0 ) ) g_access ( cp , - fcp -> acr , - fcp -> acw , - fcp -> ace ) ; g_detach ( cp ) ; g_destroy_consumer ( cp ) ; return ( error ) ; }
Add disk to given device.
Add disk to given device .
/* Metadata corrupted? */ /* Check if disk is not already attached. */ /* Re-read metadata. */ /* not yet */ /* not yet */