summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-12-02 19:59:25 +0000
committerphk <phk@FreeBSD.org>2002-12-02 19:59:25 +0000
commit7b3238944ad7e75d41b5abeec125b1565b406096 (patch)
treebc14fcae75a2e499eab6036a281b96be25a5c757 /sys
parent88d7b8f56badfe1166bf9c4ca3fe30a8e9e4b306 (diff)
downloadFreeBSD-src-7b3238944ad7e75d41b5abeec125b1565b406096.zip
FreeBSD-src-7b3238944ad7e75d41b5abeec125b1565b406096.tar.gz
Add a simplified version of the hot-spot code to enable us to protect
in-band disklabels from in-band vandalism. Approve by: re
Diffstat (limited to 'sys')
-rw-r--r--sys/geom/geom_slice.c90
-rw-r--r--sys/geom/geom_slice.h13
2 files changed, 95 insertions, 8 deletions
diff --git a/sys/geom/geom_slice.c b/sys/geom/geom_slice.c
index ca8d023..8bcf52c 100644
--- a/sys/geom/geom_slice.c
+++ b/sys/geom/geom_slice.c
@@ -121,6 +121,38 @@ g_slice_access(struct g_provider *pp, int dr, int dw, int de)
return (error);
}
+void
+g_slice_finish_hot(struct bio *bp)
+{
+ struct bio *bp2;
+ struct g_geom *gp;
+ struct g_consumer *cp;
+ struct g_slicer *gsp;
+ struct g_slice *gsl;
+ int index;
+
+ KASSERT(bp->bio_to != NULL, ("NULL bio_to in g_slice_finish_hot(%p)", bp));
+ KASSERT(bp->bio_from != NULL, ("NULL bio_from in g_slice_finish_hot(%p)", bp));
+ gp = bp->bio_to->geom;
+ gsp = gp->softc;
+ cp = LIST_FIRST(&gp->consumer);
+ KASSERT(cp != NULL, ("NULL consumer in g_slice_finish_hot(%p)", bp));
+ index = bp->bio_to->index;
+ gsl = &gsp->slices[index];
+
+ bp2 = g_clone_bio(bp);
+ if (bp2 == NULL) {
+ g_io_deliver(bp, ENOMEM);
+ return;
+ }
+ if (bp2->bio_offset + bp2->bio_length > gsl->length)
+ bp2->bio_length = gsl->length - bp2->bio_offset;
+ bp2->bio_done = g_std_done;
+ bp2->bio_offset += gsl->offset;
+ g_io_request(bp2, cp);
+ return;
+}
+
static void
g_slice_start(struct bio *bp)
{
@@ -129,8 +161,9 @@ g_slice_start(struct bio *bp)
struct g_geom *gp;
struct g_consumer *cp;
struct g_slicer *gsp;
- struct g_slice *gsl;
- int index;
+ struct g_slice *gsl, *gmp;
+ int index, error;
+ u_int m_index;
off_t t;
pp = bp->bio_to;
@@ -147,6 +180,25 @@ g_slice_start(struct bio *bp)
g_io_deliver(bp, EINVAL); /* XXX: EWHAT ? */
return;
}
+ /*
+ * Check if we collide with any hot spaces, and call the
+ * method once if so.
+ */
+ for (m_index = 0; m_index < gsp->nhot; m_index++) {
+ gmp = &gsp->hot[m_index];
+ if (bp->bio_offset >= gmp->offset + gmp->length)
+ continue;
+ if (bp->bio_offset + bp->bio_length <= gmp->offset)
+ continue;
+ error = gsp->start(bp);
+ if (error == EJUSTRETURN)
+ return;
+ else if (error) {
+ g_io_deliver(bp, error);
+ return;
+ }
+ break;
+ }
bp2 = g_clone_bio(bp);
if (bp2 == NULL) {
g_io_deliver(bp, ENOMEM);
@@ -230,7 +282,7 @@ g_slice_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_cons
}
int
-g_slice_config(struct g_geom *gp, int index, int how, off_t offset, off_t length, u_int sectorsize, char *fmt, ...)
+g_slice_config(struct g_geom *gp, u_int index, int how, off_t offset, off_t length, u_int sectorsize, char *fmt, ...)
{
struct g_provider *pp;
struct g_slicer *gsp;
@@ -301,6 +353,35 @@ g_slice_config(struct g_geom *gp, int index, int how, off_t offset, off_t length
return(0);
}
+int
+g_slice_conf_hot(struct g_geom *gp, u_int index, off_t offset, off_t length)
+{
+ struct g_slicer *gsp;
+ struct g_slice *gsl, *gsl2;
+
+ g_trace(G_T_TOPOLOGY, "g_slice_conf_hot()");
+ g_topology_assert();
+ gsp = gp->softc;
+ gsl = gsp->hot;
+ if(index >= gsp->nhot) {
+ gsl2 = g_malloc((index + 1) * sizeof *gsl2, M_WAITOK | M_ZERO);
+ if (gsp->hot != NULL)
+ bcopy(gsp->hot, gsl2, gsp->nhot * sizeof *gsl2);
+ gsp->hot = gsl2;
+ if (gsp->hot != NULL)
+ g_free(gsl);
+ gsl = gsl2;
+ gsp->nhot = index + 1;
+ }
+ if (bootverbose)
+ printf("GEOM: Add %s hot[%d] start %jd length %jd end %jd\n",
+ gp->name, index, (intmax_t)offset, (intmax_t)length,
+ (intmax_t)(offset + length - 1));
+ gsl[index].offset = offset;
+ gsl[index].length = length;
+ return (0);
+}
+
struct g_provider *
g_slice_addslice(struct g_geom *gp, int index, off_t offset, off_t length, u_int sectorsize, char *fmt, ...)
{
@@ -334,7 +415,7 @@ g_slice_addslice(struct g_geom *gp, int index, off_t offset, off_t length, u_int
}
struct g_geom *
-g_slice_new(struct g_class *mp, int slices, struct g_provider *pp, struct g_consumer **cpp, void *extrap, int extra, g_slice_start_t *start)
+g_slice_new(struct g_class *mp, u_int slices, struct g_provider *pp, struct g_consumer **cpp, void *extrap, int extra, g_slice_start_t *start)
{
struct g_geom *gp;
struct g_slicer *gsp;
@@ -389,6 +470,7 @@ g_slice_orphan(struct g_consumer *cp)
("g_slice_orphan with error == 0"));
gp = cp->geom;
+ /* XXX: Not good enough we leak the softc and its suballocations */
gp->flags |= G_GEOM_WITHER;
error = cp->provider->error;
LIST_FOREACH(pp, &gp->provider, provider)
diff --git a/sys/geom/geom_slice.h b/sys/geom/geom_slice.h
index 11be047..bea6aac 100644
--- a/sys/geom/geom_slice.h
+++ b/sys/geom/geom_slice.h
@@ -48,21 +48,26 @@ struct g_slice {
typedef int g_slice_start_t (struct bio *bp);
struct g_slicer {
- int nslice;
- int nprovider;
+ u_int nslice;
+ u_int nprovider;
+ u_int nhot;
off_t cfrontstuff;
off_t frontstuff;
struct g_slice *slices;
+ struct g_slice *hot;
void *softc;
g_slice_start_t *start;
};
g_dumpconf_t g_slice_dumpconf;
struct g_provider * g_slice_addslice(struct g_geom *gp, int index, off_t offset, off_t length, u_int sectorsize, char *fmt, ...);
-int g_slice_config(struct g_geom *gp, int index, int how, off_t offset, off_t length, u_int sectorsize, char *fmt, ...);
+int g_slice_config(struct g_geom *gp, u_int index, int how, off_t offset, off_t length, u_int sectorsize, char *fmt, ...);
#define G_SLICE_CONFIG_CHECK 0
#define G_SLICE_CONFIG_SET 1
#define G_SLICE_CONFIG_FORCE 2
-struct g_geom * g_slice_new(struct g_class *mp, int slices, struct g_provider *pp, struct g_consumer **cpp, void *extrap, int extra, g_slice_start_t *start);
+struct g_geom * g_slice_new(struct g_class *mp, u_int slices, struct g_provider *pp, struct g_consumer **cpp, void *extrap, int extra, g_slice_start_t *start);
+
+int g_slice_conf_hot(struct g_geom *gp, u_int index, off_t offset, off_t length);
+void g_slice_finish_hot(struct bio *bp);
#endif /* _GEOM_GEOM_SLICE_H_ */
OpenPOWER on IntegriCloud