import time, os from autotest_lib.client.bin import test, os_dep, utils from autotest_lib.client.common_lib import error class btreplay(test.test): version = 1 # http://brick.kernel.dk/snaps/blktrace-git-latest.tar.gz def setup(self, tarball = 'blktrace-git-latest.tar.gz'): tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir) utils.extract_tarball_to_dir(tarball, self.srcdir) self.job.setup_dep(['libaio']) libs = '-L' + self.autodir + '/deps/libaio/lib -laio' cflags = '-I ' + self.autodir + '/deps/libaio/include' var_libs = 'LIBS="' + libs + '"' var_cflags = 'CFLAGS="' + cflags + '"' self.make_flags = var_libs + ' ' + var_cflags os.chdir(self.srcdir) utils.system('patch -p1 < ../Makefile.patch') utils.system(self.make_flags + ' make') def initialize(self): self.job.require_gcc() self.ldlib = 'LD_LIBRARY_PATH=%s/deps/libaio/lib'%(self.autodir) self.results = [] def run_once(self, dev="", devices="", extra_args='', tmpdir=None): # @dev: The device against which the trace will be replayed. # e.g. "sdb" or "md_d1" # @devices: A space-separated list of the underlying devices # which make up dev, e.g. "sdb sdc". You only need to set # devices if dev is an MD, LVM, or similar device; # otherwise leave it as an empty string. if not tmpdir: tmpdir = self.tmpdir os.chdir(self.srcdir) alldevs = "-d /dev/" + dev alldnames = dev for d in devices.split(): alldevs += " -d /dev/" + d alldnames += " " + d # convert the trace (assumed to be in this test's base # directory) into btreplay's required format # # TODO: The test currently halts here as there is no trace in the # test's base directory. cmd = "./btreplay/btrecord -d .. -D %s %s" % (tmpdir, dev) self.results.append(utils.system_output(cmd, retain_output=True)) # time a replay that omits "thinktime" between requests # (by use of the -N flag) cmd = self.ldlib + " /usr/bin/time ./btreplay/btreplay -d "+\ tmpdir+" -N -W "+dev+" "+extra_args+" 2>&1" self.results.append(utils.system_output(cmd, retain_output=True)) # trace a replay that reproduces inter-request delays, and # analyse the trace with btt to determine the average request # completion latency utils.system("./blktrace -D %s %s >/dev/null &" % (tmpdir, alldevs)) cmd = self.ldlib + " ./btreplay/btreplay -d %s -W %s %s" %\ (tmpdir, dev, extra_args) self.results.append(utils.system_output(cmd, retain_output=True)) utils.system("killall -INT blktrace") # wait until blktrace is really done slept = 0.0 while utils.system("ps -C blktrace > /dev/null", ignore_status=True) == 0: time.sleep(0.1) slept += 0.1 if slept > 30.0: utils.system("killall -9 blktrace") raise error.TestError("blktrace failed to exit in 30 seconds") utils.system("./blkparse -q -D %s -d %s/trace.bin -O %s >/dev/null" % (tmpdir, tmpdir, alldnames)) cmd = "./btt/btt -i %s/trace.bin" % tmpdir self.results.append(utils.system_output(cmd, retain_output=True)) def postprocess(self): for n in range(len(self.results)): if self.results[n].strip() == "==================== All Devices ====================": words = self.results[n-2].split() s = words[1].strip('sytem').split(':') e = words[2].strip('elapsd').split(':') break systime = 0.0 for n in range(len(s)): i = (len(s)-1) - n systime += float(s[i]) * (60**n) elapsed = 0.0 for n in range(len(e)): i = (len(e)-1) - n elapsed += float(e[i]) * (60**n) q2c = 0.0 for line in self.results: words = line.split() if len(words) < 3: continue if words[0] == 'Q2C': q2c = float(words[2]) break self.write_perf_keyval({'time':elapsed, 'systime':systime, 'avg_q2c_latency':q2c})