summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2009-07-10 13:33:52 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-07-10 12:25:36 -0500
commit7d8abfcb50a33aed369bbd267852cf04009c49e9 (patch)
tree9741ee54b0a4a87a4b96b579ec36812d329b8efa /qemu-io.c
parentqemu-io: add flag to mark files growable (diff)
downloadqemu-kvm-7d8abfcb50a33aed369bbd267852cf04009c49e9.tar.gz
qemu-kvm-7d8abfcb50a33aed369bbd267852cf04009c49e9.tar.bz2
qemu-kvm-7d8abfcb50a33aed369bbd267852cf04009c49e9.zip
qemu-io: fix memory leak
qemu-io leaks the request buffer whenever the read or write function isn't executed completely down the "normal" code path. [hch: also fix the aio and vectored variants the same way] Signed-off-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'qemu-io.c')
-rw-r--r--qemu-io.c60
1 files changed, 38 insertions, 22 deletions
diff --git a/qemu-io.c b/qemu-io.c
index 08c33f275..076984a94 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -358,7 +358,7 @@ read_f(int argc, char **argv)
if (cnt < 0) {
printf("read failed: %s\n", strerror(-cnt));
- return 0;
+ goto out;
}
if (Pflag) {
@@ -373,7 +373,7 @@ read_f(int argc, char **argv)
}
if (qflag)
- return 0;
+ goto out;
if (vflag)
dump_buffer(buf, offset, count);
@@ -382,6 +382,7 @@ read_f(int argc, char **argv)
t2 = tsub(t2, t1);
print_report("read", &t2, offset, count, total, cnt, Cflag);
+out:
qemu_io_free(buf);
return 0;
@@ -480,7 +481,7 @@ readv_f(int argc, char **argv)
if (cnt < 0) {
printf("readv failed: %s\n", strerror(-cnt));
- return 0;
+ goto out;
}
if (Pflag) {
@@ -495,7 +496,7 @@ readv_f(int argc, char **argv)
}
if (qflag)
- return 0;
+ goto out;
if (vflag)
dump_buffer(buf, offset, qiov.size);
@@ -504,8 +505,8 @@ readv_f(int argc, char **argv)
t2 = tsub(t2, t1);
print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
+out:
qemu_io_free(buf);
-
return 0;
}
@@ -613,16 +614,17 @@ write_f(int argc, char **argv)
if (cnt < 0) {
printf("write failed: %s\n", strerror(-cnt));
- return 0;
+ goto out;
}
if (qflag)
- return 0;
+ goto out;
/* Finally, report back -- -C gives a parsable format */
t2 = tsub(t2, t1);
print_report("wrote", &t2, offset, count, total, cnt, Cflag);
+out:
qemu_io_free(buf);
return 0;
@@ -713,18 +715,17 @@ writev_f(int argc, char **argv)
if (cnt < 0) {
printf("writev failed: %s\n", strerror(-cnt));
- return 0;
+ goto out;
}
if (qflag)
- return 0;
+ goto out;
/* Finally, report back -- -C gives a parsable format */
t2 = tsub(t2, t1);
print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
-
+out:
qemu_io_free(buf);
-
return 0;
}
@@ -761,18 +762,18 @@ aio_write_done(void *opaque, int ret)
if (ret < 0) {
printf("aio_write failed: %s\n", strerror(-ret));
- return;
+ goto out;
}
if (ctx->qflag) {
- return;
+ goto out;
}
/* Finally, report back -- -C gives a parsable format */
t2 = tsub(t2, ctx->t1);
print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
ctx->qiov.size, 1, ctx->Cflag);
-
+out:
qemu_io_free(ctx->buf);
free(ctx);
}
@@ -789,7 +790,7 @@ aio_read_done(void *opaque, int ret)
if (ret < 0) {
printf("readv failed: %s\n", strerror(-ret));
- return;
+ goto out;
}
if (ctx->Pflag) {
@@ -805,7 +806,7 @@ aio_read_done(void *opaque, int ret)
}
if (ctx->qflag) {
- return;
+ goto out;
}
if (ctx->vflag) {
@@ -816,7 +817,7 @@ aio_read_done(void *opaque, int ret)
t2 = tsub(t2, ctx->t1);
print_report("read", &t2, ctx->offset, ctx->qiov.size,
ctx->qiov.size, 1, ctx->Cflag);
-
+out:
qemu_io_free(ctx->buf);
free(ctx);
}
@@ -865,17 +866,20 @@ aio_read_f(int argc, char **argv)
ctx->vflag = 1;
break;
default:
+ free(ctx);
return command_usage(&aio_read_cmd);
}
}
- if (optind > argc - 2)
+ if (optind > argc - 2) {
+ free(ctx);
return command_usage(&aio_read_cmd);
-
+ }
ctx->offset = cvtnum(argv[optind]);
if (ctx->offset < 0) {
printf("non-numeric length argument -- %s\n", argv[optind]);
+ free(ctx);
return 0;
}
optind++;
@@ -883,6 +887,7 @@ aio_read_f(int argc, char **argv)
if (ctx->offset & 0x1ff) {
printf("offset %lld is not sector aligned\n",
(long long)ctx->offset);
+ free(ctx);
return 0;
}
@@ -892,8 +897,11 @@ aio_read_f(int argc, char **argv)
gettimeofday(&ctx->t1, NULL);
acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
ctx->qiov.size >> 9, aio_read_done, ctx);
- if (!acb)
+ if (!acb) {
+ free(ctx->buf);
+ free(ctx);
return -EIO;
+ }
return 0;
}
@@ -952,16 +960,20 @@ aio_write_f(int argc, char **argv)
pattern = atoi(optarg);
break;
default:
+ free(ctx);
return command_usage(&aio_write_cmd);
}
}
- if (optind > argc - 2)
+ if (optind > argc - 2) {
+ free(ctx);
return command_usage(&aio_write_cmd);
+ }
ctx->offset = cvtnum(argv[optind]);
if (ctx->offset < 0) {
printf("non-numeric length argument -- %s\n", argv[optind]);
+ free(ctx);
return 0;
}
optind++;
@@ -969,6 +981,7 @@ aio_write_f(int argc, char **argv)
if (ctx->offset & 0x1ff) {
printf("offset %lld is not sector aligned\n",
(long long)ctx->offset);
+ free(ctx);
return 0;
}
@@ -978,8 +991,11 @@ aio_write_f(int argc, char **argv)
gettimeofday(&ctx->t1, NULL);
acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
ctx->qiov.size >> 9, aio_write_done, ctx);
- if (!acb)
+ if (!acb) {
+ free(ctx->buf);
+ free(ctx);
return -EIO;
+ }
return 0;
}