Esempio n. 1
0
/*
 * NB! curthread is user process which GCTL'ed.
 */
static void
g_bsd_config(struct gctl_req *req, struct g_class *mp, char const *verb)
{
	u_char *label;
	int error;
	struct h0h0 h0h0;
	struct g_geom *gp;
	struct g_slicer *gsp;
	struct g_consumer *cp;
	struct g_bsd_softc *ms;

	g_topology_assert();
	gp = gctl_get_geom(req, mp, "geom");
	if (gp == NULL)
		return;
	cp = LIST_FIRST(&gp->consumer);
	gsp = gp->softc;
	ms = gsp->softc;
	if (!strcmp(verb, "read mbroffset")) {
		gctl_set_param_err(req, "mbroffset", &ms->mbroffset,
		    sizeof(ms->mbroffset));
		return;
	} else if (!strcmp(verb, "write label")) {
		label = gctl_get_paraml(req, "label", LABELSIZE);
		if (label == NULL)
			return;
		h0h0.gp = gp;
		h0h0.ms = gsp->softc;
		h0h0.label = label;
		h0h0.error = -1;
		/* XXX: Does this reference register with our selfdestruct code ? */
		error = g_access(cp, 1, 1, 1);
		if (error) {
			gctl_error(req, "could not access consumer");
			return;
		}
		g_bsd_callconfig(&h0h0, 0);
		error = h0h0.error;
		g_access(cp, -1, -1, -1);
	} else if (!strcmp(verb, "write bootcode")) {
		label = gctl_get_paraml(req, "bootcode", BBSIZE);
		if (label == NULL)
			return;
		/* XXX: Does this reference register with our selfdestruct code ? */
		error = g_access(cp, 1, 1, 1);
		if (error) {
			gctl_error(req, "could not access consumer");
			return;
		}
		error = g_bsd_writelabel(gp, label);
		g_access(cp, -1, -1, -1);
	} else {
		gctl_error(req, "Unknown verb parameter");
	}

	return;
}
Esempio n. 2
0
static void
g_bsd_callconfig(void *arg, int flag)
{
	struct h0h0 *hp;

	hp = arg;
	hp->error = g_bsd_modify(hp->gp, hp->label);
	if (!hp->error)
		hp->error = g_bsd_writelabel(hp->gp, NULL);
}
Esempio n. 3
0
/*-
 * This start routine is only called for non-trivial requests, all the
 * trivial ones are handled autonomously by the slice code.
 * For requests we handle here, we must call the g_io_deliver() on the
 * bio, and return non-zero to indicate to the slice code that we did so.
 * This code executes in the "DOWN" I/O path, this means:
 *    * No sleeping.
 *    * Don't grab the topology lock.
 *    * Don't call biowait, g_getattr(), g_setattr() or g_read_data()
 */
static int
g_bsd_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td)
{
	struct g_geom *gp;
	struct g_bsd_softc *ms;
	struct g_slicer *gsp;
	u_char *label;
	int error;

	gp = pp->geom;
	gsp = gp->softc;
	ms = gsp->softc;

	switch(cmd) {
	case DIOCGDINFO:
		/* Return a copy of the disklabel to userland. */
		bsd_disklabel_le_dec(ms->label, data, MAXPARTITIONS);
		return(0);
	case DIOCBSDBB: {
		struct g_consumer *cp;
		u_char *buf;
		void *p;
		int error, i;
		uint64_t sum;

		if (!(fflag & FWRITE))
			return (EPERM);
		/* The disklabel to set is the ioctl argument. */
		buf = g_malloc(BBSIZE, M_WAITOK);
		p = *(void **)data;
		error = copyin(p, buf, BBSIZE);
		if (!error) {
			/* XXX: Rude, but supposedly safe */
			DROP_GIANT();
			g_topology_lock();
			/* Validate and modify our slice instance to match. */
			error = g_bsd_modify(gp, buf + ms->labeloffset);
			if (!error) {
				cp = LIST_FIRST(&gp->consumer);
				if (ms->labeloffset == ALPHA_LABEL_OFFSET) {
					sum = 0;
					for (i = 0; i < 63; i++)
						sum += le64dec(buf + i * 8);
					le64enc(buf + 504, sum);
				}
				error = g_write_data(cp, 0, buf, BBSIZE);
			}
			g_topology_unlock();
			PICKUP_GIANT();
		}
		g_free(buf);
		return (error);
	}
	case DIOCSDINFO:
	case DIOCWDINFO: {
		if (!(fflag & FWRITE))
			return (EPERM);
		label = g_malloc(LABELSIZE, M_WAITOK);
		/* The disklabel to set is the ioctl argument. */
		bsd_disklabel_le_enc(label, data);

		DROP_GIANT();
		g_topology_lock();
		/* Validate and modify our slice instance to match. */
		error = g_bsd_modify(gp, label);
		if (error == 0 && cmd == DIOCWDINFO)
			error = g_bsd_writelabel(gp, NULL);
		g_topology_unlock();
		PICKUP_GIANT();
		g_free(label);
		return(error);
	}
	default:
		return (ENOIOCTL);
	}
}