blob: 61fe66f74e0d86cac1ceac6f0012521c5fb45776 [file] [log] [blame]
/*
* Copyright (c) 2011 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LTP_AIODIO_COMMON_SPARSE
#define LTP_AIODIO_COMMON_SPARSE
/*
* This code tries to create dirty free blocks on
* the HDD so there is a chance that blocks to be allocated
* for a file are filled with something else than zeroes.
*
* The usefulness of this is IMHO questionable.
*/
static void dirty_freeblocks(int size)
{
int fd;
void *p;
int pg;
char *filename = "dirty_freeblocks";
pg = getpagesize();
size = ((size + pg - 1) / pg) * pg;
fd = open(filename, O_CREAT|O_RDWR|O_EXCL, 0600);
if (fd < 0)
tst_brkm(TBROK|TERRNO, cleanup, "failed to open '%s'", filename);
SAFE_FTRUNCATE(cleanup, fd, size);
p = SAFE_MMAP(cleanup, NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
memset(p, 0xaa, size);
msync(p, size, MS_SYNC);
munmap(p, size);
close(fd);
unlink(filename);
}
/*
* Scale value by kilo, mega, or giga.
*/
long long scale_by_kmg(long long value, char scale)
{
switch (scale) {
case 'g':
case 'G':
value *= 1024;
case 'm':
case 'M':
value *= 1024;
case 'k':
case 'K':
value *= 1024;
break;
case '\0':
break;
default:
usage();
break;
}
return value;
}
char *check_zero(char *buf, int size)
{
char *p;
p = buf;
while (size > 0) {
if (*buf != 0) {
fprintf(stderr, "non zero buffer at buf[%d] => 0x%02x,%02x,%02x,%02x\n",
buf - p, (unsigned int)buf[0],
size > 1 ? (unsigned int)buf[1] : 0,
size > 2 ? (unsigned int)buf[2] : 0,
size > 3 ? (unsigned int)buf[3] : 0);
return buf;
}
buf++;
size--;
}
return NULL;
}
/*
* Make sure we read only zeroes,
* either there is a hole in the file,
* or zeroes were actually written by parent.
*/
static void read_sparse(char *filename, int filesize)
{
int fd;
int i, j, r;
char buf[4096];
/*
* Wait for the file to appear.
*/
for (i = 0; i < 10000; i++) {
fd = open(filename, O_RDONLY);
if (fd != -1)
break;
if (debug)
fprintf(stderr, "Child %i waits for '%s' to appear\n",
getpid(), filename);
usleep(100000);
}
if (fd == -1) {
if (debug)
fprintf(stderr, "Child %i failed to open '%s'\n",
getpid(), filename);
exit(10);
}
if (debug)
fprintf(stderr, "Child %i has opened '%s' for reading\n",
getpid(), filename);
for (i = 0; i < 100000000; i++) {
off_t offset = 0;
char *badbuf;
if (debug)
fprintf(stderr, "Child %i loop %i\n", getpid(), i);
lseek(fd, SEEK_SET, 0);
for (j = 0; j < filesize+1; j += sizeof(buf)) {
r = read(fd, buf, sizeof(buf));
if (r > 0) {
if ((badbuf = check_zero(buf, r))) {
fprintf(stderr, "non-zero read at offset %d\n",
offset + badbuf - buf);
exit(10);
}
}
offset += r;
}
}
exit(0);
}
#endif /* LTP_AIODIO_COMMON_SPARSE */