diff --git a/memory/ndctl.py b/memory/ndctl.py index f45669837..6555786d1 100644 --- a/memory/ndctl.py +++ b/memory/ndctl.py @@ -41,7 +41,7 @@ class NdctlTest(Test): Ndctl user space tooling for Linux, which handles NVDIMM devices. """ - def get_json(self, option=''): + def run_ndctl_list(self, option=''): """ Get the json of each provided options @@ -56,7 +56,7 @@ def get_json(self, option=''): return json_op @staticmethod - def get_json_val(json_op, field): + def run_ndctl_list_val(json_op, field): """ Get the value of a field in given json """ @@ -73,27 +73,20 @@ def get_default_region(self): region = self.params.get('region', default=None) if region: return region - regions = self.get_json('-R') + regions = self.run_ndctl_list('-R') regions = sorted(regions, key=lambda i: i['size'], reverse=True) - return self.get_json_val(regions[0], 'dev') + return self.run_ndctl_list_val(regions[0], 'dev') - def get_aligned_count(self, size): + @staticmethod + def get_size_alignval(): """ - Return count based on default alignemnt + Return the size align restriction based on platform """ if 'Hash' in genio.read_file('/proc/cpuinfo').rstrip('\t\r\n\0'): def_align = 16 * 1024 * 1024 else: def_align = 2 * 1024 * 1024 - if ((size // self.cnt) % def_align) != 0: - self.log.warn("Namespace would fail as it is not %sM " - "aligned! Changing the number of " - "namespaces", def_align // (1024 * 1024)) - for count in range(self.cnt, 1, -1): - if ((size // count) % def_align) == 0: - self.log.info("Changing namespaces to %s", count) - return count - return self.cnt + return def_align def get_slot_count(self, region): """ @@ -107,8 +100,8 @@ def get_slot_count(self, region): except ValueError: json_op = [] first_dict = json_op[0] - index_dict = self.get_json_val(first_dict, 'index')[0] - return self.get_json_val(index_dict, 'nslot') + index_dict = self.run_ndctl_list_val(first_dict, 'index')[0] + return self.run_ndctl_list_val(index_dict, 'nslot') - 1 def build_fio(self): """ @@ -247,19 +240,14 @@ def setUp(self): deps = [] self.dist = distro.detect() self.package = self.params.get('package', default='upstream') - self.cnt = self.params.get('namespace_cnt', default=4) self.preserve_setup = self.params.get('preserve_change', default=False) - self.size = self.params.get('size', default=None) self.mode_to_use = self.params.get('modes', default='fsdax') - self.reflink = '' if self.dist.name not in ['SuSE', 'rhel']: self.cancel('Unsupported OS %s' % self.dist.name) - else: - if self.dist.name == 'rhel': - # DAX wont work with reflink, disabling here - self.reflink = '-m reflink=0' + # DAX wont work with reflink, disabling here + self.reflink = '-m reflink=0' if not self.check_buses(): self.cancel("Test needs atleast one region") @@ -311,8 +299,8 @@ def test_bus_ids(self): """ Test the bus id info """ - vals = self.get_json('-B') - if not len(vals): + vals = self.run_ndctl_list('-B') + if not vals: self.fail('Failed to fetch bus IDs') self.log.info('Available Bus provider IDs: %s', vals) @@ -320,8 +308,8 @@ def test_dimms(self): """ Test the dimms info """ - vals = self.get_json('-D') - if not len(vals): + vals = self.run_ndctl_list('-D') + if not vals: self.fail('Failed to fetch DIMMs') self.log.info('Available DIMMs: %s', vals) @@ -330,9 +318,9 @@ def test_regions(self): Test the regions info """ self.disable_region() - old = self.get_json('-R') + old = self.run_ndctl_list('-R') self.enable_region() - new = self.get_json('-R') + new = self.run_ndctl_list('-R') if len(new) <= len(old): self.fail('Failed to fetch regions') self.log.info('Available regions: %s', new) @@ -342,14 +330,14 @@ def test_namespace(self): Test namespace """ self.enable_region() - regions = self.get_json('-R') + regions = self.run_ndctl_list('-R') for val in regions: - region = self.get_json_val(val, 'dev') + region = self.run_ndctl_list_val(val, 'dev') self.disable_namespace(region=region) self.destroy_namespace(region=region) self.create_namespace(region=region) - namespaces = self.get_json('-N') + namespaces = self.run_ndctl_list('-N') self.log.info('Created namespace %s', namespaces) def test_disable_enable_ns(self): @@ -359,10 +347,10 @@ def test_disable_enable_ns(self): region = self.get_default_region() for _ in range(0, 3): self.create_namespace(region=region, size='128M') - namespaces = self.get_json('-N') + namespaces = self.run_ndctl_list('-N') ns_names = [] for ns in namespaces: - ns_names.append(self.get_json_val(ns, 'dev')) + ns_names.append(self.run_ndctl_list_val(ns, 'dev')) ns_names.append('all') for namespace in ns_names: @@ -380,41 +368,69 @@ def test_namespace_modes(self): self.destroy_namespace(region=region) for mode in self.modes: self.create_namespace(region=region, mode=mode) - ns_json = self.get_json()[0] - created_mode = self.get_json_val(ns_json, 'mode') + ns_json = self.run_ndctl_list()[0] + created_mode = self.run_ndctl_list_val(ns_json, 'mode') if mode != created_mode: failed_modes.append(mode) self.log.error("Expected mode %s, Got %s", mode, created_mode) else: - self.log.info("Namespace with %s mode: %s" % (mode, ns_json)) - ns_name = self.get_json_val(ns_json, 'dev') + self.log.info("Namespace with %s mode: %s", mode, ns_json) + ns_name = self.run_ndctl_list_val(ns_json, 'dev') self.disable_namespace(namespace=ns_name, region=region) self.destroy_namespace(namespace=ns_name, region=region) if failed_modes: self.fail("Namespace for %s mode failed!" % failed_modes) - def test_multiple_namespaces_region(self): + def multiple_namespaces_region(self, region): """ Test multiple namespace with single region """ - region = self.get_default_region() + namespace_size = self.params.get('size', default=None) + size_align = self.get_size_alignval() + slot_count = self.get_slot_count(region) self.log.info("Using %s for muliple namespace regions", region) self.disable_namespace(region=region) self.destroy_namespace(region=region) - self.log.info("Creating %s namespaces", self.cnt) - if not self.size: - self.size = self.get_json_val(self.get_json( - '-r %s' % region)[0], 'size') - ch_cnt = self.get_aligned_count(self.size) - self.size = self.size // ch_cnt + if namespace_size and ((namespace_size % size_align) != 0): + self.cancel("Size value not %d aligned %d \n", + size_align, namespace_size) + + region_size = self.run_ndctl_list_val(self.run_ndctl_list( + '-r %s' % region)[0], 'size') + if not namespace_size: + namespace_size = region_size // slot_count + # Now align the namespace size + namespace_size = (namespace_size // size_align) * size_align else: - # Assuming self.cnt is aligned - ch_cnt = self.cnt - for nid in range(0, ch_cnt): + slot_count = region_size // namespace_size + + self.log.info("Creating %s namespaces", slot_count) + for count in range(0, slot_count): self.create_namespace( - region=region, mode=self.mode_to_use, size=self.size) - self.log.info("Namespace %s created", nid + 1) + region=region, mode=self.mode_to_use, size=namespace_size) + self.log.info("Namespace %s created", count + 1) + + def test_multiple_namespaces_region(self): + """ + Test multiple namespace with single region + """ + region = self.get_default_region() + self.multiple_namespaces_region(region) + + def test_multiple_ns_multiple_region(self): + """ + Test multiple namespace with multiple region + """ + self.enable_region() + if len(self.run_ndctl_list('-R')) <= 1: + self.cancel("Test not applicable without multiple regions") + regions = self.run_ndctl_list('-R') + self.disable_namespace() + self.destroy_namespace() + for val in regions: + region = self.run_ndctl_list_val(val, 'dev') + self.multiple_namespaces_region(region) def test_multiple_ns_modes_region(self): """ @@ -424,7 +440,7 @@ def test_multiple_ns_modes_region(self): self.log.info("Using %s for muliple namespace regions", region) self.disable_namespace(region=region) self.destroy_namespace(region=region) - size = self.get_json_val(self.get_json( + size = self.run_ndctl_list_val(self.run_ndctl_list( '-r %s' % region)[0], 'size') if size < (len(self.modes) * 64 * 1024 * 1024): self.cancel('Not enough memory to create namespaces') @@ -433,52 +449,26 @@ def test_multiple_ns_modes_region(self): region=region, mode=mode, size='64M') self.log.info("Namespace of type %s created", mode) - def test_multiple_ns_multiple_region(self): - """ - Test multiple namespace with multiple region - """ - self.enable_region() - if len(self.get_json('-R')) <= 1: - self.cancel("Test not applicable without multiple regions") - regions = self.get_json('-R') - self.disable_namespace() - self.destroy_namespace() - for val in regions: - ns_size = None - region = self.get_json_val(val, 'dev') - self.log.info("Using %s for muliple namespaces", region) - self.log.info("Creating %s namespaces", self.cnt) - if not self.size: - ns_size = self.get_json_val(self.get_json( - '-r %s' % region)[0], 'size') - ch_cnt = self.get_aligned_count(ns_size) - ns_size = ns_size // ch_cnt - else: - # Assuming size is aligned - ns_size = self.size - ch_cnt = self.cnt - for nid in range(0, ch_cnt): - self.create_namespace( - region=region, mode=self.mode_to_use, size=ns_size) - self.log.info("Namespace %s created", nid + 1) - def test_nslot_namespace(self): """ Test max namespace with nslot value """ region = self.get_default_region() + size_align = self.get_size_alignval() + slot_count = self.get_slot_count(region) self.log.info("Using %s for max namespace creation", region) self.disable_namespace() self.destroy_namespace() - region_size = self.get_json_val(self.get_json( + region_size = self.run_ndctl_list_val(self.run_ndctl_list( '-r %s' % region)[0], 'size') - namespace_size = 1 << 30 - count = region_size // namespace_size - count = min(count, self.get_slot_count(region)) - 1 - self.log.info("Creating %s namespace", count) - for nid in range(1, count + 1): + namespace_size = region_size // slot_count + # Now align the namespace size + namespace_size = (namespace_size // size_align) * size_align + + self.log.info("Creating %s namespace", slot_count) + for count in range(0, slot_count): self.create_namespace(region=region, mode='fsdax', size='1G') - self.log.info("Namespace %s created", nid) + self.log.info("Namespace %s created", count) def test_namespace_reconfigure(self): """ @@ -489,12 +479,12 @@ def test_namespace_reconfigure(self): self.disable_namespace() self.destroy_namespace() self.create_namespace(region=region, mode='fsdax', align='64k') - old_ns = self.get_json()[0] - old_ns_dev = self.get_json_val(old_ns, 'dev') + old_ns = self.run_ndctl_list()[0] + old_ns_dev = self.run_ndctl_list_val(old_ns, 'dev') self.log.info("Re-configuring namespace %s", old_ns_dev) self.create_namespace(region=region, mode='fsdax', name='test_ns', reconfig=old_ns_dev, force=True) - new_ns = self.get_json()[0] + new_ns = self.run_ndctl_list()[0] self.log.info("Checking namespace changes") failed_vals = [] for key, val in new_ns.items(): @@ -515,7 +505,7 @@ def test_check_namespace(self): self.destroy_namespace() self.log.info("Creating sector namespace using %s", region) self.create_namespace(region=region, mode='sector') - ns_sec_dev = self.get_json_val(self.get_json()[0], 'dev') + ns_sec_dev = self.run_ndctl_list_val(self.run_ndctl_list()[0], 'dev') self.disable_namespace(namespace=ns_sec_dev) self.log.info("Checking BTT metadata") if process.system("%s check-namespace %s" % (self.binary, ns_sec_dev), @@ -524,13 +514,13 @@ def test_check_namespace(self): def test_check_numa(self): self.enable_region() - regions = self.get_json('-R') + regions = self.run_ndctl_list('-R') for val in regions: - reg = self.get_json_val(val, 'dev') + reg = self.run_ndctl_list_val(val, 'dev') numa = genio.read_one_line('/sys/devices/ndbus%s/%s/numa_node' % (re.findall(r'\d+', reg)[0], reg)) # Check numa config in ndctl and sys interface - if len(self.get_json('-r %s -U %s' % (reg, numa))) != 1: + if len(self.run_ndctl_list('-r %s -U %s' % (reg, numa))) != 1: self.fail('Region mismatch between ndctl and sys interface') def test_label_read_write(self): @@ -546,7 +536,8 @@ def test_label_read_write(self): self.enable_region(name=region) self.create_namespace(region=region) self.log.info("Storing labels with a namespace") - old_op = process.system_output('%s check-labels %s' % (self.binary, nmem), shell=True) + old_op = process.system_output( + '%s check-labels %s' % (self.binary, nmem), shell=True) if process.system('%s read-labels %s -o output' % (self.binary, nmem), shell=True): self.fail("Label read failed") @@ -563,12 +554,13 @@ def test_label_read_write(self): self.enable_region(name=region) self.log.info("Checking mismatch after restore") - new_op = process.system_output('%s check-labels %s' % (self.binary, nmem), shell=True) + new_op = process.system_output( + '%s check-labels %s' % (self.binary, nmem), shell=True) if new_op != old_op: self.fail("Label read and write mismatch") self.log.info("Checking created namespace after restore") - if len(self.get_json('-r %s' % region)) != 1: + if len(self.run_ndctl_list('-r %s' % region)) != 1: self.fail("Created namespace not found after label restore") def test_daxctl_list(self): @@ -593,9 +585,9 @@ def test_sector_write(self): self.disable_namespace(region=region) self.destroy_namespace(region=region) self.create_namespace(region=region, mode='sector', sector_size='512') - self.disk = '/dev/%s' % self.get_json_val( - self.get_json("-N -r %s" % region)[0], 'blockdev') - size = self.get_json_val(self.get_json( + self.disk = '/dev/%s' % self.run_ndctl_list_val( + self.run_ndctl_list("-N -r %s" % region)[0], 'blockdev') + size = self.run_ndctl_list_val(self.run_ndctl_list( "-N -r %s" % region)[0], 'size') self.part = partition.Partition(self.disk) self.part.mkfs(fstype='xfs', args='-b size=%s -s size=512' % @@ -617,9 +609,9 @@ def test_fsdax_write(self): """ region = self.get_default_region() self.create_namespace(region=region, mode='fsdax') - self.disk = '/dev/%s' % self.get_json_val( - self.get_json("-N -r %s" % region)[0], 'blockdev') - size = self.get_json_val(self.get_json( + self.disk = '/dev/%s' % self.run_ndctl_list_val( + self.run_ndctl_list("-N -r %s" % region)[0], 'blockdev') + size = self.run_ndctl_list_val(self.run_ndctl_list( "-N -r %s" % region)[0], 'size') self.part = partition.Partition(self.disk) self.part.mkfs(fstype='xfs', args='-b size=%s -s size=512 %s' % @@ -641,9 +633,10 @@ def test_devdax_write(self): """ region = self.get_default_region() self.create_namespace(region=region, mode='devdax') - daxdev = "/dev/%s" % self.get_json_val( - self.get_json("-N -r %s" % region)[0], 'chardev') - if process.system("%s -b no -i /dev/urandom -o %s" % (self.get_data("daxio.static"), daxdev), ignore_status=True): + daxdev = "/dev/%s" % self.run_ndctl_list_val( + self.run_ndctl_list("-N -r %s" % region)[0], 'chardev') + if process.system("%s -b no -i /dev/urandom " + "-o %s" % (self.get_data("daxio.static"), daxdev), ignore_status=True): self.fail("DAXIO write on devdax failed") def tearDown(self): @@ -656,7 +649,7 @@ def tearDown(self): self.fail("Failed to delete filesystem on %s" % self.disk) if not self.preserve_setup: - if len(self.get_json('-N')): + if self.run_ndctl_list('-N'): self.destroy_namespace(force=True) self.disable_region() diff --git a/memory/ndctl.py.data/ndctl.yaml b/memory/ndctl.py.data/ndctl.yaml index 1187055d8..521a3b46e 100644 --- a/memory/ndctl.py.data/ndctl.yaml +++ b/memory/ndctl.py.data/ndctl.yaml @@ -1,5 +1,4 @@ config: - namespace_cnt: 4 region: 'region0' preserve_change: True mnt_point: '/mnt/pmem' @@ -12,7 +11,5 @@ config: mode_types: !mux fsdax: modes: 'fsdax' - size: '1G' sector: modes: 'sector' - size: '300M'