summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/geom/bde/g_bde.h2
-rw-r--r--sys/geom/bde/g_bde_crypt.c93
-rw-r--r--sys/geom/bde/g_bde_work.c19
3 files changed, 66 insertions, 48 deletions
diff --git a/sys/geom/bde/g_bde.h b/sys/geom/bde/g_bde.h
index c5f9bf5abb39..b162e9621803 100644
--- a/sys/geom/bde/g_bde.h
+++ b/sys/geom/bde/g_bde.h
@@ -161,7 +161,7 @@ void g_bde_hash_pass(struct g_bde_softc *sc, const void *input, u_int len);
/* g_bde_math .c */
uint64_t g_bde_max_sector(struct g_bde_key *lp);
-void g_bde_map_sector(struct g_bde_key *lp, uint64_t isector, uint64_t *osector, uint64_t *ksector, u_int *koffset);
+void g_bde_map_sector(struct g_bde_work *wp);
/* g_bde_work.c */
void g_bde_start1(struct bio *bp);
diff --git a/sys/geom/bde/g_bde_crypt.c b/sys/geom/bde/g_bde_crypt.c
index bd368d8162f3..ec58dbffdf07 100644
--- a/sys/geom/bde/g_bde_crypt.c
+++ b/sys/geom/bde/g_bde_crypt.c
@@ -245,8 +245,13 @@ g_bde_max_sector(struct g_bde_key *kp)
* on a "cold" disk image.
*
* We do this by adding the "keyoffset" from the lock to the physical sector
- * number modulus the available number of sectors, since all physical sectors
- * presumably look the same cold, this should be enough.
+ * number modulus the available number of sectors. Since all physical sectors
+ * presumably look the same cold, this will do.
+ *
+ * As part of the mapping we have to skip the lock sectors which we know
+ * the physical address off. We also truncate the work packet, respecting
+ * zone boundaries and lock sectors, so that we end up with a sequence of
+ * sectors which are physically contiguous.
*
* Shuffling things further is an option, but the incremental frustration is
* not currently deemed worth the run-time performance hit resulting from the
@@ -257,52 +262,64 @@ g_bde_max_sector(struct g_bde_key *kp)
*/
void
-g_bde_map_sector(struct g_bde_key *kp,
- uint64_t isector,
- uint64_t *osector,
- uint64_t *ksector,
- u_int *koffset)
+g_bde_map_sector(struct g_bde_work *wp)
{
- u_int zone, zoff, zidx, u;
- uint64_t os;
+ u_int zone, zoff, u, len;
+ uint64_t ko;
+ struct g_bde_softc *sc;
+ struct g_bde_key *kp;
- /* find which zone and the offset and index in it */
- zone = isector / kp->zone_cont;
- zoff = isector % kp->zone_cont;
- zidx = zoff / kp->sectorsize;
+ sc = wp->softc;
+ kp = &sc->key;
- /* Find physical sector address */
- os = zone * kp->zone_width + zoff;
- os += kp->keyoffset;
- os %= kp->media_width;
- os += kp->sector0;
+ /* find which zone and the offset in it */
+ zone = wp->offset / kp->zone_cont;
+ zoff = wp->offset % kp->zone_cont;
- /* Compensate for lock sectors */
- for (u = 0; u < G_BDE_MAXKEYS; u++)
- if (os >= (kp->lsector[u] & ~(kp->sectorsize - 1)))
- os += kp->sectorsize;
+ /* Calculate the offset of the key in the key sector */
+ wp->ko = (zoff / kp->sectorsize) * G_BDE_SKEYLEN;
- *osector = os;
+ /* restrict length to that zone */
+ len = kp->zone_cont - zoff;
+ if (len < wp->length)
+ wp->length = len;
- /* The key sector is the last in this zone. */
- os = (1 + zone) * kp->zone_width - kp->sectorsize;
- os += kp->keyoffset;
- os %= kp->media_width;
- os += kp->sector0;
+ /* Find physical sector address */
+ wp->so = zone * kp->zone_width + zoff;
+ wp->so += kp->keyoffset;
+ wp->so %= kp->media_width;
+ wp->so += kp->sector0;
- for (u = 0; u < G_BDE_MAXKEYS; u++)
- if (os >= (kp->lsector[u] & ~(kp->sectorsize - 1)))
- os += kp->sectorsize;
- *ksector = os;
+ /* The key sector is the last in this zone. */
+ wp->kso = zone * kp->zone_width + kp->zone_cont;
+ wp->kso += kp->keyoffset;
+ wp->kso %= kp->media_width;
+ wp->kso += kp->sector0;
- *koffset = zidx * G_BDE_SKEYLEN;
+ /* Compensate for lock sectors */
+ for (u = 0; u < G_BDE_MAXKEYS; u++) {
+ /* Find the start of this lock sector */
+ ko = kp->lsector[u] & ~(kp->sectorsize - 1);
+
+ if (wp->kso >= ko)
+ wp->kso += kp->sectorsize;
+
+ if (wp->so >= ko) {
+ /* lock sector before work packet */
+ wp->so += kp->sectorsize;
+ } else if ((wp->so + wp->length) > ko) {
+ /* lock sector in work packet, truncate */
+ wp->length = ko - wp->so;
+ }
+ }
#if 0
- printf("off %jd %jd %jd %u\n",
- (intmax_t)isector,
- (intmax_t)*osector,
- (intmax_t)*ksector,
- *koffset);
+ printf("off %jd len %jd so %jd ko %jd kso %u\n",
+ (intmax_t)wp->offset,
+ (intmax_t)wp->length,
+ (intmax_t)wp->so,
+ (intmax_t)wp->kso,
+ wp->ko);
#endif
}
diff --git a/sys/geom/bde/g_bde_work.c b/sys/geom/bde/g_bde_work.c
index e173d804aa07..3635869ae868 100644
--- a/sys/geom/bde/g_bde_work.c
+++ b/sys/geom/bde/g_bde_work.c
@@ -651,10 +651,9 @@ g_bde_start2(struct g_bde_work *wp)
struct g_bde_softc *sc;
KASSERT(wp != NULL, ("NULL wp in g_bde_start2"));
+ KASSERT(wp->softc != NULL, ("NULL wp->softc"));
g_trace(G_T_TOPOLOGY, "g_bde_start2(%p)", wp);
sc = wp->softc;
- KASSERT(wp->softc != NULL, ("NULL wp->softc"));
- g_bde_map_sector(&sc->key, wp->offset, &wp->so, &wp->kso, &wp->ko);
if (wp->bp->bio_cmd == BIO_READ) {
wp->sp = g_bde_new_sector(wp, 0);
if (wp->sp == NULL) {
@@ -704,8 +703,8 @@ g_bde_start2(struct g_bde_work *wp)
}
/*
- * Split the incoming bio on zone boundaries and submit the resulting
- * work structures to g_bde_start2().
+ * Create a sequence of work structures, and have g_bde_map_sector() determine
+ * how long they each can be. Feed them to g_bde_start2().
*/
void
@@ -713,13 +712,13 @@ g_bde_start1(struct bio *bp)
{
struct g_bde_softc *sc;
struct g_bde_work *wp;
- off_t left;
+ off_t done;
sc = bp->bio_to->geom->softc;
bp->bio_driver1 = sc;
mtx_lock(&sc->worklist_mutex);
- for(left = 0;left < bp->bio_length; left += sc->sectorsize) {
+ for(done = 0; done < bp->bio_length; ) {
wp = g_bde_new_work(sc);
if (wp == NULL) {
g_io_deliver(bp, ENOMEM);
@@ -727,9 +726,11 @@ g_bde_start1(struct bio *bp)
return;
}
wp->bp = bp;
- wp->offset = bp->bio_offset + left;
- wp->data = bp->bio_data + left;
- wp->length = sc->sectorsize;
+ wp->offset = bp->bio_offset + done;
+ wp->data = bp->bio_data + done;
+ wp->length = bp->bio_length - done;
+ g_bde_map_sector(wp);
+ done += wp->length;
g_bde_start2(wp);
}
mtx_unlock(&sc->worklist_mutex);