Motr  M0
error_injection.py
Go to the documentation of this file.
1 #!/usr/bin/python3
2 #
3 # Copyright (c) 2020 Seagate Technology LLC and/or its Affiliates
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #
17 # For any questions about this software or licensing,
18 # please email opensource@seagate.com or cortx-questions@seagate.com.
19 #
20 import binascii
21 import sys
22 import os
23 import random
24 import argparse
25 import time
26 import logging
27 
28 timestr = time.strftime("%Y%m%d-%H%M%S")
29 log_filename = "hole_creation_" + timestr + ".log"
30 
31 logger = logging.getLogger()
32 logger.setLevel(logging.DEBUG)
33 
34 fh = logging.FileHandler(log_filename)
35 fh.setLevel(logging.DEBUG)
36 
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)
43 logger.addHandler(fh)
44 logger.addHandler(ch)
45 
46 logger.info("***** Script Started *****")
47 
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')
76 
77 args = parser.parse_args()
78 
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))
95 
96 filename = args.mfile
97 recordType = args.Record_Type
98 noOfErr = args.noOfErr
99 
100 if args.seed != 0:
101  seed = args.seed
102  logger.info("Seed used: {}".format(seed))
103 else:
104  seed = time.time()
105  logger.info("Seed used: {}".format(seed))
106 
107 random.seed(seed)
108 
109 if not os.walk(filename):
110  logger.error('Failed: The path specified does not exist or Missing file path')
111  sys.exit(1)
112 
113 # M0_FORMAT_HEADER_MAGIC = 0x33011ca5e511de77
114 header = b'33011ca5e511de77'
115 # M0_FORMAT_FOOTER_MAGIC = 0x33f007e7f007e777
116 footer = b'33f007e7f007e777'
117 
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',
123  b'12': 'CAS_INDEX',
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'}
126 
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': []}
132 
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': []}
138 
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']
142 
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'}
146 
147 BeBnodeTypeKeys = {}
148 
149 def RecordOffset(record, i, size):
150  if record in recordDict.keys():
151  recordDict[record].append(i)
152  sizeDict[record].append(size)
153  if record == "BE_BNODE":
154  bliType = i + 16 # bli_type offet
155  btNumActiveKey = i + 56 # active key count offset
156  BeBnodeTypeKeys[i] = [bliType, btNumActiveKey]
157  else:
158  recordDict['EXTRA'].append(i)
159  sizeDict['EXTRA'].append(size)
160 
161 def ReadTypeSize(byte): # Ex: 0001(ver) 0009(type) 00003dd8(size)
162  # ver = byte[:4] # .ot_version = src->hd_bits >> 48,
163  rtype = byte[6:8] # .ot_type = src->hd_bits >> 32 & 0x0000ffff,
164  size = byte[8:16] # .ot_size = src->hd_bits & 0xffffffff
165  # logger.info("Version {}, Type {}, Size {}".format(ver, rtype, size)) #debug print
166  return rtype, size
167 
168 
169 def EditMetadata(offset):
170  with open(filename, 'r+b') as wbfr:
171  logger.info("** Corrupting 8byte of Metadata at offset {} with b'1111222244443333' **".format(offset))
172  wbfr.seek(offset)
173  wbfr.write(b'\x33\x33\x44\x44\x22\x22\x11\x11')
174  wbfr.seek(offset)
175  ReadMetadata(offset)
176 
177 
178 # If you want to verify the written Metadata then run below segment of code
179 def ReadMetadata(offset):
180  with open(filename, "rb") as mdata:
181  mdata.seek(offset)
182  data = binascii.hexlify((mdata.read(8))[::-1])
183  if data == footer:
184  return True, data
185  else:
186  return False, data
187 
188 # This function returns complete data with list format in 8 bytes chunks,
189 # starting after header and until footer for record
190 def ReadCompleteRecord(offset):
191  curr_record = []
192  while 1:
193  footerFound, data=ReadMetadata(offset)
194  if footerFound:
195  break
196  curr_record.append(data.decode('utf-8'))
197  offset = offset + 8 # check next 8 bytes
198 
199  # Convert list to hex representation
200  curr_record = [ hex(int(i, 16)) for i in curr_record]
201  return curr_record, offset # Return record data and footer offset
202 
203 def ReadBeBNode(offset):
204  llist = BeBnodeTypeKeys[offset]
205  with open(filename, "rb") as mdata:
206  mdata.seek(llist[0])
207  data = binascii.hexlify((mdata.read(8))[::-1])
208  data = data[14:16]
209  logger.info("bli_type of BE_BNODE is: {0}: {1}".format( data, btreeType[data]))
210 
211  mdata.seek(llist[1])
212  data = binascii.hexlify((mdata.read(8))[::-1])
213  data = data[8:16]
214  logger.info("Active key count of BE_BNODE is: {}".format( int(data,16)))
215 
216 def InduceCorruption(recordType, noOfErr):
217  count = 0
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")
224  count = 0
225  return count
226  elif len(lookupList) < noOfErr:
227  logger.error(
228  " Record List contains Less number of entries than input. Please reduce the number of Error Injection")
229  count = 0
230  return count
231  else:
232  logger.info(lookupList)
233  logger.info("**** Inducing {} Error in Record: {} ****".format(noOfErr, recordType))
234  for i in range(noOfErr):
235  offset = lookupList[i] # Please add offset here for starting from middle of offset list
236  ReadMetadata(offset + 8)
237  EditMetadata(offset + 8)
238  if recordType == "BE_BNODE":
239  ReadBeBNode(offset)
240  count = count + 1
241  return count
242 
243 
245  count = 0
247  while 1:
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")
255  else:
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)))
261  ReadMetadata(offset + 8) # Read original
262  EditMetadata(offset + 8) # Modify
263  ReadMetadata(offset + 8) # Verify
264  count = count + 1
265  break
266  return count
267 
268 
270  count = 0
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)
277  if length == 0:
278  logger.info("Record List is empty. Moving to Next Record")
279  else:
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)))
285  ReadMetadata(offset + 8) # Read original
286  EditMetadata(offset + 8) # Modify
287  ReadMetadata(offset + 8) # Verify
288  count = count + 1
289  return count
290 
291 
293  count = 0
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)
300  if length == 0:
301  logger.info("Record List is empty. Moving to Next Record")
302  else:
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)))
308  ReadMetadata(offset + 8) # Read original
309  EditMetadata(offset + 8) # Modify
310  ReadMetadata(offset + 8) # Verify
311  count = count + 1
312  return count
313 
314 
316  count = 0
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)
323  if length == 0:
324  logger.info("Record List is empty. Moving to Next Record")
325  else:
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)))
331  ReadMetadata(offset + 8)
332  EditMetadata(offset + 8)
333  ReadMetadata(offset + 8)
334  count = count + 1
335  return count
336 
337 
338 # Corrupt Metadata file from random location till end of metadata file
340  count = 0
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))
347  while 1:
348  offset = offset + 8
349  wbfr.seek(offset)
350  byte = wbfr.read(8)
351  if not byte:
352  break
353  else:
354  EditMetadata(offset + 8)
355  count = count + 1
356  return count
357 
358 
359 # Corrupt 512k Metadata in Metadata file from random location
361  count = 0
362  j = 0
363  with open(filename, 'r+b') as wbfr:
364  wbfr.seek(-524400, os.SEEK_END) # Took a bigger number than 512k
365  endOffset = wbfr.tell()
366  offset = random.randint(1, endOffset)
367  logger.info("Start offset is {}".format(offset))
368  while 1:
369  offset = offset + 8
370  j = j + 8
371  wbfr.seek(offset)
372  byte = wbfr.read(8)
373  if not byte:
374  break
375  else:
376  if j > 524288:
377  break
378  else:
379  EditMetadata(offset)
380  count = count + 1
381  return count
382 
383 # This function take stob_f_container, stob_f_key and returns cob_f_cotainer, cob_f_key and device_id
384 def ConvertAdstob2Cob(stob_f_container, stob_f_key):
385  M0_FID_DEVICE_ID_OFFSET = 32
386  M0_FID_DEVICE_ID_MASK = 72057589742960640
387  M0_FID_TYPE_MASK = 72057594037927935
388 
389  # m0_fid_tassume()
390  tid = int(67) # Char 'C' Ascii Value
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
394 
395  return cob_f_container, cob_f_key, device_id
396 
397 # This function take cob_f_cotainer, cob_f_key and returns stob_f_container, stob_f_key
398 def ConvertCobAdstob(cob_f_container, cob_f_key):
399  M0_FID_TYPE_MASK = 72057594037927935
400 
401  # m0_fid_tassume()
402  tid = 2 # STOB_TYPE_AD = 0x02
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)
405 
406  return stob_f_container, stob_f_key
407 
408 # This function corrupt Emap Record specified by Cob Id
409 def CorruptEmap(recordType, stob_f_container, stob_f_key):
410  count = 0
412  lookupList = recordDict[recordType]
413  # logger.info("Offset List of {} = {} ".format(recordType, lookupList))
414  logger.info("*****Corrupting BE_EMAP_KEY for Cob ID {}*****".format(args.corrupt_emap))
415 
416  for offset in lookupList:
417  emap_key_data, offset = ReadCompleteRecord(offset)
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):
419  # 16 bytes of BE_EMAP_KEY (footer) + 16 bytes of BE_EMAP_REC(header) gives offset of corresponding BE_EMAP_REC
420  rec_offset = offset + 32
421  emap_rec_data, rec_offset = ReadCompleteRecord(rec_offset)
422 
423  # Check er_cs_nob and if it is not 0 then go and corrupt last checksum 8 bytes
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:]))
429  EditMetadata(rec_offset-8)
430  count = count + 1
431  print()
432  return count
433 
435  logger.info("*****Listing all emap keys and emap records with device id*****")
436  recordType = "BE_EMAP_KEY"
438  lookupList = recordDict[recordType]
439  # logger.info(lookupList)
440 
441  for offset in lookupList:
442  print()
443  emap_key_data , offset = ReadCompleteRecord(offset)
444  stob_f_container_hex = emap_key_data[0]
445  stob_f_key_hex = emap_key_data[1]
446  _, _, device_id = ConvertAdstob2Cob(stob_f_container_hex, stob_f_key_hex)
447  # 16 bytes of BE_EMAP_KEY (footer) + 16 bytes of BE_EMAP_REC(header) gives offset of Corresponding BE_EMAP_REC
448  emap_rec_offset = offset + 32
449  emap_rec_data, _ = ReadCompleteRecord(emap_rec_offset)
450 
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:]))
455 
456 
457 def VerifyLengthOfRecord(recordDict):
458  count = 0
460  logger.info("***********Record list will be print here************")
461  for record, items in recordDict.items():
462  logger.info(" {} : {}".format(record, len(items)))
463  count = count + 1
464  return count
465 
466 
468  with open(filename, "rb") as metadata:
469  i: int = 0
470  metadata.seek(args.seek_offset)
471  while 1:
472  byte = metadata.read(8)
473  i = i + 8
474  if not byte:
475  break
476  byte = binascii.hexlify(byte[::-1])
477  if byte == header:
478  byte = binascii.hexlify((metadata.read(8))[::-1]) # Read the Type Size Version
479  rtype, size = ReadTypeSize(byte)
480  if rtype not in typeDict.keys():
481  continue
482  record = typeDict[rtype]
483  i = i + 8
484  if size > b'00000000':
485  RecordOffset(record, i, size)
486  # logger.info("*** RECORD TYPE {}, OFFSET {}, SIZE{} ***".format(record, i, size)) #Debug print
487  i = int(size, 16) + i - 16
488  metadata.seek(i)
489  # Not parsing the whole file for few test as It will take many hours, depending on metadata size
490  if (args.verify == True) or (args.list_emap == True):
491  if args.parse_size:
492  if i > args.parse_size: # This will parse metadata file util specified parse_size for list_emap and verify option
493  break
494  else:
495  pass # we will read complete metadata file in case of -v or -list_emap option
496  else:
497  if i > 111280000: # Increase this number for reading more location in metadata
498  break
499 
500 
501 noOfErrs = 0
502 
503 if args.err512k:
504  noOfErrs = Induce512kbError()
505 
506 elif args.hugeCorruption:
507  noOfErrs = InduceHugeError()
508 
509 elif args.random:
510  noOfErrs = InduceRandomCorruption(noOfErr)
511 
512 elif recordType:
513  noOfErrs = InduceCorruption(recordType, noOfErr)
514 
515 elif args.verify:
516  noOfErrs = VerifyLengthOfRecord(recordDict)
517 
518 elif args.allErr:
519  noOfErrs = InduceErrInAllRecord()
520 
521 elif args.allGMD:
522  noOfErrs = InduceErrInGMDRecords()
523 
524 elif args.allDMD:
525  noOfErrs = InduceErrInDMDRecords()
526 
527 elif args.corrupt_emap:
528  _f_container, _f_key = args.corrupt_emap.split(":")
529  cob_f_container = hex(int(_f_container, 16))
530  cob_f_key = hex(int(_f_key, 16))
531  stob_f_container, stob_f_key = ConvertCobAdstob(cob_f_container, cob_f_key)
532  noOfErrs = CorruptEmap("BE_EMAP_KEY", stob_f_container, stob_f_key)
533 
534 elif args.list_emap:
536 
537 if not args.verify:
538  logger.info("Number of errors induced by script: {}".format(noOfErrs))
539 
540 if noOfErrs > 0:
541  logger.info("**** Successfully injected holes in metadata ****")
542 else:
543  logger.error("**** Failed to inject holes in metadata ****")
static struct m0_list list
Definition: list.c:144
def RecordOffset(record, i, size)
def ReadTypeSize(byte)
static M0_UNUSED void print(struct m0_be_list *list)
Definition: list.c:186
def VerifyLengthOfRecord(recordDict)
def InduceCorruption(recordType, noOfErr)
def ReadCompleteRecord(offset)
format
Definition: hist.py:128
def ConvertAdstob2Cob(stob_f_container, stob_f_key)
def EditMetadata(offset)
def ReadMetadata(offset)
def ConvertCobAdstob(cob_f_container, cob_f_key)
def CorruptEmap(recordType, stob_f_container, stob_f_key)
def InduceRandomCorruption(noOfErr)
def ReadBeBNode(offset)
static void hex(struct m0_addb2__context *ctx, const uint64_t *v, char *buf)
Definition: dump.c:413