FreeBSD/sys/geom/virstor/g_virstor.c
/*
 * Taste event (per-class callback)
 * Examines a provider and creates geom instances if needed
 */
Taste event (per-class callback)
Examines a provider and creates geom instances if needed
Taste event ( per - class callback ) Examines a provider and creates geom instances if needed
static struct g_geom *
g_virstor_taste(struct g_class *mp, struct g_provider *pp, int flags)
{
	struct g_virstor_metadata md;
	struct g_geom *gp;
	struct g_consumer *cp;
	struct g_virstor_softc *sc;
	int error;
	g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, pp->name);
	g_topology_assert();
	LOG_MSG(LVL_DEBUG, "Tasting %s", pp->name);
	gp = g_new_geomf(mp, "virstor:taste.helper");
	gp->start = (void *)invalid_call;	
	gp->access = (void *)invalid_call;	
	gp->orphan = (void *)invalid_call;	
	cp = g_new_consumer(gp);
	g_attach(cp, pp);
	error = read_metadata(cp, &md);
	g_detach(cp);
	g_destroy_consumer(cp);
	g_destroy_geom(gp);
	if (error != 0)
		return (NULL);
	if (strcmp(md.md_magic, G_VIRSTOR_MAGIC) != 0)
		return (NULL);
	if (md.md_version != G_VIRSTOR_VERSION) {
		LOG_MSG(LVL_ERROR, "Kernel module version invalid "
		    "to handle %s (%s) : %d should be %d",
		    md.md_name, pp->name, md.md_version, G_VIRSTOR_VERSION);
		return (NULL);
	}
	if (md.provsize != pp->mediasize)
		return (NULL);
	if (md.provider[0] != '\0' &&
	    !g_compare_names(md.provider, pp->name))
		return (NULL);
	sc = NULL;
	gp = NULL;
	LIST_FOREACH(gp, &mp->geom, geom) {
		sc = gp->softc;
		if (sc == NULL)
			continue;
		if (strcmp(md.md_name, sc->geom->name) != 0)
			continue;
		if (md.md_id != sc->id)
			continue;
		break;
	}
	if (gp != NULL) { 
		LOG_MSG(LVL_INFO, "Adding %s to %s", pp->name, md.md_name);
		error = add_provider_to_geom(sc, pp, &md);
		if (error != 0) {
			LOG_MSG(LVL_ERROR, "Error adding %s to %s (error %d)",
			    pp->name, md.md_name, error);
			return (NULL);
		}
	} else { 
		gp = create_virstor_geom(mp, &md);
		if (gp == NULL) {
			LOG_MSG(LVL_ERROR, "Error creating new instance of "
			    "class %s: %s", mp->name, md.md_name);
			LOG_MSG(LVL_DEBUG, "Error creating %s at %s",
			    md.md_name, pp->name);
			return (NULL);
		}
		sc = gp->softc;
		LOG_MSG(LVL_INFO, "Adding %s to %s (first found)", pp->name,
		    md.md_name);
		error = add_provider_to_geom(sc, pp, &md);
		if (error != 0) {
			LOG_MSG(LVL_ERROR, "Error adding %s to %s (error %d)",
			    pp->name, md.md_name, error);
			virstor_geom_destroy(sc, TRUE, FALSE);
			return (NULL);
		}
	}
	return (gp);
}
static struct g_geom * g_virstor_taste ( struct g_class * mp , struct g_provider * pp , int flags ) { struct g_virstor_metadata md ; struct g_geom * gp ; struct g_consumer * cp ; struct g_virstor_softc * sc ; int error ; g_trace ( G_T_TOPOLOGY , " " , __func__ , mp -> name , pp -> name ) ; g_topology_assert ( ) ; LOG_MSG ( LVL_DEBUG , " " , pp -> name ) ; gp = g_new_geomf ( mp , " " ) ; gp -> start = ( void * ) invalid_call ; gp -> access = ( void * ) invalid_call ; gp -> orphan = ( void * ) invalid_call ; cp = g_new_consumer ( gp ) ; g_attach ( cp , pp ) ; error = read_metadata ( cp , & md ) ; g_detach ( cp ) ; g_destroy_consumer ( cp ) ; g_destroy_geom ( gp ) ; if ( error != 0 ) return ( NULL ) ; if ( strcmp ( md . md_magic , G_VIRSTOR_MAGIC ) != 0 ) return ( NULL ) ; if ( md . md_version != G_VIRSTOR_VERSION ) { LOG_MSG ( LVL_ERROR , " " " " , md . md_name , pp -> name , md . md_version , G_VIRSTOR_VERSION ) ; return ( NULL ) ; } if ( md . provsize != pp -> mediasize ) return ( NULL ) ; if ( md . provider [ 0 ] != ' \0 ' && ! g_compare_names ( md . provider , pp -> name ) ) return ( NULL ) ; sc = NULL ; gp = NULL ; LIST_FOREACH ( gp , & mp -> geom , geom ) { sc = gp -> softc ; if ( sc == NULL ) continue ; if ( strcmp ( md . md_name , sc -> geom -> name ) != 0 ) continue ; if ( md . md_id != sc -> id ) continue ; break ; } if ( gp != NULL ) { LOG_MSG ( LVL_INFO , " " , pp -> name , md . md_name ) ; error = add_provider_to_geom ( sc , pp , & md ) ; if ( error != 0 ) { LOG_MSG ( LVL_ERROR , " " , pp -> name , md . md_name , error ) ; return ( NULL ) ; } } else { gp = create_virstor_geom ( mp , & md ) ; if ( gp == NULL ) { LOG_MSG ( LVL_ERROR , " " " " , mp -> name , md . md_name ) ; LOG_MSG ( LVL_DEBUG , " " , md . md_name , pp -> name ) ; return ( NULL ) ; } sc = gp -> softc ; LOG_MSG ( LVL_INFO , " " , pp -> name , md . md_name ) ; error = add_provider_to_geom ( sc , pp , & md ) ; if ( error != 0 ) { LOG_MSG ( LVL_ERROR , " " , pp -> name , md . md_name , error ) ; virstor_geom_destroy ( sc , TRUE , FALSE ) ; return ( NULL ) ; } } return ( gp ) ; }
Taste event (per-class callback)
 Examines a provider and creates geom instances if needed
Taste event ( per - class callback ) Examines a provider and creates geom instances if needed
/* We need a dummy geom to attach a consumer to the given provider */ /* XXX: hacked up so the        */ /* compiler doesn't complain.   */ /* I really want these to fail. */ /* If the provider name is hardcoded, use the offered provider only
	 * if it's been offered with its proper name (the one used in
	 * the label command). */ /* Iterate all geoms this class already knows about to see if a new
	 * geom instance of this class needs to be created (in case the provider
	 * is first from a (possibly) multi-consumer geom) or it just needs
	 * to be added to an existing instance. */ /* We found an existing geom instance; add to it */ /* New geom instance needs to be created */