1#!/usr/bin/python 2# -*- coding: utf-8 -*- 3""" 4Auxiliary script used to allocate memory on guests. 5 6@copyright: 2008-2009 Red Hat Inc. 7@author: Jiri Zupka (jzupka@redhat.com) 8""" 9 10 11import os, array, sys, random, copy, tempfile, datetime, math 12 13PAGE_SIZE = 4096 # machine page size 14 15TMPFS_OVERHEAD = 0.0022 # overhead on 1MB of write data 16 17 18class MemFill(object): 19 """ 20 Fills guest memory according to certain patterns. 21 """ 22 def __init__(self, mem, static_value, random_key): 23 """ 24 Constructor of MemFill class. 25 26 @param mem: Amount of test memory in MB. 27 @param random_key: Seed of random series used for fill up memory. 28 @param static_value: Value used to fill all memory. 29 """ 30 if (static_value < 0 or static_value > 255): 31 print ("FAIL: Initialization static value" 32 "can be only in range (0..255)") 33 return 34 35 self.tmpdp = tempfile.mkdtemp() 36 ret_code = os.system("mount -o size=%dM tmpfs %s -t tmpfs" % 37 ((mem+math.ceil(mem*TMPFS_OVERHEAD)), 38 self.tmpdp)) 39 if ret_code != 0: 40 if os.getuid() != 0: 41 print ("FAIL: Unable to mount tmpfs " 42 "(likely cause: you are not root)") 43 else: 44 print "FAIL: Unable to mount tmpfs" 45 else: 46 self.f = tempfile.TemporaryFile(prefix='mem', dir=self.tmpdp) 47 self.allocate_by = 'L' 48 self.npages = ((mem * 1024 * 1024) / PAGE_SIZE) 49 self.random_key = random_key 50 self.static_value = static_value 51 print "PASS: Initialization" 52 53 54 def __del__(self): 55 if os.path.ismount(self.tmpdp): 56 self.f.close() 57 os.system("umount %s" % (self.tmpdp)) 58 59 60 def compare_page(self, original, inmem): 61 """ 62 Compare pages of memory and print the differences found. 63 64 @param original: Data that was expected to be in memory. 65 @param inmem: Data in memory. 66 """ 67 for ip in range(PAGE_SIZE / original.itemsize): 68 if (not original[ip] == inmem[ip]): # find which item is wrong 69 originalp = array.array("B") 70 inmemp = array.array("B") 71 originalp.fromstring(original[ip:ip+1].tostring()) 72 inmemp.fromstring(inmem[ip:ip+1].tostring()) 73 for ib in range(len(originalp)): # find wrong byte in item 74 if not (originalp[ib] == inmemp[ib]): 75 position = (self.f.tell() - PAGE_SIZE + ip * 76 original.itemsize + ib) 77 print ("Mem error on position %d wanted 0x%Lx and is " 78 "0x%Lx" % (position, originalp[ib], inmemp[ib])) 79 80 81 def value_page(self, value): 82 """ 83 Create page filled by value. 84 85 @param value: String we want to fill the page with. 86 @return: return array of bytes size PAGE_SIZE. 87 """ 88 a = array.array("B") 89 for i in range((PAGE_SIZE / a.itemsize)): 90 try: 91 a.append(value) 92 except: 93 print "FAIL: Value can be only in range (0..255)" 94 return a 95 96 97 def random_page(self, seed): 98 """ 99 Create page filled by static random series. 100 101 @param seed: Seed of random series. 102 @return: Static random array series. 103 """ 104 random.seed(seed) 105 a = array.array(self.allocate_by) 106 for i in range(PAGE_SIZE / a.itemsize): 107 a.append(random.randrange(0, sys.maxint)) 108 return a 109 110 111 def value_fill(self, value=None): 112 """ 113 Fill memory page by page, with value generated with value_page. 114 115 @param value: Parameter to be passed to value_page. None to just use 116 what's on the attribute static_value. 117 """ 118 self.f.seek(0) 119 if value is None: 120 value = self.static_value 121 page = self.value_page(value) 122 for pages in range(self.npages): 123 page.tofile(self.f) 124 print "PASS: Mem value fill" 125 126 127 def value_check(self, value=None): 128 """ 129 Check memory to see if data is correct. 130 131 @param value: Parameter to be passed to value_page. None to just use 132 what's on the attribute static_value. 133 @return: if data in memory is correct return PASS 134 else print some wrong data and return FAIL 135 """ 136 self.f.seek(0) 137 e = 2 138 failure = False 139 if value is None: 140 value = self.static_value 141 page = self.value_page(value) 142 for pages in range(self.npages): 143 pf = array.array("B") 144 pf.fromfile(self.f, PAGE_SIZE / pf.itemsize) 145 if not (page == pf): 146 failure = True 147 self.compare_page(page, pf) 148 e = e - 1 149 if e == 0: 150 break 151 if failure: 152 print "FAIL: value verification" 153 else: 154 print "PASS: value verification" 155 156 157 def static_random_fill(self, n_bytes_on_end=PAGE_SIZE): 158 """ 159 Fill memory by page with static random series with added special value 160 on random place in pages. 161 162 @param n_bytes_on_end: how many bytes on the end of page can be changed. 163 @return: PASS. 164 """ 165 self.f.seek(0) 166 page = self.random_page(self.random_key) 167 random.seed(self.random_key) 168 p = copy.copy(page) 169 170 t_start = datetime.datetime.now() 171 for pages in range(self.npages): 172 rand = random.randint(((PAGE_SIZE / page.itemsize) - 1) - 173 (n_bytes_on_end / page.itemsize), 174 (PAGE_SIZE/page.itemsize) - 1) 175 p[rand] = pages 176 p.tofile(self.f) 177 p[rand] = page[rand] 178 179 t_end = datetime.datetime.now() 180 delta = t_end - t_start 181 milisec = delta.microseconds / 1e3 + delta.seconds * 1e3 182 print "PASS: filling duration = %Ld ms" % milisec 183 184 185 def static_random_verify(self, n_bytes_on_end=PAGE_SIZE): 186 """ 187 Check memory to see if it contains correct contents. 188 189 @return: if data in memory is correct return PASS 190 else print some wrong data and return FAIL. 191 """ 192 self.f.seek(0) 193 e = 2 194 page = self.random_page(self.random_key) 195 random.seed(self.random_key) 196 p = copy.copy(page) 197 failure = False 198 for pages in range(self.npages): 199 rand = random.randint(((PAGE_SIZE/page.itemsize) - 1) - 200 (n_bytes_on_end/page.itemsize), 201 (PAGE_SIZE/page.itemsize) - 1) 202 p[rand] = pages 203 pf = array.array(self.allocate_by) 204 pf.fromfile(self.f, PAGE_SIZE / pf.itemsize) 205 if not (p == pf): 206 failure = True 207 self.compare_page(p, pf) 208 e = e - 1 209 if e == 0: 210 break 211 p[rand] = page[rand] 212 if failure: 213 print "FAIL: Random series verification" 214 else: 215 print "PASS: Random series verification" 216 217 218def die(): 219 """ 220 Quit allocator. 221 """ 222 exit(0) 223 224 225def main(): 226 """ 227 Main (infinite) loop of allocator. 228 """ 229 print "PASS: Start" 230 end = False 231 while not end: 232 str = raw_input() 233 exec str 234 235 236if __name__ == "__main__": 237 main() 238