28 timestr = time.strftime(
"%Y%m%d-%H%M%S")
29 log_filename =
"hole_creation_" + timestr +
".log" 31 logger = logging.getLogger()
32 logger.setLevel(logging.DEBUG)
34 fh = logging.FileHandler(log_filename)
35 fh.setLevel(logging.DEBUG)
37 ch = logging.StreamHandler()
38 ch.setLevel(logging.DEBUG)
39 fformatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s')
40 cformatter = logging.Formatter(
'%(levelname)s : %(message)s')
41 fh.setFormatter(fformatter)
42 ch.setFormatter(cformatter)
46 logger.info(
"***** Script Started *****")
48 parser = argparse.ArgumentParser(description=
"Basic Arguments to run the script")
49 parser.add_argument(
'-rn', action=
'store_true', default=
False, dest=
'random', help=
'For inducing error at Random place')
50 parser.add_argument(
'-e', action=
'store', default=0, type=int, dest=
'noOfErr',
51 help=
'How Many number of error do you want to induce in Metadata')
52 parser.add_argument(
'-rt', action=
'store', dest=
'Record_Type',
53 help=
'Record Type For inducing error at perticular record like BE_BTREE, BE_EMAP, CAS_CTG etc')
54 parser.add_argument(
'-m', action=
'store', dest=
'mfile', help=
'Metadata Path')
55 parser.add_argument(
'-v', action=
'store_true', default=
False, dest=
'verify',
56 help=
'Read full Metadata and Print all the Records entries counts')
57 parser.add_argument(
'-a', action=
'store_true', default=
False, dest=
'allErr',
58 help=
'Induce Error in All Record at Random place')
59 parser.add_argument(
'-gmd', action=
'store_true', default=
False, dest=
'allGMD',
60 help=
'Induce Error in All GMD type of Record at Random place')
61 parser.add_argument(
'-dmd', action=
'store_true', default=
False, dest=
'allDMD',
62 help=
'Induce Error in All DMD type of Record at Random place')
63 parser.add_argument(
'-512k', action=
'store_true', default=
False, dest=
'err512k',
64 help=
'Induce 512K bytes error in Metadata')
65 parser.add_argument(
'-huge', action=
'store_true', default=
False, dest=
'hugeCorruption',
66 help=
'Induce Huge amount of corruption in Metadata')
67 parser.add_argument(
'-seed', action=
'store', default=0, type=float, dest=
'seed',
68 help=
'Seed is used to initialize the "random" library: to initialize the random generation')
69 parser.add_argument(
'-corrupt_emap', action=
'store', dest=
'corrupt_emap', help=
'Induce Error in Emap specified by Cob Id')
70 parser.add_argument(
'-list_emap', action=
'store_true', default=
False, dest=
'list_emap',
71 help=
'Display all Emap keys with device id')
72 parser.add_argument(
'-parse_size', action=
'store', dest=
'parse_size', type=int,
73 help=
'Limit for metadata parsing size in bytes for list_emap and verify option')
74 parser.add_argument(
'-offset', action=
'store', default=0, type=int, dest=
'seek_offset',
75 help=
'Starting offset of metadata file in multiple of 8 bytes')
77 args = parser.parse_args()
79 results = parser.parse_args()
80 logger.info(
'Induce Random Error = {!r}'.
format(args.random))
81 logger.info(
'Number of Error induce = {!r}'.
format(args.noOfErr))
82 logger.info(
'Record Type = {!r}'.
format(args.Record_Type))
83 logger.info(
'Metadata file path = {!r}'.
format(args.mfile))
84 logger.info(
'Verify Record entries = {!r}'.
format(args.verify))
85 logger.info(
'Induce Error in All Record = {!r}'.
format(args.allErr))
86 logger.info(
'Induce Error in GMD Record = {!r}'.
format(args.allGMD))
87 logger.info(
'Induce Error in DMD Record = {!r}'.
format(args.allDMD))
88 logger.info(
'Induce 512k errors = {!r}'.
format(args.err512k))
89 logger.info(
'Induce huge errors = {!r}'.
format(args.hugeCorruption))
90 logger.info(
'Seed for random number = {!r}'.
format(args.seed))
91 logger.info(
'Induce Error in emap by Cob Id = {!r}'.
format(args.corrupt_emap))
92 logger.info(
'List all Emap Keys and Records = {!r}'.
format(args.list_emap))
93 logger.info(
'Limit for parsing size in bytes = {!r}'.
format(args.parse_size))
94 logger.info(
'Metadata seek offset in bytes multiple of 8 bytes = {!r}'.
format(args.seek_offset))
97 recordType = args.Record_Type
98 noOfErr = args.noOfErr
102 logger.info(
"Seed used: {}".
format(seed))
105 logger.info(
"Seed used: {}".
format(seed))
109 if not os.walk(filename):
110 logger.error(
'Failed: The path specified does not exist or Missing file path')
114 header = b
'33011ca5e511de77' 116 footer = b
'33f007e7f007e777' 118 typeDict = {b
'01':
'RPC_PACKET', b
'02':
'RPC_ITEM', b
'03':
'BE_BTREE', b
'04':
'BE_BNODE', b
'05':
'BE_EMAP_KEY',
119 b
'06':
'BE_EMAP_REC',
120 b
'07':
'BE_EMAP', b
'08':
'BE_LIST', b
'09':
'BE_SEG_HDR', b
'0a':
'BALLOC', b
'0b':
'ADDB2_FRAME_HEADER',
121 b
'0c':
'STOB_AD_0TYPE_REC',
122 b
'0d':
'STOB_AD_DOMAIN', b
'0e':
'COB_DOMAIN', b
'0f':
'COB_NSREC', b
'10':
'BALLOC_GROUP_DESC', b
'11':
'EXT',
124 b
'13':
'POOLNODE', b
'14':
'POOLDEV', b
'15':
'POOL_SPARE_USAGE', b
'16':
'CAS_STATE', b
'17':
'CAS_CTG',
125 b
'22':
'WRONG_ENTRY', b
'44':
'WRONG_ENTRY'}
127 recordDict = {
'BE_BTREE': [],
'BE_BNODE': [],
'BE_EMAP_KEY': [],
'BE_EMAP_REC': [],
'BE_EMAP': [],
'BE_LIST': [],
128 'BE_SEG_HDR': [],
'BALLOC': [],
129 'STOB_AD_0TYPE_REC': [],
'STOB_AD_DOMAIN': [],
'COB_DOMAIN': [],
'COB_NSREC': [],
'BALLOC_GROUP_DESC': [],
130 'EXT': [],
'POOLNODE': [],
131 'POOLDEV': [],
'POOL_SPARE_USAGE': [],
'CAS_STATE': [],
'CAS_CTG': [],
'EXTRA': []}
133 sizeDict = {
'BE_BTREE': [],
'BE_BNODE': [],
'BE_EMAP_KEY': [],
'BE_EMAP_REC': [],
'BE_EMAP': [],
'BE_LIST': [],
134 'BE_SEG_HDR': [],
'BALLOC': [],
135 'STOB_AD_0TYPE_REC': [],
'STOB_AD_DOMAIN': [],
'COB_DOMAIN': [],
'COB_NSREC': [],
'BALLOC_GROUP_DESC': [],
136 'EXT': [],
'POOLNODE': [],
137 'POOLDEV': [],
'POOL_SPARE_USAGE': [],
'CAS_STATE': [],
'CAS_CTG': [],
'EXTRA': []}
139 DMDList = [
'BE_BNODE',
'BE_EMAP_KEY',
'BE_EMAP_REC',
'COB_NSREC',
'BALLOC_GROUP_DESC']
140 GMDList = [
'BE_BTREE',
'BE_EMAP',
'BE_LIST',
'BE_SEG_HDR',
'BALLOC',
'STOB_AD_0TYPE_REC',
'STOB_AD_DOMAIN',
141 'COB_DOMAIN',
'CAS_STATE',
'CAS_CTG']
143 btreeType = {b
'01':
'M0_BBT_INVALID', b
'02':
'M0_BBT_BALLOC_GROUP_EXTENTS', b
'03':
'M0_BBT_BALLOC_GROUP_DESC', b
'04':
'M0_BBT_EMAP_EM_MAPPING',
144 b
'05':
'M0_BBT_CAS_CTG', b
'06':
'M0_BBT_COB_NAMESPACE', b
'07':
'M0_BBT_COB_OBJECT_INDEX', b
'08':
'M0_BBT_COB_FILEATTR_BASIC',
145 b
'09':
'M0_BBT_COB_FILEATTR_EA', b
'0a':
'M0_BBT_COB_FILEATTR_OMG', b
'0b':
'M0_BBT_CONFDB', b
'0c':
'M0_BBT_UT_KV_OPS', b
'0d':
'M0_BBT_NR'}
150 if record
in recordDict.keys():
151 recordDict[record].append(i)
152 sizeDict[record].append(size)
153 if record ==
"BE_BNODE":
155 btNumActiveKey = i + 56
156 BeBnodeTypeKeys[i] = [bliType, btNumActiveKey]
158 recordDict[
'EXTRA'].append(i)
159 sizeDict[
'EXTRA'].append(size)
170 with open(filename,
'r+b')
as wbfr:
171 logger.info(
"** Corrupting 8byte of Metadata at offset {} with b'1111222244443333' **".
format(offset))
173 wbfr.write(b
'\x33\x33\x44\x44\x22\x22\x11\x11')
180 with open(filename,
"rb")
as mdata:
182 data = binascii.hexlify((mdata.read(8))[::-1])
196 curr_record.append(data.decode(
'utf-8'))
200 curr_record = [
hex(
int(i, 16))
for i
in curr_record]
201 return curr_record, offset
204 llist = BeBnodeTypeKeys[offset]
205 with open(filename,
"rb")
as mdata:
207 data = binascii.hexlify((mdata.read(8))[::-1])
209 logger.info(
"bli_type of BE_BNODE is: {0}: {1}".
format( data, btreeType[data]))
212 data = binascii.hexlify((mdata.read(8))[::-1])
214 logger.info(
"Active key count of BE_BNODE is: {}".
format(
int(data,16)))
219 logger.info(recordType)
220 logger.info(
"Number of Error want to induce: {}".
format(noOfErr))
221 lookupList = recordDict[recordType]
222 if (len(lookupList)
and noOfErr) == 0:
223 logger.error(
"Record List is empty. Please choose another Record")
226 elif len(lookupList) < noOfErr:
228 " Record List contains Less number of entries than input. Please reduce the number of Error Injection")
232 logger.info(lookupList)
233 logger.info(
"**** Inducing {} Error in Record: {} ****".
format(noOfErr, recordType))
234 for i
in range(noOfErr):
235 offset = lookupList[i]
238 if recordType ==
"BE_BNODE":
248 recType = random.choice(
list(recordDict))
249 logger.info(
"++++ Picked a Random Record from Dictionary Record type:{}++++".
format(recType))
250 logger.info(
"Number of Error want to induce: {}".
format(noOfErr))
251 lookupList = recordDict[recType]
252 logger.info(lookupList)
253 if (len(lookupList) == 0)
or (len(lookupList) < noOfErr):
254 logger.info(
"Record List is empty OR contains Less number of entries than input. Going to next Record")
256 lookupList = random.sample(lookupList, noOfErr)
257 logger.info(lookupList)
258 for i
in range(noOfErr):
259 offset = lookupList[i]
260 logger.info(
"**** Inducing RANDOM Error in Record at offsets {}****".
format(
hex(offset + 8)))
272 logger.info(
"++++ Induce Random number of errors in All Records ++++")
273 for recType
in recordDict:
274 logger.info(
"Record Name: {}".
format(recType))
275 lookupList = recordDict[recType]
276 length = len(lookupList)
278 logger.info(
"Record List is empty. Moving to Next Record")
280 lookupList = random.sample(lookupList, random.randint(1, length))
281 logger.info(
"Inducing {} Error at these offsets".
format(len(lookupList)))
282 logger.info(lookupList)
283 for offset
in lookupList:
284 logger.info(
"**** Inducing Error in Record at offsets {}****".
format(
hex(offset + 8)))
295 logger.info(
"++++ Induce Random number of errors in All GMD Records ++++")
296 for recType
in GMDList:
297 logger.info(
"Record Name: {}".
format(recType))
298 lookupList = recordDict[recType]
299 length = len(lookupList)
301 logger.info(
"Record List is empty. Moving to Next Record")
303 lookupList = random.sample(lookupList, random.randint(1, length))
304 logger.info(
"Inducing {} Error at these offsets".
format(len(lookupList)))
305 logger.info(lookupList)
306 for offset
in lookupList:
307 logger.info(
"**** Inducing Error in Record at offsets {}****".
format(
hex(offset + 8)))
318 logger.info(
"++++ Induce Random number of errors in All DMD Records ++++")
319 for recType
in DMDList:
320 logger.info(
"Record Name: {}".
format(recType))
321 lookupList = recordDict[recType]
322 length = len(lookupList)
324 logger.info(
"Record List is empty. Moving to Next Record")
326 lookupList = random.sample(lookupList, random.randint(1, length))
327 logger.info(
"Inducing {} Error at these offsets".
format(len(lookupList)))
328 logger.info(lookupList)
329 for offset
in lookupList:
330 logger.info(
"**** Inducing Error in Record at offsets {}****".
format(
hex(offset + 8)))
341 with open(filename,
'r+b')
as wbfr:
342 logger.info(
"** Corrupting 8byte of Metadata with b'1111222244443333' all place")
343 wbfr.seek(-1, os.SEEK_END)
344 endOffset = wbfr.tell()
345 offset = random.randint(1, endOffset)
346 logger.info(
"Start offset is {}".
format(offset))
363 with open(filename,
'r+b')
as wbfr:
364 wbfr.seek(-524400, os.SEEK_END)
365 endOffset = wbfr.tell()
366 offset = random.randint(1, endOffset)
367 logger.info(
"Start offset is {}".
format(offset))
385 M0_FID_DEVICE_ID_OFFSET = 32
386 M0_FID_DEVICE_ID_MASK = 72057589742960640
387 M0_FID_TYPE_MASK = 72057594037927935
391 cob_f_container = ((tid << (64 - 8 )) | (
int(stob_f_container, 16) & M0_FID_TYPE_MASK))
392 cob_f_key =
int(stob_f_key, 16)
393 device_id = (
int(cob_f_container) & M0_FID_DEVICE_ID_MASK) >> M0_FID_DEVICE_ID_OFFSET
395 return cob_f_container, cob_f_key, device_id
399 M0_FID_TYPE_MASK = 72057594037927935
403 stob_f_container = ((tid << (64 - 8 )) | (
int(cob_f_container, 16) & M0_FID_TYPE_MASK))
404 stob_f_key =
int(cob_f_key, 16)
406 return stob_f_container, stob_f_key
412 lookupList = recordDict[recordType]
414 logger.info(
"*****Corrupting BE_EMAP_KEY for Cob ID {}*****".
format(args.corrupt_emap))
416 for offset
in lookupList:
418 if (
hex(stob_f_container)
in emap_key_data)
and (
hex(stob_f_key)
in emap_key_data)
and (
"0xffffffffffffffff" not in emap_key_data):
420 rec_offset = offset + 32
424 if emap_rec_data[3] !=
"0x0":
425 logger.info(
"** Metadata at offset {}, BE_EMAP_KEY ek_prefix = {}:{}, ek_offset = {}".
format(offset-24,
426 emap_key_data[0], emap_key_data[1], emap_key_data[2]))
427 logger.info(
"** Metadata at offset {}, BE_EMAP_REC er_start = {}, er_value = {}, er_unit_size = {}, er_cs_nob = {}, checksum = {}".
format(
428 offset+32, emap_rec_data[0], emap_rec_data[1], emap_rec_data[2], emap_rec_data[3], emap_rec_data[4:]))
435 logger.info(
"*****Listing all emap keys and emap records with device id*****")
436 recordType =
"BE_EMAP_KEY" 438 lookupList = recordDict[recordType]
441 for offset
in lookupList:
444 stob_f_container_hex = emap_key_data[0]
445 stob_f_key_hex = emap_key_data[1]
448 emap_rec_offset = offset + 32
451 logger.info(
"** Metadata at offset {}, BE_EMAP_KEY ek_prefix = {}:{}, ek_offset = {}, Device ID = {}".
format(offset,
452 emap_key_data[0], emap_key_data[1], emap_key_data[2], device_id))
453 logger.info(
"** Metadata at offset {}, BE_EMAP_REC er_start = {}, er_value = {}, er_unit_size = {}, er_cs_nob = {}, checksum = {}".
format(
454 emap_rec_offset, emap_rec_data[0], emap_rec_data[1], emap_rec_data[2], emap_rec_data[3], emap_rec_data[4:]))
460 logger.info(
"***********Record list will be print here************")
461 for record, items
in recordDict.items():
462 logger.info(
" {} : {}".
format(record, len(items)))
468 with open(filename,
"rb")
as metadata:
470 metadata.seek(args.seek_offset)
472 byte = metadata.read(8)
476 byte = binascii.hexlify(byte[::-1])
478 byte = binascii.hexlify((metadata.read(8))[::-1])
480 if rtype
not in typeDict.keys():
482 record = typeDict[rtype]
484 if size > b
'00000000':
487 i =
int(size, 16) + i - 16
490 if (args.verify ==
True)
or (args.list_emap ==
True):
492 if i > args.parse_size:
506 elif args.hugeCorruption:
527 elif args.corrupt_emap:
528 _f_container, _f_key = args.corrupt_emap.split(
":")
529 cob_f_container =
hex(
int(_f_container, 16))
532 noOfErrs =
CorruptEmap(
"BE_EMAP_KEY", stob_f_container, stob_f_key)
538 logger.info(
"Number of errors induced by script: {}".
format(noOfErrs))
541 logger.info(
"**** Successfully injected holes in metadata ****")
543 logger.error(
"**** Failed to inject holes in metadata ****")
static struct m0_list list
def InduceErrInDMDRecords()
def RecordOffset(record, i, size)
def ListAllEmapPerDevice()
static M0_UNUSED void print(struct m0_be_list *list)
def InduceErrInGMDRecords()
def VerifyLengthOfRecord(recordDict)
def InduceCorruption(recordType, noOfErr)
def ReadCompleteRecord(offset)
def InduceErrInAllRecord()
def ConvertAdstob2Cob(stob_f_container, stob_f_key)
def ConvertCobAdstob(cob_f_container, cob_f_key)
def CorruptEmap(recordType, stob_f_container, stob_f_key)
def InduceRandomCorruption(noOfErr)
static void hex(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)