/
githubmirror
/
ndctl
Обзор
Документация
Войти
/
githubmirror
/
ndctl
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v63
test/multi-pmem.c
296 строк
8 KB
Dan Williams
ndctl, test: reset all nfit_test data for each test/libndctl run
01 дек 2017, 02:04
01 дек 2017, 02:04
1eeca1e
Код
Авторство
О чём код?
/* * Copyright(c) 2015-2017 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ #include <stdio.h> #include <errno.h> #include <unistd.h> #include <stdlib.h> #include <syslog.h> #include <string.h> #include <sys/stat.h> #include <sys/mman.h> #include <sys/time.h> #include <libkmod.h> #include <uuid/uuid.h> #include <sys/types.h> #include <util/size.h> #include <linux/falloc.h> #include <linux/version.h> #include <ndctl/libndctl.h> #include <ccan/array_size/array_size.h> #include <ndctl.h> #include <builtin.h> #include <test.h> #define NUM_NAMESPACES 4 #define SZ_NAMESPACE SZ_16M static int setup_namespace(struct ndctl_region *region) { struct ndctl_ctx *ctx = ndctl_region_get_ctx(region); const char *argv[] = { "__func__", "-v", "-m", "raw", "-s", "16M", "-r", "", }; int argc = ARRAY_SIZE(argv); argv[argc - 1] = ndctl_region_get_devname(region); builtin_xaction_namespace_reset(); return cmd_create_namespace(argc, argv, ctx); } static void destroy_namespace(struct ndctl_namespace *ndns) { struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns); const char *argv[] = { "__func__", "-v", "-f", "", }; int argc = ARRAY_SIZE(argv); argv[argc - 1] = ndctl_namespace_get_devname(ndns); builtin_xaction_namespace_reset(); cmd_destroy_namespace(argc, argv, ctx); } /* Check that the namespace device is gone (if it wasn't the seed) */ static int check_deleted(struct ndctl_region *region, const char *devname, struct ndctl_test *test) { struct ndctl_namespace *ndns; if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 10, 0))) return 0; ndctl_namespace_foreach(region, ndns) { if (strcmp(devname, ndctl_namespace_get_devname(ndns))) continue; if (ndns == ndctl_region_get_namespace_seed(region)) continue; fprintf(stderr, "multi-pmem: expected %s to be deleted\n", devname); return -ENXIO; } return 0; } static int do_multi_pmem(struct ndctl_ctx *ctx, struct ndctl_test *test) { int i; char devname[100]; struct ndctl_bus *bus; uuid_t uuid[NUM_NAMESPACES]; struct ndctl_namespace *ndns; struct ndctl_dimm *dimm_target, *dimm; struct ndctl_region *region, *target = NULL; struct ndctl_namespace *namespaces[NUM_NAMESPACES]; unsigned long long blk_avail, blk_avail_orig, expect; if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 9, 0))) { ndctl_test_skip(test); return 77; } bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0"); if (!bus) return -ENXIO; /* disable all regions so that set_config_data commands are permitted */ ndctl_region_foreach(bus, region) ndctl_region_disable_invalidate(region); ndctl_dimm_foreach(bus, dimm) { int rc = ndctl_dimm_zero_labels(dimm); if (rc < 0) { fprintf(stderr, "failed to zero %s\n", ndctl_dimm_get_devname(dimm)); return rc; } } /* * Set regions back to their default state and find our target * region. */ ndctl_region_foreach(bus, region) { ndctl_region_enable(region); if (ndctl_region_get_available_size(region) == SZ_NAMESPACE * NUM_NAMESPACES) target = region; } if (!target) { fprintf(stderr, "multi-pmem: failed to find target region\n"); return -ENXIO; } region = target; for (i = 0; i < (int) ARRAY_SIZE(uuid); i++) { if (setup_namespace(region) != 0) { fprintf(stderr, "multi-pmem: failed to setup namespace: %d\n", i); return -ENXIO; } sprintf(devname, "namespace%d.%d", ndctl_region_get_id(region), i); ndctl_namespace_foreach(region, ndns) if (strcmp(ndctl_namespace_get_devname(ndns), devname) == 0 && ndctl_namespace_is_enabled(ndns)) break; if (!ndns) { fprintf(stderr, "multi-pmem: failed to find namespace: %s\n", devname); return -ENXIO; } ndctl_namespace_get_uuid(ndns, uuid[i]); } /* bounce the region and verify everything came back as expected */ ndctl_region_disable_invalidate(region); ndctl_region_enable(region); for (i = 0; i < (int) ARRAY_SIZE(uuid); i++) { char uuid_str1[40], uuid_str2[40]; uuid_t uuid_check; ndctl_namespace_foreach(region, ndns) sprintf(devname, "namespace%d.%d", ndctl_region_get_id(region), i); ndctl_namespace_foreach(region, ndns) if (strcmp(ndctl_namespace_get_devname(ndns), devname) == 0 && ndctl_namespace_is_enabled(ndns)) break; if (!ndns) { fprintf(stderr, "multi-pmem: failed to restore namespace: %s\n", devname); return -ENXIO; } ndctl_namespace_get_uuid(ndns, uuid_check); uuid_unparse(uuid_check, uuid_str2); uuid_unparse(uuid[i], uuid_str1); if (uuid_compare(uuid_check, uuid[i]) != 0) { fprintf(stderr, "multi-pmem: expected uuid[%d]: %s, got %s\n", i, uuid_str1, uuid_str2); return -ENXIO; } namespaces[i] = ndns; } /* * Check that aliased blk capacity does not increase until the * highest dpa pmem-namespace is deleted. */ dimm_target = ndctl_region_get_first_dimm(region); if (!dimm_target) { fprintf(stderr, "multi-pmem: failed to retrieve dimm from %s\n", ndctl_region_get_devname(region)); return -ENXIO; } dimm = NULL; ndctl_region_foreach(bus, region) { if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLK) continue; ndctl_dimm_foreach_in_region(region, dimm) if (dimm == dimm_target) break; if (dimm) break; } blk_avail_orig = ndctl_region_get_available_size(region); for (i = 1; i < NUM_NAMESPACES - 1; i++) { ndns = namespaces[i]; sprintf(devname, "%s", ndctl_namespace_get_devname(ndns)); destroy_namespace(ndns); blk_avail = ndctl_region_get_available_size(region); if (blk_avail != blk_avail_orig) { fprintf(stderr, "multi-pmem: destroy %s %llx avail, expect %llx\n", devname, blk_avail, blk_avail_orig); return -ENXIO; } if (check_deleted(target, devname, test) != 0) return -ENXIO; } ndns = namespaces[NUM_NAMESPACES - 1]; sprintf(devname, "%s", ndctl_namespace_get_devname(ndns)); destroy_namespace(ndns); blk_avail = ndctl_region_get_available_size(region); expect = (SZ_NAMESPACE / ndctl_region_get_interleave_ways(target)) * (NUM_NAMESPACES - 1) + blk_avail_orig; if (blk_avail != expect) { fprintf(stderr, "multi-pmem: destroy %s %llx avail, expect %llx\n", devname, blk_avail, expect); return -ENXIO; } if (check_deleted(target, devname, test) != 0) return -ENXIO; ndctl_bus_foreach(ctx, bus) { if (strncmp(ndctl_bus_get_provider(bus), "nfit_test", 9) != 0) continue; ndctl_region_foreach(bus, region) ndctl_region_disable_invalidate(region); } return 0; } int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx) { struct kmod_module *mod; struct kmod_ctx *kmod_ctx; int err, result = EXIT_FAILURE; if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 2, 0))) return 77; ndctl_set_log_priority(ctx, loglevel); err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test); if (err < 0) { result = 77; ndctl_test_skip(test); fprintf(stderr, "%s unavailable skipping tests\n", "nfit_test"); return result; } result = do_multi_pmem(ctx, test); kmod_module_remove_module(mod, 0); kmod_unref(kmod_ctx); return result; } int __attribute__((weak)) main(int argc, char *argv[]) { struct ndctl_test *test = ndctl_test_new(0); struct ndctl_ctx *ctx; int rc; if (!test) { fprintf(stderr, "failed to initialize test\n"); return EXIT_FAILURE; } rc = ndctl_new(&ctx); if (rc) return ndctl_test_result(test, rc); rc = test_multi_pmem(LOG_DEBUG, test, ctx); ndctl_unref(ctx); return ndctl_test_result(test, rc); }