*** Imports
***/
+/* Add -DDNS_SLABHEADER_TRACE=1 to CFLAGS for detailed reference tracing */
+
#include <stdalign.h>
#include <stdbool.h>
_Atomic(uint16_t) attributes;
_Atomic(dns_trust_t) trust;
+ isc_refcount_t references;
+
/*%
* Locked by the owning node's lock.
*/
alignas(sizeof(void *)) unsigned char raw[];
};
+#if DNS_SLABHEADER_TRACE
+#define dns_slabheader_ref(ptr) \
+ dns_slabheader__ref(ptr, __func__, __FILE__, __LINE__)
+#define dns_slabheader_unref(ptr) \
+ dns_slabheader__unref(ptr, __func__, __FILE__, __LINE__)
+#define dns_slabheader_attach(ptr, ptrp) \
+ dns_slabheader__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
+#define dns_slabheader_detach(ptrp) \
+ dns_slabheader__detach(ptrp, __func__, __FILE__, __LINE__)
+ISC_REFCOUNT_TRACE_DECL(dns_slabheader);
+#else
+ISC_REFCOUNT_DECL(dns_slabheader);
+#endif
+
enum {
DNS_SLABHEADERATTR_NONEXISTENT = 1 << 0,
DNS_SLABHEADERATTR_STALE = 1 << 1,
*** Functions
***/
+#define dns_rdataslab_fromrdataset(rdataset, mctx, region, limit) \
+ dns_rdataslab__fromrdataset(rdataset, mctx, region, limit, __func__, \
+ __FILE__, __LINE__)
isc_result_t
-dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
- isc_region_t *region, uint32_t limit);
+dns_rdataslab__fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
+ isc_region_t *region, uint32_t limit,
+ const char *func, const char *file,
+ const unsigned int line);
/*%<
* Allocate space for a slab to hold the data in rdataset, and copy the
* data into it. The resulting slab will be returned in 'region'.
*\li true if the slabs are equal, #false otherwise.
*/
+#define dns_slabheader_reset(header, node) \
+ dns_slabheader__reset(header, node, __func__, __FILE__, __LINE__)
void
-dns_slabheader_reset(dns_slabheader_t *h, dns_dbnode_t *node);
+dns_slabheader__reset(dns_slabheader_t *h, dns_dbnode_t *node, const char *func,
+ const char *file, const unsigned int line);
/*%<
* Reset an rdataslab header 'h' so it can be used to store data in
* database node 'node'.
*/
+#define dns_slabheader_new(mctx, node) \
+ dns_slabheader__new(mctx, node, __func__, __FILE__, __LINE__)
dns_slabheader_t *
-dns_slabheader_new(isc_mem_t *mctx, dns_dbnode_t *node);
+dns_slabheader__new(isc_mem_t *mctx, dns_dbnode_t *node, const char *func,
+ const char *file, const unsigned int line);
/*%<
* Allocate memory for an rdataslab header and initialize it for use
* in database node 'node'.
*/
-void
-dns_slabheader_destroy(dns_slabheader_t **headerp);
-/*%<
- * Free all memory associated with '*headerp'.
- */
-
void
dns_slabheader_freeproof(isc_mem_t *mctx, dns_slabheader_proof_t **proof);
/*%<
cds_list_for_each_entry_safe_from(header, header_next, &top->headers,
headers_link) {
cds_list_del(&header->headers_link);
- dns_slabheader_destroy(&header);
+ dns_slabheader_detach(&header);
}
}
(STALE(header) && !KEEPSTALE(qpdb)))
{
cds_list_del(&header->headers_link);
- dns_slabheader_destroy(&header);
+ dns_slabheader_detach(&header);
}
/*
return;
}
+ dns_slabheader_ref(header);
+
qpcnode_acquire(qpdb, node, nlocktype, tlocktype DNS__DB_FLARG_PASS);
INSIST(rdataset->methods == NULL); /* We must be disassociated. */
update_rrsetstats(qpdb->rrsetstats, newheader->typepair,
newheader->attributes, true);
} else {
- dns_slabheader_destroy(&newheader);
+ dns_slabheader_detach(&newheader);
}
NODE_UNLOCK(nlock, &nlocktype);
return result;
cleanup:
- dns_slabheader_destroy(&newheader);
+ dns_slabheader_detach(&newheader);
return result;
}
result = add(qpdb, qpnode, newheader, DNS_DBADD_FORCE, NULL, 0,
nlocktype, isc_rwlocktype_none DNS__DB_FLARG_PASS);
if (result != ISC_R_SUCCESS) {
- dns_slabheader_destroy(&newheader);
+ dns_slabheader_detach(&newheader);
}
NODE_UNLOCK(nlock, &nlocktype);
headers_link)
{
cds_list_del(&header->headers_link);
- dns_slabheader_destroy(&header);
+ dns_slabheader_detach(&header);
}
if (ISC_SIEVE_LINKED(top, link)) {
static unsigned char *
newslab(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region,
- uint16_t nitems, size_t size) {
+ uint16_t nitems, size_t size, const char *func, const char *file,
+ const unsigned int line) {
dns_slabheader_t *header = isc_mem_get(mctx, size);
*header = (dns_slabheader_t){
.trust = rdataset->trust,
.dirtylink = ISC_LINK_INITIALIZER,
.nitems = nitems,
+ .references = ISC_REFCOUNT_INITIALIZER(1),
};
+#if DNS_SLABHEADER_TRACE
+ fprintf(stderr,
+ "%s:%s:%s:%u:t%" PRItid ":%p->references = %" PRIuFAST32 "\n",
+ __func__, func, file, line, isc_tid(), header,
+ header->references);
+#else
+ UNUSED(func);
+ UNUSED(file);
+ UNUSED(line);
+#endif
+
region->base = (unsigned char *)header;
region->length = size;
static isc_result_t
makeslab(dns_rdataset_t *rdataset, isc_mem_t *mctx, isc_region_t *region,
- uint32_t maxrrperset) {
+ uint32_t maxrrperset, const char *func, const char *file,
+ const unsigned int line) {
/*
* Use &removed as a sentinel pointer for duplicate
* rdata as rdata.data == NULL is valid.
dns_slabheader_t *header = rdataset_getheader(rdataset);
buflen = dns_rdataslab_size(header);
- rawbuf = newslab(rdataset, mctx, region, header->nitems,
- buflen);
+ rawbuf = newslab(rdataset, mctx, region, header->nitems, buflen,
+ func, file, line);
INSIST(headerlen <= buflen);
memmove(rawbuf, (unsigned char *)header + headerlen,
if (rdataset->type != 0) {
return ISC_R_FAILURE;
}
- rawbuf = newslab(rdataset, mctx, region, 0, buflen);
+ rawbuf = newslab(rdataset, mctx, region, 0, buflen, func, file,
+ line);
return ISC_R_SUCCESS;
}
* Allocate the memory, set up a buffer, start copying in
* data.
*/
- rawbuf = newslab(rdataset, mctx, region, nitems, buflen);
+ rawbuf = newslab(rdataset, mctx, region, nitems, buflen, func, file,
+ line);
for (i = 0; i < nalloc; i++) {
if (rdata[i].data == &removed) {
}
isc_result_t
-dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
- isc_region_t *region, uint32_t maxrrperset) {
+dns_rdataslab__fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
+ isc_region_t *region, uint32_t maxrrperset,
+ const char *func, const char *file,
+ const unsigned int line) {
if (rdataset->type == dns_rdatatype_none &&
rdataset->covers == dns_rdatatype_none)
{
return DNS_R_DISALLOWED;
}
- isc_result_t result = makeslab(rdataset, mctx, region, maxrrperset);
+ isc_result_t result = makeslab(rdataset, mctx, region, maxrrperset,
+ func, file, line);
if (result != ISC_R_SUCCESS) {
return result;
}
}
void
-dns_slabheader_reset(dns_slabheader_t *h, dns_dbnode_t *node) {
+dns_slabheader__reset(dns_slabheader_t *h, dns_dbnode_t *node, const char *func,
+ const char *file, const unsigned int line) {
h->node = node;
atomic_init(&h->attributes, 0);
atomic_init(&h->last_refresh_fail_ts, 0);
+ isc_refcount_init(&h->references, 1);
ISC_LINK_INIT(h, dirtylink);
STATIC_ASSERT(sizeof(h->attributes) == 2,
"The .attributes field of dns_slabheader_t needs to be "
"16-bit int type exactly.");
+
+#if DNS_SLABHEADER_TRACE
+ fprintf(stderr,
+ "%s:%s:%s:%u:t%" PRItid ":%p->references = %" PRIuFAST32 "\n",
+ __func__, func, file, line, isc_tid(), h, h->references);
+#else
+ UNUSED(func);
+ UNUSED(file);
+ UNUSED(line);
+#endif
}
dns_slabheader_t *
-dns_slabheader_new(isc_mem_t *mctx, dns_dbnode_t *node) {
+dns_slabheader__new(isc_mem_t *mctx, dns_dbnode_t *node, const char *func,
+ const char *file, const unsigned int line) {
dns_slabheader_t *h = NULL;
h = isc_mem_get(mctx, sizeof(*h));
*h = (dns_slabheader_t){
+ .headers_link = CDS_LIST_HEAD_INIT(h->headers_link),
.node = node,
.dirtylink = ISC_LINK_INITIALIZER,
+ .references = ISC_REFCOUNT_INITIALIZER(1),
};
+
+#if DNS_SLABHEADER_TRACE
+ fprintf(stderr,
+ "%s:%s:%s:%u:t%" PRItid ":%p->references = %" PRIuFAST32 "\n",
+ __func__, func, file, line, isc_tid(), h, h->references);
+#else
+ UNUSED(func);
+ UNUSED(file);
+ UNUSED(line);
+#endif
+
return h;
}
-void
-dns_slabheader_destroy(dns_slabheader_t **headerp) {
+static void
+slabheader_destroy(dns_slabheader_t *header) {
unsigned int size;
- dns_slabheader_t *header = *headerp;
-
- *headerp = NULL;
isc_mem_t *mctx = header->node->mctx;
dns_db_deletedata(header->node, header);
isc_mem_put(mctx, proof, sizeof(*proof));
}
+#if DNS_SLABHEADER_TRACE
+ISC_REFCOUNT_TRACE_IMPL(dns_slabheader, slabheader_destroy);
+#else
+ISC_REFCOUNT_IMPL(dns_slabheader, slabheader_destroy);
+#endif
+
/* Fixed RRSet helper macros */
static void
dns_slabheader_t *header = rdataset_getheader(rdataset);
dns_dbnode_t *node = header->node;
+ dns_slabheader_detach(&header);
+
dns__db_detachnode(&node DNS__DB_FLARG_PASS);
}
target->slab.iter_pos = NULL;
target->slab.iter_count = 0;
+
+ dns_slabheader_ref(header);
}
static unsigned int