blob: 189bde420f1336382fb0eae34b48e0cf7312967c [file] [log] [blame]
import os, time, re, subprocess, shutil, logging
from autotest_lib.client.bin import utils, test
from autotest_lib.client.common_lib import error
class dma_memtest(test.test):
A test for the memory subsystem against heavy IO and DMA operations,
implemented based on the work of Doug Leford
@author Lucas Meneghel Rodrigues (
@author Rodrigo Sampaio Vaz (
version = 1
def initialize(self):
self.cachedir = os.path.join(self.bindir, 'cache')
self.nfail = 0
def setup(self, tarball_base='linux-2.6.18.tar.bz2', parallel=True):
Downloads a copy of the linux kernel, calculate an estimated size of
the uncompressed tarball, use this value to calculate the number of
copies of the linux kernel that will be uncompressed.
@param tarball_base: Name of the kernel tarball location that will
be looked up on the mirrors.
@param parallel: If we are going to uncompress the copies of the
kernel in parallel or not
if not os.path.isdir(self.cachedir):
self.parallel = parallel
kernel_repo = ''
tarball_url = os.path.join(kernel_repo, tarball_base)
tarball_md5 = '296a6d150d260144639c3664d127d174''Downloading linux kernel tarball')
self.tarball = utils.unmap_url_cache(self.cachedir, tarball_url,
size_tarball = os.path.getsize(self.tarball) / 1024 / 1024
# Estimation of the tarball size after uncompression
compress_ratio = 5
est_size = size_tarball * compress_ratio
self.sim_cps = self.get_sim_cps(est_size)'Source file: %s' % tarball_base)'Megabytes per copy: %s' % size_tarball)'Compress ratio: %s' % compress_ratio)'Estimated size after uncompression: %s' % est_size)'Number of copies: %s' % self.sim_cps)'Parallel: %s' % parallel)
def get_sim_cps(self, est_size):
Calculate the amount of simultaneous copies that can be uncompressed
so that it will make the system swap.
@param est_size: Estimated size of uncompressed linux tarball
mem_str = utils.system_output('grep MemTotal /proc/meminfo')
mem = int('\d+', mem_str).group(0))
mem = int(mem / 1024)
# The general idea here is that we'll make an amount of copies of the
# kernel tree equal to 1.5 times the physical RAM, to make sure the
# system swaps, therefore reading and writing stuff to the disk. The
# DMA reads and writes together with the memory operations that will
# make it more likely to reveal failures in the memory subsystem.
sim_cps = (1.5 * mem) / est_size
if (mem % est_size) >= (est_size / 2):
sim_cps += 1
if (mem / 32) < 1:
sim_cps += 1
return int(sim_cps)
def run_once(self):
Represents a single iteration of the process. Uncompresses a previously
calculated number of copies of the linux kernel, sequentially or in
parallel, and then compares the tree with a base tree, that was
uncompressed on the very beginning.
parallel_procs = []
# This is the reference copy of the linux tarball
# that will be used for subsequent comparisons'Unpacking base copy')
base_dir = os.path.join(self.tmpdir, 'linux.orig')
utils.extract_tarball_to_dir(self.tarball, base_dir)'Unpacking test copies')
for j in range(self.sim_cps):
tmp_dir = 'linux.%s' % j
if self.parallel:
# Start parallel process
tar_cmd = ['tar', 'jxf', self.tarball, '-C', tmp_dir]
logging.debug("Unpacking tarball to %s", tmp_dir)
logging.debug("Unpacking tarball to %s", tmp_dir)
utils.extract_tarball_to_dir(self.tarball, tmp_dir)
# Wait for the subprocess before comparison
if self.parallel:
logging.debug("Wait background processes before proceed")
for proc in parallel_procs:
parallel_procs = []'Comparing test copies with base copy')
for j in range(self.sim_cps):
tmp_dir = 'linux.%s/%s' % (j,
if self.parallel:
diff_cmd = ['diff', '-U3', '-rN', 'linux.orig', tmp_dir]
logging.debug("Comparing linux.orig with %s", tmp_dir)
p = subprocess.Popen(diff_cmd,
logging.debug('Comparing linux.orig with %s', tmp_dir)
utils.system('diff -U3 -rN linux.orig linux.%s' % j)
except error.CmdError, e:
self.nfail += 1
logging.error('Error comparing trees: %s', e)
for proc in parallel_procs:
out_buf =
out_buf +=
if out_buf != "":
self.nfail += 1
logging.error('Error comparing trees: %s', out_buf)
# Clean up for the next iteration
parallel_procs = []'Cleaning up')
for j in range(self.sim_cps):
tmp_dir = 'linux.%s' % j
def cleanup(self):
if self.nfail != 0:
raise error.TestError('DMA memory test failed.')
else:'DMA memory test passed.')