diff --git a/lib/libnv/nv.3 b/lib/libnv/nv.3 index 4c0e236b090a..58033be61fed 100644 --- a/lib/libnv/nv.3 +++ b/lib/libnv/nv.3 @@ -232,6 +232,8 @@ The following flag can be provided: .Bl -tag -width "NV_FLAG_IGNORE_CASE" -compact -offset indent .It Dv NV_FLAG_IGNORE_CASE Perform case-insensitive lookups of provided names. +.It Dv NV_FLAG_NO_UNIQUE +Names in the nvlist do not have to be unique. .El .Pp The diff --git a/sys/kern/subr_nvlist.c b/sys/kern/subr_nvlist.c index ec4471866226..4528a359df45 100644 --- a/sys/kern/subr_nvlist.c +++ b/sys/kern/subr_nvlist.c @@ -88,7 +88,7 @@ __FBSDID("$FreeBSD$"); #endif #define NV_FLAG_PRIVATE_MASK (NV_FLAG_BIG_ENDIAN) -#define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE) +#define NV_FLAG_PUBLIC_MASK (NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE) #define NV_FLAG_ALL_MASK (NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK) #define NVLIST_MAGIC 0x6e766c /* "nvl" */ @@ -1074,10 +1074,12 @@ nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) ERRNO_SET(nvlist_error(nvl)); return; } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvl->nvl_error = EEXIST; - ERRNO_SET(nvlist_error(nvl)); - return; + if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { + if (nvlist_exists(nvl, nvpair_name(nvp))) { + nvl->nvl_error = EEXIST; + ERRNO_SET(nvlist_error(nvl)); + return; + } } newnvp = nvpair_clone(nvp); @@ -1266,11 +1268,13 @@ nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) ERRNO_SET(nvlist_error(nvl)); return; } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvpair_free(nvp); - nvl->nvl_error = EEXIST; - ERRNO_SET(nvl->nvl_error); - return; + if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) { + if (nvlist_exists(nvl, nvpair_name(nvp))) { + nvpair_free(nvp); + nvl->nvl_error = EEXIST; + ERRNO_SET(nvl->nvl_error); + return; + } } nvpair_insert(&nvl->nvl_head, nvp, nvl); diff --git a/sys/kern/subr_nvpair.c b/sys/kern/subr_nvpair.c index 153dcda76c56..cde08e6004c9 100644 --- a/sys/kern/subr_nvpair.c +++ b/sys/kern/subr_nvpair.c @@ -143,7 +143,8 @@ nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl) NVPAIR_ASSERT(nvp); PJDLOG_ASSERT(nvp->nvp_list == NULL); - PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp))); + PJDLOG_ASSERT((nvlist_flags(nvl) & NV_FLAG_NO_UNIQUE) != 0 || + !nvlist_exists(nvl, nvpair_name(nvp))); TAILQ_INSERT_TAIL(head, nvp, nvp_next); nvp->nvp_list = nvl; diff --git a/sys/sys/nv.h b/sys/sys/nv.h index 4a339ecbfa49..fa5d1385eaf6 100644 --- a/sys/sys/nv.h +++ b/sys/sys/nv.h @@ -64,6 +64,10 @@ typedef struct nvlist nvlist_t; * Perform case-insensitive lookups of provided names. */ #define NV_FLAG_IGNORE_CASE 0x01 +/* + * Names don't have to be unique. + */ +#define NV_FLAG_NO_UNIQUE 0x02 #if defined(_KERNEL) && defined(MALLOC_DECLARE) MALLOC_DECLARE(M_NVLIST);