1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging 6import traceback 7from autotest_lib.client.common_lib import error 8from autotest_lib.server import test 9 10class platform_SyncCrash(test.test): 11 """Tests syncing to the file system before a crash. 12 13 This test works in conjunction with testsync (found in 14 punybench) to test various forms of sync. Testsync runs 15 on the client to create a file, fill it with data, sync 16 that data and crash the system. The server side (this 17 code), waits for the client to restart and then invokes 18 testsync to verify the data did sync. 19 20 Testsync has different phases for testing sync 21 writer - syncs a file using fsync 22 mapper - syncs a memory mapped file using msync 23 verifier - verifies that content of the file 24 25 The tests are run on both the stateful partition 26 and ecryptfs mounted on a directory in the stateful 27 partition. 28 """ 29 version = 1 30 _STATEFUL_DIR = '/usr/local/CrashDir/' 31 _ECRYPT_DIR = '/usr/local/ecryptfs_tst/' 32 _ECRYPT_MOUNT_POINT = '/usr/local/ecryptfs_mnt/' 33 _ECRYPT_TEST_DIR = '%s/CrashDir/' % _ECRYPT_MOUNT_POINT 34 _FILE = 'xyzzy' 35 _Testsync = '/usr/local/opt/punybench/bin/testsync' 36 37 38 def _run(self, cmd): 39 """Run the given command and log results 40 41 @param cmd: command to be run 42 """ 43 result = self.client.run(cmd) 44 if result.exit_status != 0: 45 logging.error('%s: %s', cmd, result.stdout) 46 else: 47 logging.info('%s', cmd) 48 49 50 def _testsync_crash(self, args): 51 """Run testsync on the client 52 53 Since testsync forces a crash of the system, the code 54 waits for the reboot. 55 56 @param args: arguments to pass testsync 57 """ 58 logging.info('Crash: %s', self.client.hostname) 59 try: 60 cmd = '%s %s' % (self._Testsync, args) 61 logging.info('Crash: %s', cmd) 62 self.client.reboot(reboot_cmd=cmd) 63 except error.AutoservRebootError as e: 64 raise error.TestFail('%s.\nTest failed with error %s' % ( 65 traceback.format_exc(), str(e))) 66 67 68 def _testsync_verify(self, args): 69 """Verify the results from previous testsync 70 71 @param args: arguments to pass to testsync 72 """ 73 cmd = '%s %s -p verifier' % (self._Testsync, args) 74 result = self.client.run(cmd) 75 if result.exit_status != 0: 76 logging.error('%s: %s', cmd, result.stdout) 77 78 79 def _ecrypt_setup(self): 80 """Setup an eCrypt File System and mount it 81 """ 82 edir = self._ECRYPT_DIR 83 mnt = self._ECRYPT_MOUNT_POINT 84 options = ('-o' 85 ' key=passphrase:passphrase_passwd=secret' 86 ',ecryptfs_cipher=aes' 87 ',ecryptfs_key_bytes=32' 88 ',no_sig_cache' 89 ',ecryptfs_passthrough=no' 90 ',ecryptfs_enable_filename_crypto=no') 91 self._run('mkdir -p %s %s' % (edir, mnt)) 92 self._run('mount -t ecryptfs %s %s %s' % 93 (options, edir, mnt)) 94 95 96 def _ecrypt_teardown(self): 97 """Teardown the eCrypt File System 98 """ 99 edir = self._ECRYPT_DIR 100 mnt = self._ECRYPT_MOUNT_POINT 101 self._run('umount %s' % edir) 102 self._run('rm -R %s %s' % (edir, mnt)) 103 104 105 def _sync_stateful(self, dir, phase): 106 """Crash the stateful file system while changing it 107 108 @param dir - directory where test files are created 109 @param phase - which phase of testsync to invoke 110 """ 111 size = 0x1000 112 file = dir + self._FILE 113 self._run('mkdir -p %s' % dir) 114 self._testsync_crash('-f %s -z %s -p %s' % (file, size, phase)) 115 self._testsync_verify('-f %s -z %s' % (file, size)) 116 self._run('rm -r %s' % dir) 117 118 119 def _sync_ecryptfs(self, dir, phase): 120 """Crash an ecryptfs file system right after a sync 121 122 @param edir - directory used for the encrypted file system 123 @param mnt - mount point for the encrypted file system 124 @param dir - directory where test files are created 125 @param phase - which phase of testsync to invoke 126 """ 127 size = 0x1000 128 file = dir + self._FILE 129 self._ecrypt_setup() 130 self._run('mkdir -p %s' % dir) 131 self._testsync_crash('-f %s -z %s -p %s' % (file, size, phase)) 132 self._ecrypt_setup() 133 self._testsync_verify('-f %s -z %s' % (file, size)) 134 self._run('rm -r %s' % dir) 135 self._ecrypt_teardown() 136 137 138 def run_once(self, host=None): 139 """run_once runs the test. 140 141 1. Runs a crash test on stateful partition 142 2. Create an ecryptfs volume and run the same 143 crash test 144 145 @param host - the host machine running the test 146 """ 147 self.client = host 148 149 self._sync_stateful(self._STATEFUL_DIR, 'writer') 150 self._sync_stateful(self._STATEFUL_DIR, 'mapper') 151 152 self._sync_ecryptfs(self._ECRYPT_TEST_DIR, 'writer') 153 self._sync_ecryptfs(self._ECRYPT_TEST_DIR, 'mapper') 154