static int emit_e820_device(int loglevel, struct ndctl_test *test) { int err, fd; char path[256]; const char *bdev; struct ndctl_ctx *ctx; struct ndctl_bus *bus; struct ndctl_region *region; struct ndctl_namespace *ndns; enum ndctl_namespace_mode mode; if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 3, 0))) return 77; err = ndctl_new(&ctx); if (err < 0) return err; ndctl_set_log_priority(ctx, loglevel); err = -ENXIO; bus = ndctl_bus_get_by_provider(ctx, "e820"); if (!bus) goto out; region = ndctl_region_get_first(bus); if (!region) goto out; ndns = ndctl_namespace_get_first(region); if (!ndns) goto out; mode = ndctl_namespace_get_mode(ndns); if (mode >= 0 && mode != NDCTL_NS_MODE_MEMORY) goto out; bdev = ndctl_namespace_get_block_device(ndns); if (!bdev) goto out; if (snprintf(path, sizeof(path), "/dev/%s", bdev) >= (int) sizeof(path)) goto out; /* * Note, if the bdev goes active after this check we'll still * clobber it in the following tests, see test/dax.sh. */ fd = open(path, O_RDWR | O_EXCL); if (fd < 0) goto out; err = 0; fprintf(stdout, "%s\n", path); out: if (err) fprintf(stderr, "%s: failed to find usable victim device\n", __func__); ndctl_unref(ctx); return err; }
int test_parent_uuid(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, 3, 0))) return 77; err = ndctl_new(&ctx); if (err < 0) exit(EXIT_FAILURE); ndctl_set_log_priority(ctx, loglevel); kmod_ctx = kmod_new(NULL, NULL); if (!kmod_ctx) goto err_kmod; err = kmod_module_new_from_name(kmod_ctx, NFIT_TEST_MODULE, &mod); if (err < 0) goto err_module; err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); if (err < 0) { result = 77; ndctl_test_skip(test); fprintf(stderr, "%s unavailable skipping tests\n", NFIT_TEST_MODULE); goto err_module; } err = do_test(ctx); if (err == 0) result = EXIT_SUCCESS; kmod_module_remove_module(mod, 0); err_module: kmod_unref(kmod_ctx); err_kmod: ndctl_unref(ctx); return result; }
static int emit_e820_device(int loglevel, struct ndctl_test *test) { int err, fd; char path[256]; const char *bdev; struct ndctl_ctx *ctx; struct ndctl_bus *bus; struct ndctl_dax *dax; struct ndctl_pfn *pfn; struct ndctl_region *region; struct ndctl_namespace *ndns; enum ndctl_namespace_mode mode; if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 3, 0))) return 77; err = ndctl_new(&ctx); if (err < 0) return err; ndctl_set_log_priority(ctx, loglevel); err = -ENXIO; bus = ndctl_bus_get_by_provider(ctx, "e820"); if (!bus) goto out; region = ndctl_region_get_first(bus); if (!region) goto out; ndns = ndctl_namespace_get_first(region); if (!ndns) goto out; mode = ndctl_namespace_get_mode(ndns); if (mode >= 0 && mode != NDCTL_NS_MODE_MEMORY) goto out; /* if device-dax mode already established it might contain user data */ pfn = ndctl_namespace_get_pfn(ndns); dax = ndctl_namespace_get_dax(ndns); if (dax || pfn) goto out; /* device is unconfigured, assume that was on purpose */ bdev = ndctl_namespace_get_block_device(ndns); if (!bdev) goto out; if (snprintf(path, sizeof(path), "/dev/%s", bdev) >= (int) sizeof(path)) goto out; /* * Note, if the bdev goes active after this check we'll still * clobber it in the following tests, see test/dax.sh and * test/device-dax.sh. */ fd = open(path, O_RDWR | O_EXCL); if (fd < 0) goto out; err = 0; out: if (err) { fprintf(stderr, "%s: failed to find usable victim device\n", __func__); ndctl_test_skip(test); err = 77; } else fprintf(stdout, "%s\n", ndctl_namespace_get_devname(ndns)); ndctl_unref(ctx); return err; }
int test_pmem_namespaces(int log_level, struct ndctl_test *test) { struct ndctl_region *region, *pmem_region = NULL; struct kmod_ctx *kmod_ctx = NULL; struct kmod_module *mod = NULL; struct ndctl_namespace *ndns; struct ndctl_dimm *dimm; struct ndctl_ctx *ctx; struct ndctl_bus *bus; char bdev[50]; int rc; if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 2, 0))) return 77; rc = ndctl_new(&ctx); if (rc < 0) return rc; ndctl_set_log_priority(ctx, log_level); bus = ndctl_bus_get_by_provider(ctx, "ACPI.NFIT"); if (!bus) { fprintf(stderr, "ACPI.NFIT unavailable falling back to nfit_test\n"); kmod_ctx = kmod_new(NULL, NULL); if (!kmod_ctx) goto err_kmod; kmod_set_log_priority(kmod_ctx, log_level); rc = kmod_module_new_from_name(kmod_ctx, "nfit_test", &mod); if (rc < 0) goto err_module; rc = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); ndctl_invalidate(ctx); bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0"); if (rc < 0 || !bus) { rc = 77; ndctl_test_skip(test); fprintf(stderr, "nfit_test unavailable skipping tests\n"); goto err_module; } } fprintf(stderr, "%s: found provider: %s\n", comm, ndctl_bus_get_provider(bus)); /* get the system to a clean state */ ndctl_region_foreach(bus, region) ndctl_region_disable_invalidate(region); ndctl_dimm_foreach(bus, dimm) { rc = ndctl_dimm_zero_labels(dimm); if (rc < 0) { fprintf(stderr, "failed to zero %s\n", ndctl_dimm_get_devname(dimm)); goto err; } }
int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align, void *dax_addr, off_t offset, bool fsdax) { unsigned char *addr = MAP_FAILED; struct sigaction act; unsigned x = x; void *buf; int rc; if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 19, 0))) return 77; /* * MADV_HWPOISON must be page aligned, and this routine assumes * align is >= 8K */ if (align < SZ_2M) return 0; if (posix_memalign(&buf, 4096, 4096) != 0) return -ENOMEM; memset(&act, 0, sizeof(act)); act.sa_sigaction = sigbus_hdl; act.sa_flags = SA_SIGINFO; if (sigaction(SIGBUS, &act, 0)) { fail(); rc = -errno; goto out; } /* dirty the block on disk to bypass the default zero page */ if (fsdax) { rc = pwrite(dax_fd, buf, 4096, offset + align / 2); if (rc < 4096) { fail(); rc = -ENXIO; goto out; } fsync(dax_fd); } addr = mmap(dax_addr, 2*align, PROT_READ|PROT_WRITE, MAP_SHARED_VALIDATE|MAP_POPULATE|MAP_SYNC, dax_fd, offset); if (addr == MAP_FAILED) { fail(); rc = -errno; goto out; } if (sigsetjmp(sj_env, 1)) { if (sig_mcerr_ar) { fprintf(stderr, "madvise triggered 'action required' sigbus\n"); goto clear_error; } else if (sig_count) { fail(); return -ENXIO; } } rc = madvise(addr + align / 2, 4096, MADV_HWPOISON); if (rc) { fail(); rc = -errno; goto out; } /* clear the error */ clear_error: if (!sig_mcerr_ar) { fail(); rc = -ENXIO; goto out; } if (!fsdax) { rc = 0; goto out; } rc = fallocate(dax_fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset + align / 2, 4096); if (rc) { fail(); rc = -errno; goto out; } rc = pwrite(dax_fd, buf, 4096, offset + align / 2); if (rc < 4096) { fail(); rc = -ENXIO; goto out; } fsync(dax_fd); /* check that we can fault in the poison page */ x = *(volatile unsigned *) addr + align / 2; rc = 0; out: if (addr != MAP_FAILED) munmap(addr, 2 * align); free(buf); return rc; }