Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- # Simulate a specific write pattern that triggers data corruption on OCFS2 volume.
- #
- # Usage: /path/to/ocfs2_fallocate_bug_plain_write.py [MAX_TIME_SECONDS]
- #
- # How it works:
- # 1. Opens the file for appending
- # 2. Write N random bytes, where N is a random integer in range [1..256]
- # 3. With 50% probability, wait M centiseconds (=0.01 of a second), where M is in range [1..100]
- # 4. If the time elapsed since step 1 is less than MAX_TIME_SECONDS, repeat from step 2
- #
- # Default MAX_TIME_SECONDS is 20
- #
- # How to use:
- # * Mount the same shared OCFS2 volume on two hosts in the cluster
- # * On first host, change current directory to the directory where the OCFS2 volume is mounted
- # * Run this script, notice the MD5 hash in its output
- # * Calculate MD5 hash of "output.bin" file. It should match the one from the script output
- # * Calculate MD5 hash of the same file from the other host
- # If data on disk is corrupted, the hashes calculated on two hosts will differ.
- # The reason is that the cache on the first host contains correct data, so the hash is correct,
- # while the second host has no cached data for this file,
- # so it reads the corrupted data directly from the block device.
- import os, hashlib, random, time, sys
- FILE = 'output.bin' # file name to write
- MAX_CHUNKS = 100000
- TIME_LIMIT_SECONDS = 20
- FALLOC_FL_KEEP_SIZE = 1
- FALLOC_FL_PUNCH_HOLE = 2
- if os.path.exists(FILE):
- os.unlink(FILE)
- hash_sum = hashlib.md5()
- written = 0
- time_start = time.time()
- time_end = time_start
- if len(sys.argv) > 1:
- TIME_LIMIT_SECONDS = float(sys.argv[1])
- last_progress = ''
- with open(FILE, 'ab') as fd:
- fileno = fd.fileno()
- for chunk_idx in range(MAX_CHUNKS):
- chunk_size = random.randint(1, 256)
- with open('/dev/urandom', 'rb') as fd:
- chunk = fd.read(chunk_size)
- hash_sum.update(chunk)
- pos = os.lseek(fileno, 0, 1)
- os.lseek(fileno, pos, 0)
- written += os.write(fileno, chunk)
- if last_progress:
- print('\015' * len(last_progress), end='', file=sys.stderr)
- last_progress = '{:8d}/{}'.format(chunk_idx + 1, MAX_CHUNKS)
- print(last_progress, end='', file=sys.stderr)
- time_end = time.time()
- if time_end - time_start >= TIME_LIMIT_SECONDS:
- break
- delay = random.randint(1, 200)
- if delay <= 100:
- time.sleep(delay / 100)
- if last_progress:
- print('\015' * len(last_progress), end='', file=sys.stderr)
- print("Wrote {} bytes, {:.3f} seconds elapsed, MD5 = {}".format(written, time_end - time_start, hash_sum.hexdigest()))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement