Add a simplified version of the hot-spot code to enable us to protect
in-band disklabels from in-band vandalism. Approve by: re
This commit is contained in:
parent
a3dca4517e
commit
188321b737
@ -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)
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user