@@ -43,11 +43,54 @@ def setUp(self):
4343 """ Pre Section for TestNVMeIO """
4444 super ().setUp ()
4545 # common code used in various testcases.
46- (self .data_size , _ ) = self .get_lba_format_size ()
46+ (ds , ms ) = self .get_lba_format_size ()
47+ self .ms = ms
48+ # PI type occupies bits 2:0 of the DPS field; bits 5:3 are PIF.
49+ pi_type = self .ns_dps & 0x7
50+ if pi_type != 0 and ms != 0 and self .ns_meta_ext :
51+ # PI active + extended LBA (metadata appended to data buffer).
52+ # Use PRACT=1 (--prinfo=8) so the controller inserts and strips PI
53+ # automatically. With PRACT=1 the PI bytes are not transferred
54+ # over the host interface, so data_size equals the logical block
55+ # data size only (ds), not ds+ms. This works for all PI sizes
56+ # (8 bytes for PIF 0/2, 16 bytes for PIF 1) and all guard widths
57+ # (16-bit, 32-bit, 64-bit CRC) because the controller handles
58+ # the PI entirely.
59+ self .prinfo = 8
60+ self .data_size = ds
61+ elif pi_type != 0 and ms != 0 and not self .ns_meta_ext :
62+ # PI active + separate metadata (flbas bit 4 clear). PRACT=1
63+ # (--prinfo=8) is invalid for the Compare command on this format
64+ # (NVMe spec: PRACT=1 for Compare requires PI in the host data
65+ # buffer, which only applies to the extended-LBA layout). Use
66+ # prinfo=0 (PRACT=0, PRCHK=0) for all operations and supply an
67+ # explicit zero-filled metadata buffer of ms bytes so that the
68+ # stored metadata and the compared metadata are both known zeros.
69+ # PRCHK=0 skips PI validation, so the zero PI bytes are accepted
70+ # by the controller on write and matched exactly on compare. This
71+ # is PI-format and guard-width agnostic: the entire ms-byte
72+ # metadata slot (whether holding an 8-byte PI with 16-bit or
73+ # 32-bit guard, or a 16-byte PI with 64-bit guard) is zeroed.
74+ self .prinfo = 0
75+ self .data_size = ds
76+ else :
77+ # No PI. For extended LBA format (metadata appended to the data
78+ # buffer) include the metadata bytes so that the controller sees
79+ # a consistent data+metadata unit. For separate metadata format
80+ # (flbas bit 4 clear) the metadata is transferred via a different
81+ # pointer and must NOT be folded into the data buffer; use ds only
82+ # so that the data transfer length matches exactly one LBA.
83+ self .prinfo = 0
84+ self .data_size = ds + ms if self .ns_meta_ext else ds
4785 self .start_block = 0
4886 self .block_count = 0
4987 self .write_file = "write_file.txt"
5088 self .read_file = "read_file.txt"
89+ # Basename only; subclasses must prepend the test_log_dir path before
90+ # use (same convention as write_file and read_file above).
91+ if self .ms > 0 and not self .ns_meta_ext :
92+ self .write_meta_file = "write_meta_file.bin"
93+ self .read_meta_file = "read_meta_file.bin"
5194
5295 def tearDown (self ):
5396 """ Post Section for TestNVMeIO """
@@ -70,6 +113,18 @@ def create_data_file(self, pathname, data_size, pattern):
70113 os .fsync (data_file .fileno ())
71114 data_file .close ()
72115
116+ def create_meta_file (self , pathname , meta_size ):
117+ """ Creates a binary file of meta_size zero bytes for use as a
118+ separate-metadata buffer in nvme write/read/compare commands.
119+ - Args:
120+ - pathname : metadata file path name.
121+ - meta_size : total size of the metadata in bytes.
122+ - Returns:
123+ None
124+ """
125+ with open (pathname , "wb" ) as meta_file :
126+ meta_file .write (bytes (meta_size ))
127+
73128 def nvme_write (self ):
74129 """ Wrapper for nvme write operation
75130 - Args:
@@ -81,6 +136,11 @@ def nvme_write(self):
81136 f"--start-block={ str (self .start_block )} " + \
82137 f"--block-count={ str (self .block_count )} " + \
83138 f"--data-size={ str (self .data_size )} --data={ self .write_file } "
139+ if self .prinfo :
140+ write_cmd += f" --prinfo={ self .prinfo } "
141+ if self .ms > 0 and not self .ns_meta_ext :
142+ write_cmd += \
143+ f" --metadata-size={ self .ms } --metadata={ self .write_meta_file } "
84144 return self .exec_cmd (write_cmd )
85145
86146 def nvme_read (self ):
@@ -94,4 +154,9 @@ def nvme_read(self):
94154 f"--start-block={ str (self .start_block )} " + \
95155 f"--block-count={ str (self .block_count )} " + \
96156 f"--data-size={ str (self .data_size )} --data={ self .read_file } "
157+ if self .prinfo :
158+ read_cmd += f" --prinfo={ self .prinfo } "
159+ if self .ms > 0 and not self .ns_meta_ext :
160+ read_cmd += \
161+ f" --metadata-size={ self .ms } --metadata={ self .read_meta_file } "
97162 return self .exec_cmd (read_cmd )
0 commit comments