2 # -*- coding: utf-8 -*-
4 Auxiliary script used to allocate memory on guests.
6 @copyright: 2008-2009 Red Hat Inc.
7 @author: Jiri Zupka (jzupka@redhat.com)
11 import os
, array
, sys
, random
, copy
, tempfile
, datetime
, math
13 PAGE_SIZE
= 4096 # machine page size
15 TMPFS_OVERHEAD
= 0.0022 # overhead on 1MB of write data
18 class MemFill(object):
20 Fills guest memory according to certain patterns.
22 def __init__(self
, mem
, static_value
, random_key
):
24 Constructor of MemFill class.
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.
30 if (static_value
< 0 or static_value
> 255):
31 print ("FAIL: Initialization static value"
32 "can be only in range (0..255)")
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
)),
41 print ("FAIL: Unable to mount tmpfs "
42 "(likely cause: you are not root)")
44 print "FAIL: Unable to mount tmpfs"
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"
55 if os
.path
.ismount(self
.tmpdp
):
57 os
.system("umount %s" % (self
.tmpdp
))
60 def compare_page(self
, original
, inmem
):
62 Compare pages of memory and print the differences found.
64 @param original: Data that was expected to be in memory.
65 @param inmem: Data in memory.
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
]))
81 def value_page(self
, value
):
83 Create page filled by value.
85 @param value: String we want to fill the page with.
86 @return: return array of bytes size PAGE_SIZE.
89 for i
in range((PAGE_SIZE
/ a
.itemsize
)):
93 print "FAIL: Value can be only in range (0..255)"
97 def random_page(self
, seed
):
99 Create page filled by static random series.
101 @param seed: Seed of random series.
102 @return: Static random array series.
105 a
= array
.array(self
.allocate_by
)
106 for i
in range(PAGE_SIZE
/ a
.itemsize
):
107 a
.append(random
.randrange(0, sys
.maxint
))
111 def value_fill(self
, value
=None):
113 Fill memory page by page, with value generated with value_page.
115 @param value: Parameter to be passed to value_page. None to just use
116 what's on the attribute static_value.
120 value
= self
.static_value
121 page
= self
.value_page(value
)
122 for pages
in range(self
.npages
):
124 print "PASS: Mem value fill"
127 def value_check(self
, value
=None):
129 Check memory to see if data is correct.
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
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
)
147 self
.compare_page(page
, pf
)
152 print "FAIL: value verification"
154 print "PASS: value verification"
157 def static_random_fill(self
, n_bytes_on_end
=PAGE_SIZE
):
159 Fill memory by page with static random series with added special value
160 on random place in pages.
162 @param n_bytes_on_end: how many bytes on the end of page can be changed.
166 page
= self
.random_page(self
.random_key
)
167 random
.seed(self
.random_key
)
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)
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
185 def static_random_verify(self
, n_bytes_on_end
=PAGE_SIZE
):
187 Check memory to see if it contains correct contents.
189 @return: if data in memory is correct return PASS
190 else print some wrong data and return FAIL.
194 page
= self
.random_page(self
.random_key
)
195 random
.seed(self
.random_key
)
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)
203 pf
= array
.array(self
.allocate_by
)
204 pf
.fromfile(self
.f
, PAGE_SIZE
/ pf
.itemsize
)
207 self
.compare_page(p
, pf
)
213 print "FAIL: Random series verification"
215 print "PASS: Random series verification"
227 Main (infinite) loop of allocator.
236 if __name__
== "__main__":