Re: [PATCH] fix unbalanced page refcounting in bio_map_user_iov

Vitaly Mayatskikh
2017-09-22T05:24:10Z

Reproducer (needs SCSI disk):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <malloc.h>
#include <string.h>
#include <scsi/sg.h>

#define NR_IOS 10000
#define NR_IOVECS 8
#define SG_IO 0x2285

int main(int argc, char *argv[])
{
int fd, i, j;
unsigned char *buf, *ptr, cdb[10];
sg_io_hdr_t io_hdr;
sg_iovec_t iovec[NR_IOVECS];

if (argc < 2) {
printf("Run: %s </dev/sdX>\n", argv[0]);
exit(1);
}

buf = ptr = memalign(4096, NR_IOS * NR_IOVECS * 512);
if (!buf) {
printf("can't alloc memory\n");
exit(1);
}

fd = open(argv[1], 0);
if (fd < 0) {
printf("open %s failed: %d (%s)\n", argv[1], errno, strerror(errno));
exit(1);
}

io_hdr.interface_id = 'S';
io_hdr.cmd_len = sizeof(cdb);
io_hdr.cmdp = cdb;
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = 512 * NR_IOVECS;
io_hdr.dxferp = iovec;
io_hdr.iovec_count = NR_IOVECS;

cdb[0] = 0x28; // READ10
cdb[8] = NR_IOVECS; // sectors

for (j = 0; j < NR_IOS; j++, ptr += 512) {
for (i = 0; i < NR_IOVECS; i++) {
iovec[i].iov_base = ptr;
iovec[i].iov_len = 512;
}
if (ioctl(fd, SG_IO, &io_hdr)) {
printf("IOCTL failed: %d (%s)\n", errno, strerror(errno));
exit(1);
}
}

free(buf);
close(fd);
return 0;
}

# free -m
total used free shared buff/cache available
Mem: 3827 46 3601 0 178 3568
Swap: 0 0 0
# ./sgio-leak /dev/sdd
# free -m
total used free shared buff/cache available
Mem: 3827 85 3562 0 178 3529
Swap: 0 0 0
[root@node-A ~]# free -m
total used free shared buff/cache available
Mem: 3827 85 3628 0 113 3561
Swap: 0 0 0
# ./sgio-leak /dev/sdd
# free -m
total used free shared buff/cache available
Mem: 3827 124 3589 0 113 3523
Swap: 0 0 0

--
wbr, Vitaly