Commit 7d8abfcb50a33aed369bbd267852cf04009c49e9
Committed by
Anthony Liguori
1 parent
9c4bab26
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>
Showing
1 changed file
with
38 additions
and
22 deletions
qemu-io.c
... | ... | @@ -358,7 +358,7 @@ read_f(int argc, char **argv) |
358 | 358 | |
359 | 359 | if (cnt < 0) { |
360 | 360 | printf("read failed: %s\n", strerror(-cnt)); |
361 | - return 0; | |
361 | + goto out; | |
362 | 362 | } |
363 | 363 | |
364 | 364 | if (Pflag) { |
... | ... | @@ -373,7 +373,7 @@ read_f(int argc, char **argv) |
373 | 373 | } |
374 | 374 | |
375 | 375 | if (qflag) |
376 | - return 0; | |
376 | + goto out; | |
377 | 377 | |
378 | 378 | if (vflag) |
379 | 379 | dump_buffer(buf, offset, count); |
... | ... | @@ -382,6 +382,7 @@ read_f(int argc, char **argv) |
382 | 382 | t2 = tsub(t2, t1); |
383 | 383 | print_report("read", &t2, offset, count, total, cnt, Cflag); |
384 | 384 | |
385 | +out: | |
385 | 386 | qemu_io_free(buf); |
386 | 387 | |
387 | 388 | return 0; |
... | ... | @@ -480,7 +481,7 @@ readv_f(int argc, char **argv) |
480 | 481 | |
481 | 482 | if (cnt < 0) { |
482 | 483 | printf("readv failed: %s\n", strerror(-cnt)); |
483 | - return 0; | |
484 | + goto out; | |
484 | 485 | } |
485 | 486 | |
486 | 487 | if (Pflag) { |
... | ... | @@ -495,7 +496,7 @@ readv_f(int argc, char **argv) |
495 | 496 | } |
496 | 497 | |
497 | 498 | if (qflag) |
498 | - return 0; | |
499 | + goto out; | |
499 | 500 | |
500 | 501 | if (vflag) |
501 | 502 | dump_buffer(buf, offset, qiov.size); |
... | ... | @@ -504,8 +505,8 @@ readv_f(int argc, char **argv) |
504 | 505 | t2 = tsub(t2, t1); |
505 | 506 | print_report("read", &t2, offset, qiov.size, total, cnt, Cflag); |
506 | 507 | |
508 | +out: | |
507 | 509 | qemu_io_free(buf); |
508 | - | |
509 | 510 | return 0; |
510 | 511 | } |
511 | 512 | |
... | ... | @@ -613,16 +614,17 @@ write_f(int argc, char **argv) |
613 | 614 | |
614 | 615 | if (cnt < 0) { |
615 | 616 | printf("write failed: %s\n", strerror(-cnt)); |
616 | - return 0; | |
617 | + goto out; | |
617 | 618 | } |
618 | 619 | |
619 | 620 | if (qflag) |
620 | - return 0; | |
621 | + goto out; | |
621 | 622 | |
622 | 623 | /* Finally, report back -- -C gives a parsable format */ |
623 | 624 | t2 = tsub(t2, t1); |
624 | 625 | print_report("wrote", &t2, offset, count, total, cnt, Cflag); |
625 | 626 | |
627 | +out: | |
626 | 628 | qemu_io_free(buf); |
627 | 629 | |
628 | 630 | return 0; |
... | ... | @@ -713,18 +715,17 @@ writev_f(int argc, char **argv) |
713 | 715 | |
714 | 716 | if (cnt < 0) { |
715 | 717 | printf("writev failed: %s\n", strerror(-cnt)); |
716 | - return 0; | |
718 | + goto out; | |
717 | 719 | } |
718 | 720 | |
719 | 721 | if (qflag) |
720 | - return 0; | |
722 | + goto out; | |
721 | 723 | |
722 | 724 | /* Finally, report back -- -C gives a parsable format */ |
723 | 725 | t2 = tsub(t2, t1); |
724 | 726 | print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag); |
725 | - | |
727 | +out: | |
726 | 728 | qemu_io_free(buf); |
727 | - | |
728 | 729 | return 0; |
729 | 730 | } |
730 | 731 | |
... | ... | @@ -761,18 +762,18 @@ aio_write_done(void *opaque, int ret) |
761 | 762 | |
762 | 763 | if (ret < 0) { |
763 | 764 | printf("aio_write failed: %s\n", strerror(-ret)); |
764 | - return; | |
765 | + goto out; | |
765 | 766 | } |
766 | 767 | |
767 | 768 | if (ctx->qflag) { |
768 | - return; | |
769 | + goto out; | |
769 | 770 | } |
770 | 771 | |
771 | 772 | /* Finally, report back -- -C gives a parsable format */ |
772 | 773 | t2 = tsub(t2, ctx->t1); |
773 | 774 | print_report("wrote", &t2, ctx->offset, ctx->qiov.size, |
774 | 775 | ctx->qiov.size, 1, ctx->Cflag); |
775 | - | |
776 | +out: | |
776 | 777 | qemu_io_free(ctx->buf); |
777 | 778 | free(ctx); |
778 | 779 | } |
... | ... | @@ -789,7 +790,7 @@ aio_read_done(void *opaque, int ret) |
789 | 790 | |
790 | 791 | if (ret < 0) { |
791 | 792 | printf("readv failed: %s\n", strerror(-ret)); |
792 | - return; | |
793 | + goto out; | |
793 | 794 | } |
794 | 795 | |
795 | 796 | if (ctx->Pflag) { |
... | ... | @@ -805,7 +806,7 @@ aio_read_done(void *opaque, int ret) |
805 | 806 | } |
806 | 807 | |
807 | 808 | if (ctx->qflag) { |
808 | - return; | |
809 | + goto out; | |
809 | 810 | } |
810 | 811 | |
811 | 812 | if (ctx->vflag) { |
... | ... | @@ -816,7 +817,7 @@ aio_read_done(void *opaque, int ret) |
816 | 817 | t2 = tsub(t2, ctx->t1); |
817 | 818 | print_report("read", &t2, ctx->offset, ctx->qiov.size, |
818 | 819 | ctx->qiov.size, 1, ctx->Cflag); |
819 | - | |
820 | +out: | |
820 | 821 | qemu_io_free(ctx->buf); |
821 | 822 | free(ctx); |
822 | 823 | } |
... | ... | @@ -865,17 +866,20 @@ aio_read_f(int argc, char **argv) |
865 | 866 | ctx->vflag = 1; |
866 | 867 | break; |
867 | 868 | default: |
869 | + free(ctx); | |
868 | 870 | return command_usage(&aio_read_cmd); |
869 | 871 | } |
870 | 872 | } |
871 | 873 | |
872 | - if (optind > argc - 2) | |
874 | + if (optind > argc - 2) { | |
875 | + free(ctx); | |
873 | 876 | return command_usage(&aio_read_cmd); |
874 | - | |
877 | + } | |
875 | 878 | |
876 | 879 | ctx->offset = cvtnum(argv[optind]); |
877 | 880 | if (ctx->offset < 0) { |
878 | 881 | printf("non-numeric length argument -- %s\n", argv[optind]); |
882 | + free(ctx); | |
879 | 883 | return 0; |
880 | 884 | } |
881 | 885 | optind++; |
... | ... | @@ -883,6 +887,7 @@ aio_read_f(int argc, char **argv) |
883 | 887 | if (ctx->offset & 0x1ff) { |
884 | 888 | printf("offset %lld is not sector aligned\n", |
885 | 889 | (long long)ctx->offset); |
890 | + free(ctx); | |
886 | 891 | return 0; |
887 | 892 | } |
888 | 893 | |
... | ... | @@ -892,8 +897,11 @@ aio_read_f(int argc, char **argv) |
892 | 897 | gettimeofday(&ctx->t1, NULL); |
893 | 898 | acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, |
894 | 899 | ctx->qiov.size >> 9, aio_read_done, ctx); |
895 | - if (!acb) | |
900 | + if (!acb) { | |
901 | + free(ctx->buf); | |
902 | + free(ctx); | |
896 | 903 | return -EIO; |
904 | + } | |
897 | 905 | |
898 | 906 | return 0; |
899 | 907 | } |
... | ... | @@ -952,16 +960,20 @@ aio_write_f(int argc, char **argv) |
952 | 960 | pattern = atoi(optarg); |
953 | 961 | break; |
954 | 962 | default: |
963 | + free(ctx); | |
955 | 964 | return command_usage(&aio_write_cmd); |
956 | 965 | } |
957 | 966 | } |
958 | 967 | |
959 | - if (optind > argc - 2) | |
968 | + if (optind > argc - 2) { | |
969 | + free(ctx); | |
960 | 970 | return command_usage(&aio_write_cmd); |
971 | + } | |
961 | 972 | |
962 | 973 | ctx->offset = cvtnum(argv[optind]); |
963 | 974 | if (ctx->offset < 0) { |
964 | 975 | printf("non-numeric length argument -- %s\n", argv[optind]); |
976 | + free(ctx); | |
965 | 977 | return 0; |
966 | 978 | } |
967 | 979 | optind++; |
... | ... | @@ -969,6 +981,7 @@ aio_write_f(int argc, char **argv) |
969 | 981 | if (ctx->offset & 0x1ff) { |
970 | 982 | printf("offset %lld is not sector aligned\n", |
971 | 983 | (long long)ctx->offset); |
984 | + free(ctx); | |
972 | 985 | return 0; |
973 | 986 | } |
974 | 987 | |
... | ... | @@ -978,8 +991,11 @@ aio_write_f(int argc, char **argv) |
978 | 991 | gettimeofday(&ctx->t1, NULL); |
979 | 992 | acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov, |
980 | 993 | ctx->qiov.size >> 9, aio_write_done, ctx); |
981 | - if (!acb) | |
994 | + if (!acb) { | |
995 | + free(ctx->buf); | |
996 | + free(ctx); | |
982 | 997 | return -EIO; |
998 | + } | |
983 | 999 | |
984 | 1000 | return 0; |
985 | 1001 | } | ... | ... |