1import time, os 2from autotest_lib.client.bin import test, os_dep, utils 3from autotest_lib.client.common_lib import error 4 5 6class btreplay(test.test): 7 version = 1 8 9 # http://brick.kernel.dk/snaps/blktrace-git-latest.tar.gz 10 def setup(self, tarball = 'blktrace-git-latest.tar.gz'): 11 tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir) 12 utils.extract_tarball_to_dir(tarball, self.srcdir) 13 14 self.job.setup_dep(['libaio']) 15 libs = '-L' + self.autodir + '/deps/libaio/lib -laio' 16 cflags = '-I ' + self.autodir + '/deps/libaio/include' 17 var_libs = 'LIBS="' + libs + '"' 18 var_cflags = 'CFLAGS="' + cflags + '"' 19 self.make_flags = var_libs + ' ' + var_cflags 20 21 os.chdir(self.srcdir) 22 23 utils.system('patch -p1 < ../Makefile.patch') 24 utils.system(self.make_flags + ' make') 25 26 27 def initialize(self): 28 self.job.require_gcc() 29 self.ldlib = 'LD_LIBRARY_PATH=%s/deps/libaio/lib'%(self.autodir) 30 self.results = [] 31 32 33 def run_once(self, dev="", devices="", extra_args='', tmpdir=None): 34 # @dev: The device against which the trace will be replayed. 35 # e.g. "sdb" or "md_d1" 36 # @devices: A space-separated list of the underlying devices 37 # which make up dev, e.g. "sdb sdc". You only need to set 38 # devices if dev is an MD, LVM, or similar device; 39 # otherwise leave it as an empty string. 40 41 if not tmpdir: 42 tmpdir = self.tmpdir 43 44 os.chdir(self.srcdir) 45 46 alldevs = "-d /dev/" + dev 47 alldnames = dev 48 for d in devices.split(): 49 alldevs += " -d /dev/" + d 50 alldnames += " " + d 51 52 # convert the trace (assumed to be in this test's base 53 # directory) into btreplay's required format 54 # 55 # TODO: The test currently halts here as there is no trace in the 56 # test's base directory. 57 cmd = "./btreplay/btrecord -d .. -D %s %s" % (tmpdir, dev) 58 self.results.append(utils.system_output(cmd, retain_output=True)) 59 60 # time a replay that omits "thinktime" between requests 61 # (by use of the -N flag) 62 cmd = self.ldlib + " /usr/bin/time ./btreplay/btreplay -d "+\ 63 tmpdir+" -N -W "+dev+" "+extra_args+" 2>&1" 64 self.results.append(utils.system_output(cmd, retain_output=True)) 65 66 # trace a replay that reproduces inter-request delays, and 67 # analyse the trace with btt to determine the average request 68 # completion latency 69 utils.system("./blktrace -D %s %s >/dev/null &" % (tmpdir, alldevs)) 70 cmd = self.ldlib + " ./btreplay/btreplay -d %s -W %s %s" %\ 71 (tmpdir, dev, extra_args) 72 self.results.append(utils.system_output(cmd, retain_output=True)) 73 utils.system("killall -INT blktrace") 74 75 # wait until blktrace is really done 76 slept = 0.0 77 while utils.system("ps -C blktrace > /dev/null", 78 ignore_status=True) == 0: 79 time.sleep(0.1) 80 slept += 0.1 81 if slept > 30.0: 82 utils.system("killall -9 blktrace") 83 raise error.TestError("blktrace failed to exit in 30 seconds") 84 utils.system("./blkparse -q -D %s -d %s/trace.bin -O %s >/dev/null" % 85 (tmpdir, tmpdir, alldnames)) 86 cmd = "./btt/btt -i %s/trace.bin" % tmpdir 87 self.results.append(utils.system_output(cmd, retain_output=True)) 88 89 90 def postprocess(self): 91 for n in range(len(self.results)): 92 if self.results[n].strip() == "==================== All Devices ====================": 93 words = self.results[n-2].split() 94 s = words[1].strip('sytem').split(':') 95 e = words[2].strip('elapsd').split(':') 96 break 97 98 systime = 0.0 99 for n in range(len(s)): 100 i = (len(s)-1) - n 101 systime += float(s[i]) * (60**n) 102 elapsed = 0.0 103 for n in range(len(e)): 104 i = (len(e)-1) - n 105 elapsed += float(e[i]) * (60**n) 106 107 q2c = 0.0 108 for line in self.results: 109 words = line.split() 110 if len(words) < 3: 111 continue 112 if words[0] == 'Q2C': 113 q2c = float(words[2]) 114 break 115 116 self.write_perf_keyval({'time':elapsed, 'systime':systime, 117 'avg_q2c_latency':q2c}) 118