summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2017-10-01 15:03:44 +0000
committeravg <avg@FreeBSD.org>2017-10-01 15:03:44 +0000
commitf06a9a5a8f5dcc0bbf7c6a00fbe76dc108a3661c (patch)
treee6cca0bb90d7520e47fbc4077be0cdffbfec1e47
parentdcfc2bd7cd1285924c2dcad43a959a082ffb2903 (diff)
downloadFreeBSD-src-f06a9a5a8f5dcc0bbf7c6a00fbe76dc108a3661c.zip
FreeBSD-src-f06a9a5a8f5dcc0bbf7c6a00fbe76dc108a3661c.tar.gz
MFV r323796: fix memory leak in g_bio zone introduced in r320452
I overlooked the fact that that ZIO_IOCTL_PIPELINE does not include ZIO_STAGE_VDEV_IO_DONE stage. We do allocate a struct bio for an ioctl zio (a disk cache flush), but we never freed it. This change splits bio handling into two groups, one for normal read/write i/o that passes data around and, thus, needs the abd data tranform; the other group is for "data-less" i/o such as trim and cache flush. PR: 222288
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
index d67220a..d863e0b 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -989,6 +989,15 @@ vdev_geom_io_intr(struct bio *bp)
break;
}
+ /*
+ * We have to split bio freeing into two parts, because the ABD code
+ * cannot be called in this context and vdev_op_io_done is not called
+ * for ZIO_TYPE_IOCTL zio-s.
+ */
+ if (zio->io_type != ZIO_TYPE_READ && zio->io_type != ZIO_TYPE_WRITE) {
+ g_destroy_bio(bp);
+ zio->io_bio = NULL;
+ }
zio_delay_interrupt(zio);
}
@@ -1090,21 +1099,23 @@ vdev_geom_io_done(zio_t *zio)
{
struct bio *bp = zio->io_bio;
+ if (zio->io_type != ZIO_TYPE_READ && zio->io_type != ZIO_TYPE_WRITE) {
+ ASSERT(bp == NULL);
+ return;
+ }
+
if (bp == NULL) {
- ASSERT3S(zio->io_error, !=, 0);
- IMPLY(zio->io_type == ZIO_TYPE_READ ||
- zio->io_type == ZIO_TYPE_WRITE,
- zio->io_error == ENXIO);
+ ASSERT3S(zio->io_error, ==, ENXIO);
return;
}
- if (zio->io_type == ZIO_TYPE_READ) {
+ if (zio->io_type == ZIO_TYPE_READ)
abd_return_buf_copy(zio->io_abd, bp->bio_data, zio->io_size);
- } else if (zio->io_type == ZIO_TYPE_WRITE) {
+ else
abd_return_buf(zio->io_abd, bp->bio_data, zio->io_size);
- }
g_destroy_bio(bp);
+ zio->io_bio = NULL;
}
static void
OpenPOWER on IntegriCloud