diff options
author | phk <phk@FreeBSD.org> | 2002-12-02 19:59:25 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2002-12-02 19:59:25 +0000 |
commit | 7b3238944ad7e75d41b5abeec125b1565b406096 (patch) | |
tree | bc14fcae75a2e499eab6036a281b96be25a5c757 /sys | |
parent | 88d7b8f56badfe1166bf9c4ca3fe30a8e9e4b306 (diff) | |
download | FreeBSD-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.c | 90 | ||||
-rw-r--r-- | sys/geom/geom_slice.h | 13 |
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_ */ |