geom_sunlabel.c revision 113880
155714Skris/*-
255714Skris * Copyright (c) 2002 Poul-Henning Kamp
355714Skris * Copyright (c) 2002 Networks Associates Technology, Inc.
455714Skris * All rights reserved.
555714Skris *
6160814Ssimon * This software was developed for the FreeBSD Project by Poul-Henning Kamp
755714Skris * and NAI Labs, the Security Research Division of Network Associates, Inc.
855714Skris * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
955714Skris * DARPA CHATS research program.
1055714Skris *
1155714Skris * Redistribution and use in source and binary forms, with or without
1255714Skris * modification, are permitted provided that the following conditions
1355714Skris * are met:
1455714Skris * 1. Redistributions of source code must retain the above copyright
1555714Skris *    notice, this list of conditions and the following disclaimer.
1655714Skris * 2. Redistributions in binary form must reproduce the above copyright
1755714Skris *    notice, this list of conditions and the following disclaimer in the
1855714Skris *    documentation and/or other materials provided with the distribution.
1955714Skris * 3. The names of the authors may not be used to endorse or promote
2055714Skris *    products derived from this software without specific prior written
2155714Skris *    permission.
2255714Skris *
2355714Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2455714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2555714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2655714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2755714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2855714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2955714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3055714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3155714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3255714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3355714Skris * SUCH DAMAGE.
3455714Skris *
3555714Skris * $FreeBSD: head/sys/geom/geom_sunlabel.c 113880 2003-04-22 21:29:58Z phk $
3655714Skris */
3755714Skris
3855714Skris
3955714Skris#include <sys/param.h>
4055714Skris#include <sys/endian.h>
4155714Skris#include <sys/systm.h>
4255714Skris#include <sys/kernel.h>
4355714Skris#include <sys/conf.h>
4455714Skris#include <sys/bio.h>
4555714Skris#include <sys/malloc.h>
4655714Skris#include <sys/lock.h>
4755714Skris#include <sys/mutex.h>
4855714Skris#include <sys/sun_disklabel.h>
4955714Skris#include <geom/geom.h>
5055714Skris#include <geom/geom_slice.h>
5155714Skris#include <machine/endian.h>
5255714Skris
5355714Skris#define SUNLABEL_CLASS_NAME "SUN"
5455714Skris
5555714Skrisstruct g_sunlabel_softc {
5655714Skris	int sectorsize;
5755714Skris	int nheads;
5855714Skris	int nsects;
5955714Skris	int nalt;
6055714Skris};
6168651Skris
6268651Skrisstatic int
6368651Skrisg_sunlabel_modify(struct g_geom *gp, struct g_sunlabel_softc *ms, u_char *sec0)
6468651Skris{
6555714Skris	int i, error;
6655714Skris	u_int u, v, csize;
6755714Skris	struct sun_disklabel sl;
6855714Skris
6955714Skris	error = sunlabel_dec(sec0, &sl);
7055714Skris	if (error)
7155714Skris		return (error);
7255714Skris
7355714Skris	csize = sl.sl_ntracks * sl.sl_nsectors;
7455714Skris
7555714Skris	for (i = 0; i < SUN_NPART; i++) {
7655714Skris		v = sl.sl_part[i].sdkp_cyloffset;
77160814Ssimon		u = sl.sl_part[i].sdkp_nsectors;
7855714Skris		error = g_slice_config(gp, i, G_SLICE_CONFIG_CHECK,
7955714Skris		    ((off_t)v * csize) << 9ULL,
8055714Skris		    ((off_t)u) << 9ULL,
8155714Skris		    ms->sectorsize,
82160814Ssimon		    "%s%c", gp->name, 'a' + i);
8355714Skris		if (error)
84160814Ssimon			return (error);
8555714Skris	}
8655714Skris	for (i = 0; i < SUN_NPART; i++) {
8755714Skris		v = sl.sl_part[i].sdkp_cyloffset;
8855714Skris		u = sl.sl_part[i].sdkp_nsectors;
8955714Skris		g_slice_config(gp, i, G_SLICE_CONFIG_SET,
9055714Skris		    ((off_t)v * csize) << 9ULL,
91109998Smarkm		    ((off_t)u) << 9ULL,
92109998Smarkm		    ms->sectorsize,
93109998Smarkm		    "%s%c", gp->name, 'a' + i);
9455714Skris	}
9555714Skris	ms->nalt = sl.sl_acylinders;
9655714Skris	ms->nheads = sl.sl_ntracks;
9755714Skris	ms->nsects = sl.sl_nsectors;
9855714Skris
9955714Skris	return (0);
10055714Skris}
10155714Skris
10255714Skrisstatic void
10355714Skrisg_sunlabel_hotwrite(void *arg, int flag)
10455714Skris{
10555714Skris	struct bio *bp;
10655714Skris	struct g_geom *gp;
10755714Skris	struct g_slicer *gsp;
10855714Skris	struct g_slice *gsl;
10955714Skris	struct g_sunlabel_softc *ms;
11055714Skris	u_char *p;
11155714Skris	int error;
11255714Skris
11355714Skris	KASSERT(flag != EV_CANCEL, ("g_sunlabel_hotwrite cancelled"));
11455714Skris	bp = arg;
11555714Skris	gp = bp->bio_to->geom;
11655714Skris	gsp = gp->softc;
11755714Skris	ms = gsp->softc;
11855714Skris	gsl = &gsp->slices[bp->bio_to->index];
11955714Skris	/*
12055714Skris	 * XXX: For all practical purposes, this whould be equvivalent to
12155714Skris	 * XXX: "p = (u_char *)bp->bio_data;" because the label is always
12255714Skris	 * XXX: in the first sector and we refuse sectors smaller than the
12355714Skris	 * XXX: label.
12455714Skris	 */
12555714Skris	p = (u_char *)bp->bio_data - (bp->bio_offset + gsl->offset);
12655714Skris
12755714Skris	error = g_sunlabel_modify(gp, ms, p);
12855714Skris	if (error) {
12955714Skris		g_io_deliver(bp, EPERM);
13055714Skris		return;
13155714Skris	}
13255714Skris	g_slice_finish_hot(bp);
13355714Skris}
13455714Skris
13555714Skrisstatic void
13668651Skrisg_sunlabel_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g_consumer *cp __unused, struct g_provider *pp)
13768651Skris{
13855714Skris	struct g_slicer *gsp;
13955714Skris	struct g_sunlabel_softc *ms;
14055714Skris
14155714Skris	gsp = gp->softc;
14255714Skris	ms = gsp->softc;
14355714Skris	g_slice_dumpconf(sb, indent, gp, cp, pp);
14455714Skris	if (indent == NULL) {
14555714Skris		sbuf_printf(sb, " sc %u hd %u alt %u",
14655714Skris		    ms->nsects, ms->nheads, ms->nalt);
14755714Skris	}
14855714Skris}
14955714Skris
15055714Skrisstatic struct g_geom *
15155714Skrisg_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags)
15255714Skris{
15355714Skris	struct g_geom *gp;
15455714Skris	struct g_consumer *cp;
15555714Skris	int error, npart;
15659191Skris	u_char *buf;
15759191Skris	struct g_sunlabel_softc *ms;
15859191Skris	off_t mediasize;
15959191Skris	struct g_slicer *gsp;
16059191Skris
161109998Smarkm	g_trace(G_T_TOPOLOGY, "g_sunlabel_taste(%s,%s)", mp->name, pp->name);
162109998Smarkm	g_topology_assert();
163109998Smarkm	if (flags == G_TF_NORMAL &&
164109998Smarkm	    !strcmp(pp->geom->class->name, SUNLABEL_CLASS_NAME))
165109998Smarkm		return (NULL);
16655714Skris	gp = g_slice_new(mp, 8, pp, &cp, &ms, sizeof *ms, NULL);
16755714Skris	if (gp == NULL)
168109998Smarkm		return (NULL);
169109998Smarkm	gsp = gp->softc;
170109998Smarkm	gp->dumpconf = g_sunlabel_dumpconf;
171109998Smarkm	npart = 0;
172109998Smarkm	do {
173109998Smarkm		if (gp->rank != 2 && flags == G_TF_NORMAL)
174109998Smarkm			break;
175109998Smarkm		ms->sectorsize = cp->provider->sectorsize;
176109998Smarkm		if (ms->sectorsize < 512)
17755714Skris			break;
17855714Skris		mediasize = cp->provider->mediasize;
17955714Skris		g_topology_unlock();
18055714Skris		buf = g_read_data(cp, 0, ms->sectorsize, &error);
181109998Smarkm		g_topology_lock();
182109998Smarkm		if (buf == NULL || error != 0)
183109998Smarkm			break;
184109998Smarkm
185109998Smarkm		g_sunlabel_modify(gp, ms, buf);
186109998Smarkm
187109998Smarkm		break;
188109998Smarkm	} while (0);
189109998Smarkm	g_access_rel(cp, -1, 0, 0);
190109998Smarkm	if (LIST_EMPTY(&gp->provider)) {
191109998Smarkm		g_std_spoiled(cp);
19255714Skris		return (NULL);
19355714Skris	} else {
194109998Smarkm		g_slice_conf_hot(gp, 0, 0, SUN_SIZE,
19555714Skris		    G_SLICE_HOT_ALLOW, G_SLICE_HOT_DENY, G_SLICE_HOT_CALL);
196109998Smarkm		gsp->hot = g_sunlabel_hotwrite;
19755714Skris	}
19855714Skris	return (gp);
19955714Skris}
200109998Smarkm
201109998Smarkmstatic struct g_class g_sunlabel_class = {
20259191Skris	.name = SUNLABEL_CLASS_NAME,
20359191Skris	.taste = g_sunlabel_taste,
20459191Skris	G_CLASS_INITIALIZER
20559191Skris};
20659191Skris
207109998SmarkmDECLARE_GEOM_CLASS(g_sunlabel_class, g_sunlabel);
208109998Smarkm