FreeBSD/sys/geom/virstor/g_virstor.c
/*
 * Remove a component from virstor device.
 * Can only be done if the component is unallocated.
 */
Remove a component from virstor device.
Can only be done if the component is unallocated.
Remove a component from virstor device . Can only be done if the component is unallocated .
static void
virstor_ctl_remove(struct gctl_req *req, struct g_class *cp)
{
	struct g_virstor_softc *sc;
	int *nargs;
	const char *geom_name;
	u_int removed;
	int i;
	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
	if (nargs == NULL) {
		gctl_error(req, "Error fetching argument '%s'", "nargs");
		return;
	}
	if (*nargs < 2) {
		gctl_error(req, "Invalid number of arguments");
		return;
	}
	geom_name = gctl_get_asciiparam(req, "arg0");
	if (geom_name == NULL) {
		gctl_error(req, "Error fetching argument '%s'",
		    "geom_name (arg0)");
		return;
	}
	sc = virstor_find_geom(cp, geom_name);
	if (sc == NULL) {
		gctl_error(req, "Don't know anything about '%s'", geom_name);
		return;
	}
	if (virstor_valid_components(sc) != sc->n_components) {
		LOG_MSG(LVL_ERROR, "Cannot remove components from incomplete "
		    "virstor %s", sc->geom->name);
		gctl_error(req, "Virstor %s is incomplete", sc->geom->name);
		return;
	}
	removed = 0;
	for (i = 1; i < *nargs; i++) {
		char param[8];
		const char *prov_name;
		int j, found;
		struct g_virstor_component *newcomp, *compbak;
		sprintf(param, "arg%d", i);
		prov_name = gctl_get_asciiparam(req, param);
		if (prov_name == NULL) {
			gctl_error(req, "Error fetching argument '%s'", param);
			return;
		}
		if (strncmp(prov_name, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
			prov_name += sizeof(_PATH_DEV) - 1;
		found = -1;
		for (j = 0; j < sc->n_components; j++) {
			if (strcmp(sc->components[j].gcons->provider->name,
			    prov_name) == 0) {
				found = j;
				break;
			}
		}
		if (found == -1) {
			LOG_MSG(LVL_ERROR, "No %s component in %s",
			    prov_name, sc->geom->name);
			continue;
		}
		compbak = sc->components;
		newcomp = malloc(sc->n_components * sizeof(*sc->components),
		    M_GVIRSTOR, M_WAITOK | M_ZERO);
		bcopy(sc->components, newcomp, found * sizeof(*sc->components));
		bcopy(&sc->components[found + 1], newcomp + found,
		    found * sizeof(*sc->components));
		if ((sc->components[j].flags & VIRSTOR_PROVIDER_ALLOCATED) != 0) {
			LOG_MSG(LVL_ERROR, "Allocated provider %s cannot be "
			    "removed from %s",
			    prov_name, sc->geom->name);
			free(newcomp, M_GVIRSTOR);
			continue;
		}
		for (j = 0; j < sc->n_components-1; j++) {
			if ((sc->components[j].flags &
			    VIRSTOR_PROVIDER_ALLOCATED) == 0) {
				sc->components[j].index = j;
			}
		}
		sc->components = newcomp;
		sc->n_components--;
		g_topology_lock();
		if (clear_metadata(&compbak[found]) != 0) {
			LOG_MSG(LVL_WARNING, "Trouble ahead: cannot clear "
			    "metadata on %s", prov_name);
		}
		g_detach(compbak[found].gcons);
		g_destroy_consumer(compbak[found].gcons);
		g_topology_unlock();
		free(compbak, M_GVIRSTOR);
		removed++;
	}
	g_topology_lock();
	update_metadata(sc);
	g_topology_unlock();
	LOG_MSG(LVL_INFO, "Removed %d component(s) from %s", removed,
	    sc->geom->name);
}
static void virstor_ctl_remove ( struct gctl_req * req , struct g_class * cp ) { struct g_virstor_softc * sc ; int * nargs ; const char * geom_name ; u_int removed ; int i ; nargs = gctl_get_paraml ( req , " " , sizeof ( * nargs ) ) ; if ( nargs == NULL ) { gctl_error ( req , " " , " " ) ; return ; } if ( * nargs < 2 ) { gctl_error ( req , " " ) ; return ; } geom_name = gctl_get_asciiparam ( req , " " ) ; if ( geom_name == NULL ) { gctl_error ( req , " " , " " ) ; return ; } sc = virstor_find_geom ( cp , geom_name ) ; if ( sc == NULL ) { gctl_error ( req , " " , geom_name ) ; return ; } if ( virstor_valid_components ( sc ) != sc -> n_components ) { LOG_MSG ( LVL_ERROR , " " " " , sc -> geom -> name ) ; gctl_error ( req , " " , sc -> geom -> name ) ; return ; } removed = 0 ; for ( i = 1 ; i < * nargs ; i ++ ) { char param [ 8 ] ; const char * prov_name ; int j , found ; struct g_virstor_component * newcomp , * compbak ; sprintf ( param , " " , i ) ; prov_name = gctl_get_asciiparam ( req , param ) ; if ( prov_name == NULL ) { gctl_error ( req , " " , param ) ; return ; } if ( strncmp ( prov_name , _PATH_DEV , sizeof ( _PATH_DEV ) - 1 ) == 0 ) prov_name += sizeof ( _PATH_DEV ) - 1 ; found = -1 ; for ( j = 0 ; j < sc -> n_components ; j ++ ) { if ( strcmp ( sc -> components [ j ] . gcons -> provider -> name , prov_name ) == 0 ) { found = j ; break ; } } if ( found == -1 ) { LOG_MSG ( LVL_ERROR , " " , prov_name , sc -> geom -> name ) ; continue ; } compbak = sc -> components ; newcomp = malloc ( sc -> n_components * sizeof ( * sc -> components ) , M_GVIRSTOR , M_WAITOK | M_ZERO ) ; bcopy ( sc -> components , newcomp , found * sizeof ( * sc -> components ) ) ; bcopy ( & sc -> components [ found + 1 ] , newcomp + found , found * sizeof ( * sc -> components ) ) ; if ( ( sc -> components [ j ] . flags & VIRSTOR_PROVIDER_ALLOCATED ) != 0 ) { LOG_MSG ( LVL_ERROR , " " " " , prov_name , sc -> geom -> name ) ; free ( newcomp , M_GVIRSTOR ) ; continue ; } for ( j = 0 ; j < sc -> n_components - 1 ; j ++ ) { if ( ( sc -> components [ j ] . flags & VIRSTOR_PROVIDER_ALLOCATED ) == 0 ) { sc -> components [ j ] . index = j ; } } sc -> components = newcomp ; sc -> n_components -- ; g_topology_lock ( ) ; if ( clear_metadata ( & compbak [ found ] ) != 0 ) { LOG_MSG ( LVL_WARNING , " " " " , prov_name ) ; } g_detach ( compbak [ found ] . gcons ) ; g_destroy_consumer ( compbak [ found ] . gcons ) ; g_topology_unlock ( ) ; free ( compbak , M_GVIRSTOR ) ; removed ++ ; } g_topology_lock ( ) ; update_metadata ( sc ) ; g_topology_unlock ( ) ; LOG_MSG ( LVL_INFO , " " , removed , sc -> geom -> name ) ; }
Remove a component from virstor device.
Remove a component from virstor device .
/* As this is executed in parallel to I/O, operations on virstor
	 * structures must be as atomic as possible. */ /* Find "our" geom */ /* We'll consider this non-fatal error */ /* Renumerate unallocated components */ /* This is the critical section. If a component allocation
		 * event happens while both variables are not yet set,
		 * there will be trouble. Something will panic on encountering
		 * NULL sc->components[x].gcomp member.
		 * Luckily, component allocation happens very rarely and
		 * removing components is an abnormal action in any case. */ /* End critical section */ /* This call to update_metadata() is critical. In case there's a
	 * power failure in the middle of it and some components are updated
	 * while others are not, there will be trouble on next .taste() iff
	 * a non-updated component is detected first */