diff options
Diffstat (limited to 'sys/contrib/libnv')
-rw-r--r-- | sys/contrib/libnv/nvlist.c | 124 |
1 files changed, 53 insertions, 71 deletions
diff --git a/sys/contrib/libnv/nvlist.c b/sys/contrib/libnv/nvlist.c index 311325d822ce..31ab62abeb67 100644 --- a/sys/contrib/libnv/nvlist.c +++ b/sys/contrib/libnv/nvlist.c @@ -99,6 +99,7 @@ struct nvlist { int nvl_magic; int nvl_error; int nvl_flags; + size_t nvl_datasize; nvpair_t *nvl_parent; nvpair_t *nvl_array_next; struct nvl_head nvl_head; @@ -139,6 +140,7 @@ nvlist_create(int flags) nvl->nvl_flags = flags; nvl->nvl_parent = NULL; nvl->nvl_array_next = NULL; + nvl->nvl_datasize = sizeof(struct nvlist_header); TAILQ_INIT(&nvl->nvl_head); nvl->nvl_magic = NVLIST_MAGIC; @@ -247,6 +249,51 @@ nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele) nvl->nvl_array_next = ele; } +static void +nvlist_update_size(nvlist_t *nvl, nvpair_t *new, ssize_t mul) +{ + ssize_t size; + size_t nitems; + const nvlist_t *nvlistnew; + const nvlist_t * const *nvlarray; + nvlist_t *parent; + unsigned int ii; + + NVLIST_ASSERT(nvl); + NVPAIR_ASSERT(new); + PJDLOG_ASSERT(mul == 1 || mul == -1); + + size = nvpair_header_size(); + size += strlen(nvpair_name(new)) + 1; + + if (nvpair_type(new) == NV_TYPE_NVLIST) { + nvlistnew = nvpair_get_nvlist(new); + size += nvlistnew->nvl_datasize; + size += nvpair_header_size() + 1; + } else if (nvpair_type(new) == NV_TYPE_NVLIST_ARRAY) { + nvlarray = nvpair_get_nvlist_array(new, &nitems); + PJDLOG_ASSERT(nitems > 0); + + size += (nvpair_header_size() + 1) * nitems; + for (ii = 0; ii < nitems; ii++) { + PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0); + size += nvlarray[ii]->nvl_datasize; + } + } else { + size += nvpair_size(new); + } + + size *= mul; + + nvl->nvl_datasize += size; + + parent = nvl; + while ((parent = __DECONST(nvlist_t *, + nvlist_get_parent(parent, NULL))) != NULL) { + parent->nvl_datasize += size; + } +} + nvpair_t * nvlist_get_array_next_nvpair(nvlist_t *nvl) { @@ -640,78 +687,8 @@ nvlist_fdump(const nvlist_t *nvl, FILE *fp) size_t nvlist_size(const nvlist_t *nvl) { - const nvlist_t *tmpnvl; - const nvlist_t * const *nvlarray; - const nvpair_t *nvp, *tmpnvp; - void *cookie; - size_t size, nitems; - unsigned int ii; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - size = sizeof(struct nvlist_header); - nvp = nvlist_first_nvpair(nvl); - while (nvp != NULL) { - size += nvpair_header_size(); - size += strlen(nvpair_name(nvp)) + 1; - if (nvpair_type(nvp) == NV_TYPE_NVLIST) { - size += sizeof(struct nvlist_header); - size += nvpair_header_size() + 1; - tmpnvl = nvpair_get_nvlist(nvp); - PJDLOG_ASSERT(tmpnvl->nvl_error == 0); - tmpnvp = nvlist_first_nvpair(tmpnvl); - if (tmpnvp != NULL) { - nvl = tmpnvl; - nvp = tmpnvp; - continue; - } - } else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) { - nvlarray = nvpair_get_nvlist_array(nvp, &nitems); - PJDLOG_ASSERT(nitems > 0); - - size += (nvpair_header_size() + 1) * nitems; - size += sizeof(struct nvlist_header) * nitems; - - tmpnvl = NULL; - tmpnvp = NULL; - for (ii = 0; ii < nitems; ii++) { - PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0); - tmpnvp = nvlist_first_nvpair(nvlarray[ii]); - if (tmpnvp != NULL) { - tmpnvl = nvlarray[ii]; - break; - } - } - if (tmpnvp != NULL) { - nvp = tmpnvp; - nvl = tmpnvl; - continue; - } - - } else { - size += nvpair_size(nvp); - } - - while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) { - do { - cookie = NULL; - nvl = nvlist_get_pararr(nvl, &cookie); - if (nvl == NULL) - goto out; - if (nvlist_in_array(nvl) && cookie == NULL) { - nvp = nvlist_first_nvpair(nvl); - } else { - nvp = cookie; - } - } while (nvp == NULL); - if (nvlist_in_array(nvl) && cookie == NULL) - break; - } - } - -out: - return (size); + return (nvl->nvl_datasize); } #ifndef _KERNEL @@ -1483,6 +1460,7 @@ nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) } nvpair_insert(&nvl->nvl_head, newnvp, nvl); + nvlist_update_size(nvl, newnvp, 1); } void @@ -1631,10 +1609,12 @@ nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\ nvlist_add_##type##_array(nvl, name, &value, 1); \ return; \ } \ + nvlist_update_size(nvl, nvp, -1); \ if (nvpair_append_##type##_array(nvp, value) == -1) { \ nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM); \ ERRNO_SET(nvl->nvl_error); \ } \ + nvlist_update_size(nvl, nvp, 1); \ } NVLIST_APPEND_ARRAY(const bool, bool, BOOL) @@ -1669,6 +1649,7 @@ nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp) } nvpair_insert(&nvl->nvl_head, nvp, nvl); + nvlist_update_size(nvl, nvp, 1); return (true); } @@ -2020,6 +2001,7 @@ nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp) PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl); nvpair_remove(&nvl->nvl_head, nvp, nvl); + nvlist_update_size(nvl, nvp, -1); } void |