--- a/usr/src/uts/common/fs/zfs/zio.c Thu Apr 23 18:28:16 2009 -0500
+++ b/usr/src/uts/common/fs/zfs/zio.c Thu Apr 23 17:33:43 2009 -0700
@@ -490,11 +490,10 @@
zio->io_bp_orig = *bp;
if (type != ZIO_TYPE_WRITE)
zio->io_bp = &zio->io_bp_copy; /* so caller can free */
- if (zio->io_child_type == ZIO_CHILD_LOGICAL) {
- if (BP_IS_GANG(bp))
- pipeline |= ZIO_GANG_STAGES;
+ if (zio->io_child_type == ZIO_CHILD_LOGICAL)
zio->io_logical = zio;
- }
+ if (zio->io_child_type > ZIO_CHILD_GANG && BP_IS_GANG(bp))
+ pipeline |= ZIO_GANG_STAGES;
}
zio->io_spa = spa;
@@ -520,6 +519,8 @@
if (pio != NULL) {
if (zio->io_logical == NULL)
zio->io_logical = pio->io_logical;
+ if (zio->io_child_type == ZIO_CHILD_GANG)
+ zio->io_gang_leader = pio->io_gang_leader;
zio_add_child(pio, zio);
}
@@ -826,7 +827,8 @@
blkptr_t *bp = zio->io_bp;
if (BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF &&
- zio->io_logical == zio && !(zio->io_flags & ZIO_FLAG_RAW)) {
+ zio->io_child_type == ZIO_CHILD_LOGICAL &&
+ !(zio->io_flags & ZIO_FLAG_RAW)) {
uint64_t csize = BP_GET_PSIZE(bp);
void *cbuf = zio_buf_alloc(csize);
@@ -1100,6 +1102,8 @@
ASSERT(pio->io_child_type == ZIO_CHILD_LOGICAL);
ASSERT(pio->io_orig_stage == ZIO_STAGE_OPEN);
+ ASSERT(pio->io_gang_leader == NULL);
+ ASSERT(pio->io_gang_tree == NULL);
pio->io_flags = pio->io_orig_flags;
pio->io_stage = pio->io_orig_stage;
@@ -1307,7 +1311,7 @@
* (Presently, nothing actually uses interior data checksums;
* this is just good hygiene.)
*/
- if (gn != pio->io_logical->io_gang_tree) {
+ if (gn != pio->io_gang_leader->io_gang_tree) {
zio_checksum_compute(zio, BP_GET_CHECKSUM(bp),
data, BP_GET_PSIZE(bp));
}
@@ -1389,27 +1393,26 @@
}
static void
-zio_gang_tree_assemble(zio_t *lio, blkptr_t *bp, zio_gang_node_t **gnpp)
+zio_gang_tree_assemble(zio_t *gio, blkptr_t *bp, zio_gang_node_t **gnpp)
{
zio_gang_node_t *gn = zio_gang_node_alloc(gnpp);
- ASSERT(lio->io_logical == lio);
+ ASSERT(gio->io_gang_leader == gio);
ASSERT(BP_IS_GANG(bp));
- zio_nowait(zio_read(lio, lio->io_spa, bp, gn->gn_gbh,
+ zio_nowait(zio_read(gio, gio->io_spa, bp, gn->gn_gbh,
SPA_GANGBLOCKSIZE, zio_gang_tree_assemble_done, gn,
- lio->io_priority, ZIO_GANG_CHILD_FLAGS(lio), &lio->io_bookmark));
+ gio->io_priority, ZIO_GANG_CHILD_FLAGS(gio), &gio->io_bookmark));
}
static void
zio_gang_tree_assemble_done(zio_t *zio)
{
- zio_t *lio = zio->io_logical;
+ zio_t *gio = zio->io_gang_leader;
zio_gang_node_t *gn = zio->io_private;
blkptr_t *bp = zio->io_bp;
- zio_t *pio = zio_unique_parent(zio);
- ASSERT(pio == lio);
+ ASSERT(gio == zio_unique_parent(zio));
ASSERT(zio_walk_children(zio) == NULL);
if (zio->io_error)
@@ -1426,25 +1429,25 @@
blkptr_t *gbp = &gn->gn_gbh->zg_blkptr[g];
if (!BP_IS_GANG(gbp))
continue;
- zio_gang_tree_assemble(lio, gbp, &gn->gn_child[g]);
+ zio_gang_tree_assemble(gio, gbp, &gn->gn_child[g]);
}
}
static void
zio_gang_tree_issue(zio_t *pio, zio_gang_node_t *gn, blkptr_t *bp, void *data)
{
- zio_t *lio = pio->io_logical;
+ zio_t *gio = pio->io_gang_leader;
zio_t *zio;
ASSERT(BP_IS_GANG(bp) == !!gn);
- ASSERT(BP_GET_CHECKSUM(bp) == BP_GET_CHECKSUM(lio->io_bp));
- ASSERT(BP_GET_LSIZE(bp) == BP_GET_PSIZE(bp) || gn == lio->io_gang_tree);
+ ASSERT(BP_GET_CHECKSUM(bp) == BP_GET_CHECKSUM(gio->io_bp));
+ ASSERT(BP_GET_LSIZE(bp) == BP_GET_PSIZE(bp) || gn == gio->io_gang_tree);
/*
* If you're a gang header, your data is in gn->gn_gbh.
* If you're a gang member, your data is in 'data' and gn == NULL.
*/
- zio = zio_gang_issue_func[lio->io_type](pio, bp, gn, data);
+ zio = zio_gang_issue_func[gio->io_type](pio, bp, gn, data);
if (gn != NULL) {
ASSERT(gn->gn_gbh->zg_tail.zbt_magic == ZBT_MAGIC);
@@ -1458,8 +1461,8 @@
}
}
- if (gn == lio->io_gang_tree)
- ASSERT3P((char *)lio->io_data + lio->io_size, ==, data);
+ if (gn == gio->io_gang_tree)
+ ASSERT3P((char *)gio->io_data + gio->io_size, ==, data);
if (zio != pio)
zio_nowait(zio);
@@ -1470,7 +1473,10 @@
{
blkptr_t *bp = zio->io_bp;
- ASSERT(BP_IS_GANG(bp) && zio == zio->io_logical);
+ ASSERT(BP_IS_GANG(bp) && zio->io_gang_leader == NULL);
+ ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
+
+ zio->io_gang_leader = zio;
zio_gang_tree_assemble(zio, bp, &zio->io_gang_tree);
@@ -1480,18 +1486,18 @@
static int
zio_gang_issue(zio_t *zio)
{
- zio_t *lio = zio->io_logical;
blkptr_t *bp = zio->io_bp;
if (zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_DONE))
return (ZIO_PIPELINE_STOP);
- ASSERT(BP_IS_GANG(bp) && zio == lio);
+ ASSERT(BP_IS_GANG(bp) && zio->io_gang_leader == zio);
+ ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
if (zio->io_child_error[ZIO_CHILD_GANG] == 0)
- zio_gang_tree_issue(lio, lio->io_gang_tree, bp, lio->io_data);
+ zio_gang_tree_issue(zio, zio->io_gang_tree, bp, zio->io_data);
else
- zio_gang_tree_free(&lio->io_gang_tree);
+ zio_gang_tree_free(&zio->io_gang_tree);
zio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
@@ -1502,7 +1508,7 @@
zio_write_gang_member_ready(zio_t *zio)
{
zio_t *pio = zio_unique_parent(zio);
- zio_t *lio = zio->io_logical;
+ zio_t *gio = zio->io_gang_leader;
dva_t *cdva = zio->io_bp->blk_dva;
dva_t *pdva = pio->io_bp->blk_dva;
uint64_t asize;
@@ -1513,7 +1519,7 @@
ASSERT(BP_IS_HOLE(&zio->io_bp_orig));
ASSERT(zio->io_child_type == ZIO_CHILD_GANG);
- ASSERT3U(zio->io_prop.zp_ndvas, ==, lio->io_prop.zp_ndvas);
+ ASSERT3U(zio->io_prop.zp_ndvas, ==, gio->io_prop.zp_ndvas);
ASSERT3U(zio->io_prop.zp_ndvas, <=, BP_GET_NDVAS(zio->io_bp));
ASSERT3U(pio->io_prop.zp_ndvas, <=, BP_GET_NDVAS(pio->io_bp));
ASSERT3U(BP_GET_NDVAS(zio->io_bp), <=, BP_GET_NDVAS(pio->io_bp));
@@ -1533,28 +1539,28 @@
{
spa_t *spa = pio->io_spa;
blkptr_t *bp = pio->io_bp;
- zio_t *lio = pio->io_logical;
+ zio_t *gio = pio->io_gang_leader;
zio_t *zio;
zio_gang_node_t *gn, **gnpp;
zio_gbh_phys_t *gbh;
uint64_t txg = pio->io_txg;
uint64_t resid = pio->io_size;
uint64_t lsize;
- int ndvas = lio->io_prop.zp_ndvas;
+ int ndvas = gio->io_prop.zp_ndvas;
int gbh_ndvas = MIN(ndvas + 1, spa_max_replication(spa));
zio_prop_t zp;
int error;
error = metaslab_alloc(spa, spa->spa_normal_class, SPA_GANGBLOCKSIZE,
- bp, gbh_ndvas, txg, pio == lio ? NULL : lio->io_bp,
+ bp, gbh_ndvas, txg, pio == gio ? NULL : gio->io_bp,
METASLAB_HINTBP_FAVOR | METASLAB_GANG_HEADER);
if (error) {
pio->io_error = error;
return (ZIO_PIPELINE_CONTINUE);
}
- if (pio == lio) {
- gnpp = &lio->io_gang_tree;
+ if (pio == gio) {
+ gnpp = &gio->io_gang_tree;
} else {
gnpp = pio->io_private;
ASSERT(pio->io_ready == zio_write_gang_member_ready);
@@ -1578,11 +1584,11 @@
SPA_MINBLOCKSIZE);
ASSERT(lsize >= SPA_MINBLOCKSIZE && lsize <= resid);
- zp.zp_checksum = lio->io_prop.zp_checksum;
+ zp.zp_checksum = gio->io_prop.zp_checksum;
zp.zp_compress = ZIO_COMPRESS_OFF;
zp.zp_type = DMU_OT_NONE;
zp.zp_level = 0;
- zp.zp_ndvas = lio->io_prop.zp_ndvas;
+ zp.zp_ndvas = gio->io_prop.zp_ndvas;
zio_nowait(zio_write(zio, spa, txg, &gbh->zg_blkptr[g],
(char *)pio->io_data + (pio->io_size - resid), lsize, &zp,
@@ -1615,6 +1621,11 @@
blkptr_t *bp = zio->io_bp;
int error;
+ if (zio->io_gang_leader == NULL) {
+ ASSERT(zio->io_child_type > ZIO_CHILD_GANG);
+ zio->io_gang_leader = zio;
+ }
+
ASSERT(BP_IS_HOLE(bp));
ASSERT3U(BP_GET_NDVAS(bp), ==, 0);
ASSERT3U(zio->io_prop.zp_ndvas, >, 0);
@@ -2059,11 +2070,10 @@
blkptr_t *bp = zio->io_bp;
zio_t *pio, *pio_next;
+ if (zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_READY))
+ return (ZIO_PIPELINE_STOP);
+
if (zio->io_ready) {
- if (BP_IS_GANG(bp) &&
- zio_wait_for_children(zio, ZIO_CHILD_GANG, ZIO_WAIT_READY))
- return (ZIO_PIPELINE_STOP);
-
ASSERT(IO_IS_ALLOCATING(zio));
ASSERT(bp->blk_birth == zio->io_txg || BP_IS_HOLE(bp));
ASSERT(zio->io_children[ZIO_CHILD_GANG][ZIO_WAIT_READY] == 0);
@@ -2108,7 +2118,7 @@
zio_t *pio, *pio_next;
/*
- * If our of children haven't all completed,
+ * If our children haven't all completed,
* wait for them and then repeat this pipeline stage.
*/
if (zio_wait_for_children(zio, ZIO_CHILD_VDEV, ZIO_WAIT_DONE) ||
@@ -2199,6 +2209,14 @@
*/
zio_inherit_child_errors(zio, ZIO_CHILD_LOGICAL);
+ if ((zio->io_error || zio->io_reexecute) && IO_IS_ALLOCATING(zio) &&
+ zio->io_child_type == ZIO_CHILD_LOGICAL) {
+ ASSERT(zio->io_child_type != ZIO_CHILD_GANG);
+ zio_dva_unallocate(zio, zio->io_gang_tree, bp);
+ }
+
+ zio_gang_tree_free(&zio->io_gang_tree);
+
if (zio->io_reexecute && !(zio->io_flags & ZIO_FLAG_GODFATHER)) {
/*
* This is a logical I/O that wants to reexecute.
@@ -2215,10 +2233,7 @@
*/
ASSERT(zio->io_child_type == ZIO_CHILD_LOGICAL);
- if (IO_IS_ALLOCATING(zio))
- zio_dva_unallocate(zio, zio->io_gang_tree, bp);
-
- zio_gang_tree_free(&zio->io_gang_tree);
+ zio->io_gang_leader = NULL;
mutex_enter(&zio->io_lock);
zio->io_state[ZIO_WAIT_DONE] = 1;
@@ -2280,8 +2295,6 @@
if (zio->io_done)
zio->io_done(zio);
- zio_gang_tree_free(&zio->io_gang_tree);
-
mutex_enter(&zio->io_lock);
zio->io_state[ZIO_WAIT_DONE] = 1;
mutex_exit(&zio->io_lock);