1 /* 2 * Copyright (c) 2011 Cyril Hrubis <chrubis (at) suse.cz> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 #ifndef LTP_AIODIO_COMMON_SPARSE 20 #define LTP_AIODIO_COMMON_SPARSE 21 22 /* 23 * This code tries to create dirty free blocks on 24 * the HDD so there is a chance that blocks to be allocated 25 * for a file are filled with something else than zeroes. 26 * 27 * The usefulness of this is IMHO questionable. 28 */ 29 static void dirty_freeblocks(int size) 30 { 31 int fd; 32 void *p; 33 int pg; 34 char *filename = "dirty_freeblocks"; 35 36 pg = getpagesize(); 37 size = ((size + pg - 1) / pg) * pg; 38 39 fd = open(filename, O_CREAT|O_RDWR|O_EXCL, 0600); 40 41 if (fd < 0) 42 tst_brkm(TBROK|TERRNO, cleanup, "failed to open '%s'", filename); 43 44 SAFE_FTRUNCATE(cleanup, fd, size); 45 46 p = SAFE_MMAP(cleanup, NULL, size, PROT_WRITE|PROT_READ, MAP_SHARED|MAP_FILE, fd, 0); 47 48 memset(p, 0xaa, size); 49 msync(p, size, MS_SYNC); 50 munmap(p, size); 51 close(fd); 52 unlink(filename); 53 } 54 55 /* 56 * Scale value by kilo, mega, or giga. 57 */ 58 long long scale_by_kmg(long long value, char scale) 59 { 60 switch (scale) { 61 case 'g': 62 case 'G': 63 value *= 1024; 64 case 'm': 65 case 'M': 66 value *= 1024; 67 case 'k': 68 case 'K': 69 value *= 1024; 70 break; 71 case '\0': 72 break; 73 default: 74 usage(); 75 break; 76 } 77 return value; 78 } 79 80 char *check_zero(char *buf, int size) 81 { 82 char *p; 83 84 p = buf; 85 86 while (size > 0) { 87 if (*buf != 0) { 88 fprintf(stderr, "non zero buffer at buf[%d] => 0x%02x,%02x,%02x,%02x\n", 89 buf - p, (unsigned int)buf[0], 90 size > 1 ? (unsigned int)buf[1] : 0, 91 size > 2 ? (unsigned int)buf[2] : 0, 92 size > 3 ? (unsigned int)buf[3] : 0); 93 return buf; 94 } 95 buf++; 96 size--; 97 } 98 99 return NULL; 100 } 101 102 /* 103 * Make sure we read only zeroes, 104 * either there is a hole in the file, 105 * or zeroes were actually written by parent. 106 */ 107 static void read_sparse(char *filename, int filesize) 108 { 109 int fd; 110 int i, j, r; 111 char buf[4096]; 112 113 /* 114 * Wait for the file to appear. 115 */ 116 for (i = 0; i < 10000; i++) { 117 fd = open(filename, O_RDONLY); 118 119 if (fd != -1) 120 break; 121 122 if (debug) 123 fprintf(stderr, "Child %i waits for '%s' to appear\n", 124 getpid(), filename); 125 126 usleep(100000); 127 } 128 129 if (fd == -1) { 130 if (debug) 131 fprintf(stderr, "Child %i failed to open '%s'\n", 132 getpid(), filename); 133 exit(10); 134 } 135 136 if (debug) 137 fprintf(stderr, "Child %i has opened '%s' for reading\n", 138 getpid(), filename); 139 140 for (i = 0; i < 100000000; i++) { 141 off_t offset = 0; 142 char *badbuf; 143 144 if (debug) 145 fprintf(stderr, "Child %i loop %i\n", getpid(), i); 146 147 lseek(fd, SEEK_SET, 0); 148 for (j = 0; j < filesize+1; j += sizeof(buf)) { 149 r = read(fd, buf, sizeof(buf)); 150 if (r > 0) { 151 if ((badbuf = check_zero(buf, r))) { 152 fprintf(stderr, "non-zero read at offset %d\n", 153 offset + badbuf - buf); 154 exit(10); 155 } 156 } 157 offset += r; 158 } 159 } 160 161 exit(0); 162 } 163 164 #endif /* LTP_AIODIO_COMMON_SPARSE */ 165