mirror of https://github.com/xemu-project/xemu.git
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>
This commit is contained in:
parent
9c4bab2668
commit
7d8abfcb50
60
qemu-io.c
60
qemu-io.c
|
@ -358,7 +358,7 @@ read_f(int argc, char **argv)
|
||||||
|
|
||||||
if (cnt < 0) {
|
if (cnt < 0) {
|
||||||
printf("read failed: %s\n", strerror(-cnt));
|
printf("read failed: %s\n", strerror(-cnt));
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Pflag) {
|
if (Pflag) {
|
||||||
|
@ -373,7 +373,7 @@ read_f(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qflag)
|
if (qflag)
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
if (vflag)
|
if (vflag)
|
||||||
dump_buffer(buf, offset, count);
|
dump_buffer(buf, offset, count);
|
||||||
|
@ -382,6 +382,7 @@ read_f(int argc, char **argv)
|
||||||
t2 = tsub(t2, t1);
|
t2 = tsub(t2, t1);
|
||||||
print_report("read", &t2, offset, count, total, cnt, Cflag);
|
print_report("read", &t2, offset, count, total, cnt, Cflag);
|
||||||
|
|
||||||
|
out:
|
||||||
qemu_io_free(buf);
|
qemu_io_free(buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -480,7 +481,7 @@ readv_f(int argc, char **argv)
|
||||||
|
|
||||||
if (cnt < 0) {
|
if (cnt < 0) {
|
||||||
printf("readv failed: %s\n", strerror(-cnt));
|
printf("readv failed: %s\n", strerror(-cnt));
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Pflag) {
|
if (Pflag) {
|
||||||
|
@ -495,7 +496,7 @@ readv_f(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qflag)
|
if (qflag)
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
if (vflag)
|
if (vflag)
|
||||||
dump_buffer(buf, offset, qiov.size);
|
dump_buffer(buf, offset, qiov.size);
|
||||||
|
@ -504,8 +505,8 @@ readv_f(int argc, char **argv)
|
||||||
t2 = tsub(t2, t1);
|
t2 = tsub(t2, t1);
|
||||||
print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
|
print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
|
||||||
|
|
||||||
|
out:
|
||||||
qemu_io_free(buf);
|
qemu_io_free(buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,16 +614,17 @@ write_f(int argc, char **argv)
|
||||||
|
|
||||||
if (cnt < 0) {
|
if (cnt < 0) {
|
||||||
printf("write failed: %s\n", strerror(-cnt));
|
printf("write failed: %s\n", strerror(-cnt));
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qflag)
|
if (qflag)
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
/* Finally, report back -- -C gives a parsable format */
|
/* Finally, report back -- -C gives a parsable format */
|
||||||
t2 = tsub(t2, t1);
|
t2 = tsub(t2, t1);
|
||||||
print_report("wrote", &t2, offset, count, total, cnt, Cflag);
|
print_report("wrote", &t2, offset, count, total, cnt, Cflag);
|
||||||
|
|
||||||
|
out:
|
||||||
qemu_io_free(buf);
|
qemu_io_free(buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -713,18 +715,17 @@ writev_f(int argc, char **argv)
|
||||||
|
|
||||||
if (cnt < 0) {
|
if (cnt < 0) {
|
||||||
printf("writev failed: %s\n", strerror(-cnt));
|
printf("writev failed: %s\n", strerror(-cnt));
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qflag)
|
if (qflag)
|
||||||
return 0;
|
goto out;
|
||||||
|
|
||||||
/* Finally, report back -- -C gives a parsable format */
|
/* Finally, report back -- -C gives a parsable format */
|
||||||
t2 = tsub(t2, t1);
|
t2 = tsub(t2, t1);
|
||||||
print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
|
print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
|
||||||
|
out:
|
||||||
qemu_io_free(buf);
|
qemu_io_free(buf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,18 +762,18 @@ aio_write_done(void *opaque, int ret)
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printf("aio_write failed: %s\n", strerror(-ret));
|
printf("aio_write failed: %s\n", strerror(-ret));
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->qflag) {
|
if (ctx->qflag) {
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally, report back -- -C gives a parsable format */
|
/* Finally, report back -- -C gives a parsable format */
|
||||||
t2 = tsub(t2, ctx->t1);
|
t2 = tsub(t2, ctx->t1);
|
||||||
print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
|
print_report("wrote", &t2, ctx->offset, ctx->qiov.size,
|
||||||
ctx->qiov.size, 1, ctx->Cflag);
|
ctx->qiov.size, 1, ctx->Cflag);
|
||||||
|
out:
|
||||||
qemu_io_free(ctx->buf);
|
qemu_io_free(ctx->buf);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
@ -789,7 +790,7 @@ aio_read_done(void *opaque, int ret)
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printf("readv failed: %s\n", strerror(-ret));
|
printf("readv failed: %s\n", strerror(-ret));
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->Pflag) {
|
if (ctx->Pflag) {
|
||||||
|
@ -805,7 +806,7 @@ aio_read_done(void *opaque, int ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->qflag) {
|
if (ctx->qflag) {
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->vflag) {
|
if (ctx->vflag) {
|
||||||
|
@ -816,7 +817,7 @@ aio_read_done(void *opaque, int ret)
|
||||||
t2 = tsub(t2, ctx->t1);
|
t2 = tsub(t2, ctx->t1);
|
||||||
print_report("read", &t2, ctx->offset, ctx->qiov.size,
|
print_report("read", &t2, ctx->offset, ctx->qiov.size,
|
||||||
ctx->qiov.size, 1, ctx->Cflag);
|
ctx->qiov.size, 1, ctx->Cflag);
|
||||||
|
out:
|
||||||
qemu_io_free(ctx->buf);
|
qemu_io_free(ctx->buf);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
@ -865,17 +866,20 @@ aio_read_f(int argc, char **argv)
|
||||||
ctx->vflag = 1;
|
ctx->vflag = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
free(ctx);
|
||||||
return command_usage(&aio_read_cmd);
|
return command_usage(&aio_read_cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind > argc - 2)
|
if (optind > argc - 2) {
|
||||||
|
free(ctx);
|
||||||
return command_usage(&aio_read_cmd);
|
return command_usage(&aio_read_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
ctx->offset = cvtnum(argv[optind]);
|
ctx->offset = cvtnum(argv[optind]);
|
||||||
if (ctx->offset < 0) {
|
if (ctx->offset < 0) {
|
||||||
printf("non-numeric length argument -- %s\n", argv[optind]);
|
printf("non-numeric length argument -- %s\n", argv[optind]);
|
||||||
|
free(ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
optind++;
|
optind++;
|
||||||
|
@ -883,6 +887,7 @@ aio_read_f(int argc, char **argv)
|
||||||
if (ctx->offset & 0x1ff) {
|
if (ctx->offset & 0x1ff) {
|
||||||
printf("offset %lld is not sector aligned\n",
|
printf("offset %lld is not sector aligned\n",
|
||||||
(long long)ctx->offset);
|
(long long)ctx->offset);
|
||||||
|
free(ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,8 +897,11 @@ aio_read_f(int argc, char **argv)
|
||||||
gettimeofday(&ctx->t1, NULL);
|
gettimeofday(&ctx->t1, NULL);
|
||||||
acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
|
acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov,
|
||||||
ctx->qiov.size >> 9, aio_read_done, ctx);
|
ctx->qiov.size >> 9, aio_read_done, ctx);
|
||||||
if (!acb)
|
if (!acb) {
|
||||||
|
free(ctx->buf);
|
||||||
|
free(ctx);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -952,16 +960,20 @@ aio_write_f(int argc, char **argv)
|
||||||
pattern = atoi(optarg);
|
pattern = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
free(ctx);
|
||||||
return command_usage(&aio_write_cmd);
|
return command_usage(&aio_write_cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind > argc - 2)
|
if (optind > argc - 2) {
|
||||||
|
free(ctx);
|
||||||
return command_usage(&aio_write_cmd);
|
return command_usage(&aio_write_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
ctx->offset = cvtnum(argv[optind]);
|
ctx->offset = cvtnum(argv[optind]);
|
||||||
if (ctx->offset < 0) {
|
if (ctx->offset < 0) {
|
||||||
printf("non-numeric length argument -- %s\n", argv[optind]);
|
printf("non-numeric length argument -- %s\n", argv[optind]);
|
||||||
|
free(ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
optind++;
|
optind++;
|
||||||
|
@ -969,6 +981,7 @@ aio_write_f(int argc, char **argv)
|
||||||
if (ctx->offset & 0x1ff) {
|
if (ctx->offset & 0x1ff) {
|
||||||
printf("offset %lld is not sector aligned\n",
|
printf("offset %lld is not sector aligned\n",
|
||||||
(long long)ctx->offset);
|
(long long)ctx->offset);
|
||||||
|
free(ctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,8 +991,11 @@ aio_write_f(int argc, char **argv)
|
||||||
gettimeofday(&ctx->t1, NULL);
|
gettimeofday(&ctx->t1, NULL);
|
||||||
acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
|
acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,
|
||||||
ctx->qiov.size >> 9, aio_write_done, ctx);
|
ctx->qiov.size >> 9, aio_write_done, ctx);
|
||||||
if (!acb)
|
if (!acb) {
|
||||||
|
free(ctx->buf);
|
||||||
|
free(ctx);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue