diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 4acebc05d6db..e0b49615aa88 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -268,6 +268,7 @@ struct ndctl_namespace {
 	int type, id, buf_len, raw_mode;
 	int generation;
 	unsigned long long resource, size;
+	enum ndctl_namespace_mode enforce_mode;
 	char *alt_name;
 	uuid_t uuid;
 	struct ndctl_lbasize lbasize;
@@ -2858,6 +2859,31 @@ static char *get_block_device(struct ndctl_ctx *ctx, const char *block_path)
 static int parse_lbasize_supported(struct ndctl_ctx *ctx, const char *devname,
 		const char *buf, struct ndctl_lbasize *lba);
 
+static const char *enforce_id_to_name(enum ndctl_namespace_mode mode)
+{
+	static const char *id_to_name[] = {
+		[NDCTL_NS_MODE_MEMORY] = "pfn",
+		[NDCTL_NS_MODE_SAFE] = "btt", /* TODO: convert to btt2 */
+		[NDCTL_NS_MODE_RAW] = "",
+		[NDCTL_NS_MODE_DAX] = "dax",
+		[NDCTL_NS_MODE_UNKNOWN] = "<unknown>",
+	};
+
+	if (mode < NDCTL_NS_MODE_UNKNOWN && mode >= 0)
+		return id_to_name[mode];
+	return id_to_name[NDCTL_NS_MODE_UNKNOWN];
+}
+
+static enum ndctl_namespace_mode enforce_name_to_id(const char *name)
+{
+	int i;
+
+	for (i = 0; i < NDCTL_NS_MODE_UNKNOWN; i++)
+		if (strcmp(enforce_id_to_name(i), name) == 0)
+			return i;
+	return NDCTL_NS_MODE_UNKNOWN;
+}
+
 static void *add_namespace(void *parent, int id, const char *ndns_base)
 {
 	const char *devname = devpath_to_devname(ndns_base);
@@ -2903,6 +2929,10 @@ static void *add_namespace(void *parent, int id, const char *ndns_base)
 	if (sysfs_read_attr(ctx, path, buf) == 0)
 		ndns->numa_node = strtol(buf, NULL, 0);
 
+	sprintf(path, "%s/holder_class", ndns_base);
+	if (sysfs_read_attr(ctx, path, buf) == 0)
+		ndns->enforce_mode = enforce_name_to_id(buf);
+
 	switch (ndns->type) {
 	case ND_DEVICE_NAMESPACE_BLK:
 		sprintf(path, "%s/sector_size", ndns_base);
@@ -3150,6 +3180,35 @@ NDCTL_EXPORT enum ndctl_namespace_mode ndctl_namespace_get_mode(
 	return -ENXIO;
 }
 
+NDCTL_EXPORT enum ndctl_namespace_mode ndctl_namespace_get_enforce_mode(
+		struct ndctl_namespace *ndns)
+{
+	return ndns->enforce_mode;
+}
+
+NDCTL_EXPORT int ndctl_namespace_set_enforce_mode(struct ndctl_namespace *ndns,
+		enum ndctl_namespace_mode mode)
+{
+	struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
+	char *path = ndns->ndns_buf;
+	int len = ndns->buf_len;
+	int rc;
+
+	if (mode < 0 || mode >= NDCTL_NS_MODE_UNKNOWN)
+		return -EINVAL;
+
+	if (snprintf(path, len, "%s/holder_class", ndns->ndns_path) >= len) {
+		err(ctx, "%s: buffer too small!\n",
+				ndctl_namespace_get_devname(ndns));
+		return -ENOMEM;
+	}
+
+	rc = sysfs_write_attr(ctx, path, enforce_id_to_name(mode));
+	if (rc >= 0)
+		ndns->enforce_mode = mode;
+	return rc;
+}
+
 NDCTL_EXPORT int ndctl_namespace_is_valid(struct ndctl_namespace *ndns)
 {
 	struct ndctl_region *region = ndctl_namespace_get_region(ndns);
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 9bc36a37a813..0e592435ff70 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -169,6 +169,8 @@ global:
 	ndctl_namespace_get_devname;
 	ndctl_namespace_get_block_device;
 	ndctl_namespace_get_mode;
+	ndctl_namespace_set_enforce_mode;
+	ndctl_namespace_get_enforce_mode;
 	ndctl_region_get_nstype;
 	ndctl_namespace_get_type;
 	ndctl_namespace_get_type_name;
diff --git a/ndctl/libndctl.h.in b/ndctl/libndctl.h.in
index 2c45d2daa81b..3943ad240062 100644
--- a/ndctl/libndctl.h.in
+++ b/ndctl/libndctl.h.in
@@ -489,10 +489,14 @@ enum ndctl_namespace_mode {
 	NDCTL_NS_MODE_SAFE,
 	NDCTL_NS_MODE_RAW,
 	NDCTL_NS_MODE_DAX,
-	NDCTL_NS_MODE_UNKNOWN,
+	NDCTL_NS_MODE_UNKNOWN, /* must be last entry */
 };
 enum ndctl_namespace_mode ndctl_namespace_get_mode(
 		struct ndctl_namespace *ndns);
+enum ndctl_namespace_mode ndctl_namespace_get_enforce_mode(
+		struct ndctl_namespace *ndns);
+int ndctl_namespace_set_enforce_mode(struct ndctl_namespace *ndns,
+		enum ndctl_namespace_mode mode);
 int ndctl_namespace_is_enabled(struct ndctl_namespace *ndns);
 int ndctl_namespace_enable(struct ndctl_namespace *ndns);
 int ndctl_namespace_disable(struct ndctl_namespace *ndns);
@@ -520,7 +524,6 @@ int ndctl_namespace_set_sector_size(struct ndctl_namespace *ndns,
 int ndctl_namespace_get_raw_mode(struct ndctl_namespace *ndns);
 int ndctl_namespace_set_raw_mode(struct ndctl_namespace *ndns, int raw_mode);
 int ndctl_namespace_get_numa_node(struct ndctl_namespace *ndns);
-
 struct ndctl_btt;
 struct ndctl_btt *ndctl_btt_get_first(struct ndctl_region *region);
 struct ndctl_btt *ndctl_btt_get_next(struct ndctl_btt *btt);
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index 895e39bb8c7d..8f264c348f51 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -360,6 +360,15 @@ static int setup_namespace(struct ndctl_region *region,
 		try(ndctl_namespace, set_sector_size, ndns, p->sector_size);
 
 	uuid_generate(uuid);
+
+	/*
+	 * Note, this call to ndctl_namespace_set_mode() is not error
+	 * checked since kernels older than 4.13 do not support this
+	 * property of namespaces and it is an opportunistic enforcement
+	 * mechanism.
+	 */
+	ndctl_namespace_set_enforce_mode(ndns, p->mode);
+
 	if (do_setup_pfn(ndns, p)) {
 		struct ndctl_pfn *pfn = ndctl_region_get_pfn_seed(region);
 
@@ -780,6 +789,8 @@ static int namespace_destroy(struct ndctl_region *region,
 			return rc;
 	}
 
+	ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_RAW);
+
 	if (pfn || btt || dax) {
 		rc = zero_info_block(ndns);
 		if (rc)
diff --git a/test/libndctl.c b/test/libndctl.c
index 0381ee2cdefb..24aff36fef62 100644
--- a/test/libndctl.c
+++ b/test/libndctl.c
@@ -736,6 +736,8 @@ static int __check_dax_create(struct ndctl_region *region,
 		enum ndctl_pfn_loc loc, uuid_t uuid)
 {
 	struct ndctl_dax *dax_seed = ndctl_region_get_dax_seed(region);
+	struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
+	struct ndctl_test *test = ndctl_get_private_data(ctx);
 	enum ndctl_namespace_mode mode;
 	struct ndctl_dax *dax;
 	const char *devname;
@@ -753,6 +755,12 @@ static int __check_dax_create(struct ndctl_region *region,
 	 * alignment is PAGE_SIZE
 	 */
 	ndctl_dax_set_align(dax, SZ_4K);
+
+	rc = ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_DAX);
+	if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0)) && rc < 0) {
+		fprintf(stderr, "%s: failed to enforce dax mode\n", devname);
+		return rc;
+	}
 	ndctl_dax_set_namespace(dax, ndns);
 	rc = ndctl_dax_enable(dax);
 	if (rc) {
@@ -838,6 +846,8 @@ static int __check_pfn_create(struct ndctl_region *region,
 		void *buf, enum ndctl_pfn_loc loc, uuid_t uuid)
 {
 	struct ndctl_pfn *pfn_seed = ndctl_region_get_pfn_seed(region);
+	struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
+	struct ndctl_test *test = ndctl_get_private_data(ctx);
 	enum ndctl_namespace_mode mode;
 	struct ndctl_pfn *pfn;
 	const char *devname;
@@ -857,6 +867,11 @@ static int __check_pfn_create(struct ndctl_region *region,
 	 * alignment is PAGE_SIZE
 	 */
 	ndctl_pfn_set_align(pfn, SZ_4K);
+	rc = ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_MEMORY);
+	if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0)) && rc < 0) {
+		fprintf(stderr, "%s: failed to enforce pfn mode\n", devname);
+		return rc;
+	}
 	ndctl_pfn_set_namespace(pfn, ndns);
 	rc = ndctl_pfn_enable(pfn);
 	if (rc) {
@@ -1067,6 +1082,12 @@ static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace
 		devname = ndctl_btt_get_devname(btt);
 		ndctl_btt_set_uuid(btt, btt_s->uuid);
 		ndctl_btt_set_sector_size(btt, btt_s->sector_sizes[i]);
+		rc = ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_SAFE);
+		if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0)) && rc < 0) {
+			fprintf(stderr, "%s: failed to enforce btt mode\n", devname);
+			goto err;
+		}
+
 		ndctl_btt_set_namespace(btt, ndns);
 		rc = ndctl_btt_enable(btt);
 		if (namespace->ro == (rc == 0)) {
@@ -1237,9 +1258,12 @@ static int check_pfn_autodetect(struct ndctl_bus *bus,
 		struct namespace *namespace)
 {
 	struct ndctl_region *region = ndctl_namespace_get_region(ndns);
+	struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
 	const char *devname = ndctl_namespace_get_devname(ndns);
+	struct ndctl_test *test = ndctl_get_private_data(ctx);
 	struct pfn *auto_pfn = namespace->pfn_settings;
 	struct ndctl_pfn *pfn, *found = NULL;
+	enum ndctl_namespace_mode mode;
 	ssize_t rc = -ENXIO;
 	char bdev[50];
 	int fd, ro;
@@ -1265,6 +1289,13 @@ static int check_pfn_autodetect(struct ndctl_bus *bus,
 	if (!found)
 		return -ENXIO;
 
+	mode = ndctl_namespace_get_enforce_mode(ndns);
+	if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0))
+			&& mode != NDCTL_NS_MODE_MEMORY) {
+		fprintf(stderr, "%s expected enforce_mode pfn\n", devname);
+		return -ENXIO;
+	}
+
 	sprintf(bdev, "/dev/%s", ndctl_pfn_get_block_device(pfn));
 	fd = open(bdev, O_RDONLY);
 	if (fd < 0)
@@ -1324,9 +1355,12 @@ static int check_dax_autodetect(struct ndctl_bus *bus,
 		struct namespace *namespace)
 {
 	struct ndctl_region *region = ndctl_namespace_get_region(ndns);
+	struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
 	const char *devname = ndctl_namespace_get_devname(ndns);
+	struct ndctl_test *test = ndctl_get_private_data(ctx);
 	struct dax *auto_dax = namespace->dax_settings;
 	struct ndctl_dax *dax, *found = NULL;
+	enum ndctl_namespace_mode mode;
 	ssize_t rc = -ENXIO;
 	char bdev[50];
 	int fd;
@@ -1352,6 +1386,13 @@ static int check_dax_autodetect(struct ndctl_bus *bus,
 	if (!found)
 		return -ENXIO;
 
+	mode = ndctl_namespace_get_enforce_mode(ndns);
+	if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0))
+			&& mode != NDCTL_NS_MODE_DAX) {
+		fprintf(stderr, "%s expected enforce_mode dax\n", devname);
+		return -ENXIO;
+	}
+
 	rc = validate_dax(dax);
 	if (rc) {
 		fprintf(stderr, "%s: %s validate_dax failed\n", __func__,
@@ -1399,9 +1440,12 @@ static int check_btt_autodetect(struct ndctl_bus *bus,
 		struct namespace *namespace)
 {
 	struct ndctl_region *region = ndctl_namespace_get_region(ndns);
+	struct ndctl_ctx *ctx = ndctl_region_get_ctx(region);
 	const char *devname = ndctl_namespace_get_devname(ndns);
+	struct ndctl_test *test = ndctl_get_private_data(ctx);
 	struct btt *auto_btt = namespace->btt_settings;
 	struct ndctl_btt *btt, *found = NULL;
+	enum ndctl_namespace_mode mode;
 	ssize_t rc = -ENXIO;
 	char bdev[50];
 	int fd, ro;
@@ -1427,6 +1471,13 @@ static int check_btt_autodetect(struct ndctl_bus *bus,
 	if (!found)
 		return -ENXIO;
 
+	mode = ndctl_namespace_get_enforce_mode(ndns);
+	if (ndctl_test_attempt(test, KERNEL_VERSION(4, 13, 0))
+			&& mode != NDCTL_NS_MODE_SAFE) {
+		fprintf(stderr, "%s expected enforce_mode btt\n", devname);
+		return -ENXIO;
+	}
+
 	sprintf(bdev, "/dev/%s", ndctl_btt_get_block_device(btt));
 	fd = open(bdev, O_RDONLY);
 	if (fd < 0)
