Make more of the "hotspot" stuff generic:
Give the class a way to specify the necessary action for read/delete/write: ALLOW, DENY, START or CALL. Update geom_bsd to use this.
This commit is contained in:
parent
a41f716e91
commit
db4d21ffaf
@ -58,6 +58,7 @@
|
||||
|
||||
#define ALPHA_LABEL_OFFSET 64
|
||||
|
||||
static void g_bsd_hotwrite(void *arg, int flag);
|
||||
/*
|
||||
* Our private data about one instance. All the rest is handled by the
|
||||
* slice code and stored in its softc, so this is just the stuff
|
||||
@ -190,6 +191,7 @@ g_bsd_modify(struct g_geom *gp, struct disklabel *dl)
|
||||
struct partition *ppp;
|
||||
struct g_slicer *gsp;
|
||||
struct g_consumer *cp;
|
||||
struct g_bsd_softc *ms;
|
||||
u_int secsize, u;
|
||||
off_t mediasize;
|
||||
|
||||
@ -244,6 +246,7 @@ g_bsd_modify(struct g_geom *gp, struct disklabel *dl)
|
||||
|
||||
/* Don't munge open partitions. */
|
||||
gsp = gp->softc;
|
||||
ms = gsp->softc;
|
||||
for (i = 0; i < dl->d_npartitions; i++) {
|
||||
ppp = &dl->d_partitions[i];
|
||||
|
||||
@ -267,6 +270,9 @@ g_bsd_modify(struct g_geom *gp, struct disklabel *dl)
|
||||
dl->d_secsize,
|
||||
"%s%c", gp->name, 'a' + u);
|
||||
}
|
||||
g_slice_conf_hot(gp, 0, ms->labeloffset, g_bsd_ondisk_size(),
|
||||
G_SLICE_HOT_ALLOW, G_SLICE_HOT_DENY, G_SLICE_HOT_CALL);
|
||||
gsp->hot = g_bsd_hotwrite;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -332,13 +338,7 @@ g_bsd_try(struct g_geom *gp, struct g_slicer *gsp, struct g_consumer *cp, int se
|
||||
/* Remember to free the buffer g_read_data() gave us. */
|
||||
g_free(buf);
|
||||
|
||||
/* If we had a label, record it properly. */
|
||||
if (error == 0) {
|
||||
ms->labeloffset = offset;
|
||||
g_topology_lock();
|
||||
g_slice_conf_hot(gp, 0, offset, g_bsd_ondisk_size());
|
||||
g_topology_unlock();
|
||||
}
|
||||
ms->labeloffset = offset;
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -494,6 +494,10 @@ g_bsd_hotwrite(void *arg, int flag)
|
||||
u_char *p;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* We should never get canceled, because that would amount to a removal
|
||||
* of the geom while there was outstanding I/O requests.
|
||||
*/
|
||||
KASSERT(flag != EV_CANCEL, ("g_bsd_hotwrite cancelled"));
|
||||
bp = arg;
|
||||
gp = bp->bio_to->geom;
|
||||
@ -551,15 +555,6 @@ g_bsd_start(struct bio *bp)
|
||||
gsp = gp->softc;
|
||||
ms = gsp->softc;
|
||||
switch(bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
/* We allow reading of our hot spots */
|
||||
return (0);
|
||||
case BIO_DELETE:
|
||||
/* We do not allow deleting our hot spots */
|
||||
return (EPERM);
|
||||
case BIO_WRITE:
|
||||
g_call_me(g_bsd_hotwrite, bp, gp, NULL);
|
||||
return (EJUSTRETURN);
|
||||
case BIO_GETATTR:
|
||||
if (g_handleattr(bp, "BSD::labelsum", ms->labelsum,
|
||||
sizeof(ms->labelsum)))
|
||||
|
@ -112,6 +112,13 @@ g_slice_access(struct g_provider *pp, int dr, int dw, int de)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: It should be possible to specify here if we should finish all of the
|
||||
* XXX: bio, or only the non-hot bits. This would get messy if there were
|
||||
* XXX: two hot spots in the same bio, so for now we simply finish off the
|
||||
* XXX: entire bio. Modifying hot data on the way to disk is frowned on
|
||||
* XXX: so making that considerably harder is not a bad idea anyway.
|
||||
*/
|
||||
void
|
||||
g_slice_finish_hot(struct bio *bp)
|
||||
{
|
||||
@ -122,8 +129,10 @@ g_slice_finish_hot(struct bio *bp)
|
||||
struct g_slice *gsl;
|
||||
int idx;
|
||||
|
||||
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));
|
||||
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);
|
||||
@ -153,7 +162,7 @@ g_slice_start(struct bio *bp)
|
||||
struct g_consumer *cp;
|
||||
struct g_slicer *gsp;
|
||||
struct g_slice *gsl;
|
||||
struct g_slice_hot *gmp;
|
||||
struct g_slice_hot *ghp;
|
||||
int idx, error;
|
||||
u_int m_index;
|
||||
off_t t;
|
||||
@ -177,22 +186,33 @@ g_slice_start(struct bio *bp)
|
||||
* method once if so.
|
||||
*/
|
||||
t = bp->bio_offset + gsl->offset;
|
||||
/* .ctl devices may take us negative */
|
||||
if (t < 0 || (t + bp->bio_length) < 0) {
|
||||
g_io_deliver(bp, EINVAL);
|
||||
return;
|
||||
}
|
||||
for (m_index = 0; m_index < gsp->nhotspot; m_index++) {
|
||||
gmp = &gsp->hotspot[m_index];
|
||||
if (t >= gmp->offset + gmp->length)
|
||||
ghp = &gsp->hotspot[m_index];
|
||||
if (t >= ghp->offset + ghp->length)
|
||||
continue;
|
||||
if (t + bp->bio_length <= gmp->offset)
|
||||
if (t + bp->bio_length <= ghp->offset)
|
||||
continue;
|
||||
error = gsp->start(bp);
|
||||
if (error == EJUSTRETURN)
|
||||
switch(bp->bio_cmd) {
|
||||
case BIO_READ: idx = ghp->ract; break;
|
||||
case BIO_WRITE: idx = ghp->wact; break;
|
||||
case BIO_DELETE: idx = ghp->dact; break;
|
||||
}
|
||||
switch(idx) {
|
||||
case G_SLICE_HOT_ALLOW:
|
||||
/* Fall out and continue normal processing */
|
||||
continue;
|
||||
case G_SLICE_HOT_DENY:
|
||||
g_io_deliver(bp, EROFS);
|
||||
return;
|
||||
else if (error) {
|
||||
g_io_deliver(bp, error);
|
||||
case G_SLICE_HOT_START:
|
||||
error = gsp->start(bp);
|
||||
if (error && error != EJUSTRETURN)
|
||||
g_io_deliver(bp, error);
|
||||
return;
|
||||
case G_SLICE_HOT_CALL:
|
||||
error = g_call_me(gsp->hot, bp, gp, NULL);
|
||||
if (error)
|
||||
g_io_deliver(bp, error);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -338,13 +358,27 @@ g_slice_config(struct g_geom *gp, u_int idx, int how, off_t offset, off_t length
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure "hotspots". A hotspot is a piece of the parent device which
|
||||
* this particular slicer cares about for some reason. Typically because
|
||||
* it contains meta-data used to configure the slicer.
|
||||
* A hotspot is identified by its index number. The offset and length are
|
||||
* relative to the parent device, and the three "?act" fields specify
|
||||
* what action to take on BIO_READ, BIO_DELETE and BIO_WRITE.
|
||||
*
|
||||
* XXX: There may be a race relative to g_slice_start() here, if an existing
|
||||
* XXX: hotspot is changed wile I/O is happening. Should this become a problem
|
||||
* XXX: we can protect the hotspot stuff with a mutex.
|
||||
*/
|
||||
|
||||
int
|
||||
g_slice_conf_hot(struct g_geom *gp, u_int idx, off_t offset, off_t length)
|
||||
g_slice_conf_hot(struct g_geom *gp, u_int idx, off_t offset, off_t length, int ract, int dact, int wact)
|
||||
{
|
||||
struct g_slicer *gsp;
|
||||
struct g_slice_hot *gsl, *gsl2;
|
||||
|
||||
g_trace(G_T_TOPOLOGY, "g_slice_conf_hot()");
|
||||
g_trace(G_T_TOPOLOGY, "g_slice_conf_hot(%s, idx: %d, off: %jd, len: %jd)",
|
||||
gp->name, idx, (intmax_t)offset, (intmax_t)length);
|
||||
g_topology_assert();
|
||||
gsp = gp->softc;
|
||||
gsl = gsp->hotspot;
|
||||
@ -358,12 +392,11 @@ g_slice_conf_hot(struct g_geom *gp, u_int idx, off_t offset, off_t length)
|
||||
gsl = gsl2;
|
||||
gsp->nhotspot = idx + 1;
|
||||
}
|
||||
if (bootverbose)
|
||||
printf("GEOM: Add %s hot[%d] start %jd length %jd end %jd\n",
|
||||
gp->name, idx, (intmax_t)offset, (intmax_t)length,
|
||||
(intmax_t)(offset + length - 1));
|
||||
gsl[idx].offset = offset;
|
||||
gsl[idx].length = length;
|
||||
gsl[idx].ract = ract;
|
||||
gsl[idx].dact = dact;
|
||||
gsl[idx].wact = wact;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,9 @@ struct g_slice {
|
||||
struct g_slice_hot {
|
||||
off_t offset;
|
||||
off_t length;
|
||||
int ract;
|
||||
int dact;
|
||||
int wact;
|
||||
};
|
||||
|
||||
typedef int g_slice_start_t (struct bio *bp);
|
||||
@ -56,10 +59,13 @@ struct g_slicer {
|
||||
u_int nslice;
|
||||
u_int nprovider;
|
||||
struct g_slice *slices;
|
||||
|
||||
u_int nhotspot;
|
||||
struct g_slice_hot *hotspot;
|
||||
|
||||
void *softc;
|
||||
g_slice_start_t *start;
|
||||
g_call_me_t *hot;
|
||||
};
|
||||
|
||||
g_dumpconf_t g_slice_dumpconf;
|
||||
@ -69,7 +75,12 @@ int g_slice_config(struct g_geom *gp, u_int idx, int how, off_t offset, off_t le
|
||||
#define G_SLICE_CONFIG_FORCE 2
|
||||
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 idx, off_t offset, off_t length);
|
||||
int g_slice_conf_hot(struct g_geom *gp, u_int idx, off_t offset, off_t length, int ract, int dact, int wact);
|
||||
#define G_SLICE_HOT_ALLOW 1
|
||||
#define G_SLICE_HOT_DENY 2
|
||||
#define G_SLICE_HOT_START 4
|
||||
#define G_SLICE_HOT_CALL 8
|
||||
|
||||
void g_slice_finish_hot(struct bio *bp);
|
||||
|
||||
#endif /* _GEOM_GEOM_SLICE_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user