diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h index 2a25fa191f..22e653345c 100644 --- a/lib/isc/include/isc/quota.h +++ b/lib/isc/include/isc/quota.h @@ -31,26 +31,20 @@ ***/ #include +#include #include #include #include +#include #include /***** ***** Types. *****/ -ISC_LANG_BEGINDECLS +#undef ISC_QUOTA_TRACE -/*% isc_quota_cb - quota callback structure */ -typedef struct isc_quota_cb isc_quota_cb_t; -typedef void (*isc_quota_cb_func_t)(isc_quota_t *quota, void *data); -struct isc_quota_cb { - int magic; - isc_quota_cb_func_t cb_func; - void *data; - ISC_LINK(isc_quota_cb_t) link; -}; +ISC_LANG_BEGINDECLS /*% isc_quota structure */ struct isc_quota { @@ -60,7 +54,7 @@ struct isc_quota { atomic_uint_fast32_t soft; atomic_uint_fast32_t waiting; isc_mutex_t cblock; - ISC_LIST(isc_quota_cb_t) cbs; + ISC_LIST(isc_job_t) jobs; ISC_LINK(isc_quota_t) link; }; @@ -106,25 +100,14 @@ isc_quota_getused(isc_quota_t *quota); * Get the current usage of quota. */ +#define isc_quota_acquire(quota) isc_quota_acquire_cb(quota, NULL, NULL, NULL) isc_result_t -isc_quota_attach(isc_quota_t *quota, isc_quota_t **p); +isc_quota_acquire_cb(isc_quota_t *quota, isc_job_t *job, isc_job_cb cb, + void *cbarg); /*%< * - * Attempt to reserve one unit of 'quota', and also attaches '*p' to the quota - * if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA). - * - * Returns: - * \li #ISC_R_SUCCESS Success - * \li #ISC_R_SOFTQUOTA Success soft quota reached - * \li #ISC_R_QUOTA Quota is full - */ - -isc_result_t -isc_quota_attach_cb(isc_quota_t *quota, isc_quota_t **p, isc_quota_cb_t *cb); -/*%< - * - * Like isc_quota_attach(), but if there's no quota left then cb->cb_func will - * be called when we are attached to quota. + * Attempt to reserve one unit of 'quota', if there's no quota left then + * cb->cb(cb->cbarg) will be called when there's quota again. * * Note: It's the caller's responsibility to make sure that we don't end up * with a huge number of callbacks waiting, making it easy to create a @@ -140,15 +123,9 @@ isc_quota_attach_cb(isc_quota_t *quota, isc_quota_t **p, isc_quota_cb_t *cb); */ void -isc_quota_cb_init(isc_quota_cb_t *cb, isc_quota_cb_func_t cb_func, void *data); +isc_quota_release(isc_quota_t *quota); /*%< - * Initialize isc_quota_cb_t - setup the list, set the callback and data. - */ - -void -isc_quota_detach(isc_quota_t **p); -/*%< - * Release one unit of quota, and also detaches '*p' from the quota. + * Release one unit of quota. */ ISC_LANG_ENDDECLS diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 708df67274..25bc544396 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -527,14 +527,11 @@ struct isc_nmsocket { const char *tls_verify_error; } streamdns; /*% - * quota is the TCP client, attached when a TCP connection - * is established. pquota is a non-attached pointer to the - * TCP client quota, stored in listening sockets but only - * attached in connected sockets. + * pquota is a non-attached pointer to the TCP client quota, stored in + * listening sockets. */ - isc_quota_t *quota; isc_quota_t *pquota; - isc_quota_cb_t quotacb; + isc_job_t quotacb; /*% * Socket statistics @@ -1282,8 +1279,6 @@ void isc__nm_failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req, isc_result_t eresult, bool async); void -isc__nm_failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult); -void isc__nm_failed_connect_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req, isc_result_t eresult, bool async); void diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 5862ee4c13..aea9261e5e 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -487,10 +487,7 @@ nmsocket_cleanup(void *arg) { nmhandle_free(sock, handle); } - if (sock->quota != NULL) { - isc_quota_detach(&sock->quota); - } - + INSIST(sock->server == NULL); sock->pquota = NULL; isc__nm_tls_cleanup_data(sock); @@ -707,6 +704,7 @@ isc___nmsocket_init(isc_nmsocket_t *sock, isc__networker_t *worker, .active_link = ISC_LINK_INITIALIZER, .active = true, .job = ISC_JOB_INITIALIZER, + .quotacb = ISC_JOB_INITIALIZER, }; if (iface != NULL) { @@ -1058,35 +1056,6 @@ isc__nm_failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req, } } -void -isc__nm_failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult) { - REQUIRE(sock->accepting); - REQUIRE(sock->server); - - /* - * Detach the quota early to make room for other connections; - * otherwise it'd be detached later asynchronously, and clog - * the quota unnecessarily. - */ - if (sock->quota != NULL) { - isc_quota_detach(&sock->quota); - } - - isc__nmsocket_detach(&sock->server); - - sock->accepting = false; - - switch (eresult) { - case ISC_R_NOTCONNECTED: - /* IGNORE: The client disconnected before we could accept */ - break; - default: - isc__nmsocket_log(sock, ISC_LOG_ERROR, - "Accepting TCP connection failed: %s", - isc_result_totext(eresult)); - } -} - void isc__nm_failed_connect_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req, isc_result_t eresult, bool async) { diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 670db30579..7b70fb8688 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -72,39 +72,7 @@ static isc_result_t accept_connection(isc_nmsocket_t *ssock); static void -quota_accept_cb(isc_quota_t *quota, void *arg); - -static void -failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult); - -static void -failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult) { - REQUIRE(sock->server); - REQUIRE(sock->accepting); - - sock->accepting = false; - - /* - * Detach the quota early to make room for other connections; - * otherwise it'd be detached later asynchronously, and clog - * the quota unnecessarily. - */ - if (sock->quota != NULL) { - isc_quota_detach(&sock->quota); - } - - isc__nmsocket_detach(&sock->server); - - switch (eresult) { - case ISC_R_NOTCONNECTED: - /* IGNORE: The client disconnected before we could accept */ - break; - default: - isc__nmsocket_log(sock, ISC_LOG_ERROR, - "Accepting TCP connection failed: %s", - isc_result_totext(eresult)); - } -} +quota_accept_cb(void *arg); static isc_result_t tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { @@ -458,8 +426,7 @@ start_tcp_child(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nmsocket_t *sock, csock->backlog = sock->backlog; /* - * We don't attach to quota, just assign - to avoid - * increasing quota unnecessarily. + * Quota isn't attached, just assigned. */ csock->pquota = sock->pquota; @@ -562,6 +529,8 @@ tcp_connection_cb(uv_stream_t *server, int status) { isc_nmsocket_t *ssock = uv_handle_get_data((uv_handle_t *)server); isc_result_t result; + REQUIRE(ssock->accept_cb != NULL); + if (status != 0) { result = isc_uverr2result(status); goto done; @@ -575,18 +544,24 @@ tcp_connection_cb(uv_stream_t *server, int status) { goto done; } - if (ssock->pquota != NULL) { - isc_quota_t *quota = NULL; - isc_quota_cb_init(&ssock->quotacb, quota_accept_cb, ssock); - result = isc_quota_attach_cb(ssock->pquota, "a, - &ssock->quotacb); + /* Prepare the child socket */ + isc_nmsocket_t *csock = isc_mem_get(ssock->worker->mctx, + sizeof(isc_nmsocket_t)); + isc__nmsocket_init(csock, ssock->worker, isc_nm_tcpsocket, + &ssock->iface, NULL); + isc__nmsocket_attach(ssock, &csock->server); + + if (csock->server->pquota != NULL) { + result = isc_quota_acquire_cb(csock->server->pquota, + &csock->quotacb, quota_accept_cb, + csock); if (result == ISC_R_QUOTA) { isc__nm_incstats(ssock, STATID_ACCEPTFAIL); goto done; } } - result = accept_connection(ssock); + result = accept_connection(csock); done: isc__nm_accept_connection_log(ssock, result, can_log_tcp_quota()); } @@ -700,14 +675,6 @@ isc__nm_tcp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result, destroy: isc__nmsocket_prep_destroy(sock); - - /* - * We need to detach from quota after the read callback function had a - * chance to be executed. - */ - if (sock->quota != NULL) { - isc_quota_detach(&sock->quota); - } } void @@ -849,76 +816,67 @@ tcpaccept_cb(void *arg) { isc_result_t result = accept_connection(sock); isc__nm_accept_connection_log(sock, result, can_log_tcp_quota()); - sock->pquota = NULL; isc__nmsocket_detach(&sock); } static void -quota_accept_cb(isc_quota_t *quota, void *arg) { - isc_nmsocket_t *sock = arg; +quota_accept_cb(void *arg) { + isc_nmsocket_t *csock = arg; - REQUIRE(VALID_NMSOCK(sock)); - - UNUSED(quota); + REQUIRE(VALID_NMSOCK(csock)); /* * This needs to be asynchronous, because the quota might have been * released by a different child socket. */ - if (sock->tid == isc_tid()) { - isc_result_t result = accept_connection(sock); - isc__nm_accept_connection_log(sock, result, + if (csock->tid == isc_tid()) { + isc_result_t result = accept_connection(csock); + isc__nm_accept_connection_log(csock, result, can_log_tcp_quota()); - sock->pquota = NULL; } else { - isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL }); - isc_async_run(sock->worker->loop, tcpaccept_cb, sock); + isc__nmsocket_attach(csock, &(isc_nmsocket_t *){ NULL }); + isc_async_run(csock->worker->loop, tcpaccept_cb, csock); } } static isc_result_t -accept_connection(isc_nmsocket_t *ssock) { - isc_nmsocket_t *csock = NULL; - isc__networker_t *worker = NULL; +accept_connection(isc_nmsocket_t *csock) { int r; isc_result_t result; struct sockaddr_storage ss; isc_sockaddr_t local; isc_nmhandle_t *handle = NULL; - REQUIRE(VALID_NMSOCK(ssock)); - REQUIRE(ssock->tid == isc_tid()); + REQUIRE(VALID_NMSOCK(csock)); + REQUIRE(VALID_NMSOCK(csock->server)); + REQUIRE(csock->tid == isc_tid()); - if (isc__nmsocket_closing(ssock)) { - if (ssock->pquota != NULL) { - isc_quota_detach(&ssock->pquota); - } - - return (ISC_R_CANCELED); - } - - REQUIRE(ssock->accept_cb != NULL); - - csock = isc_mem_get(ssock->worker->mctx, sizeof(isc_nmsocket_t)); - isc__nmsocket_init(csock, ssock->worker, isc_nm_tcpsocket, - &ssock->iface, NULL); - isc__nmsocket_attach(ssock, &csock->server); - csock->recv_cb = ssock->recv_cb; - csock->recv_cbarg = ssock->recv_cbarg; csock->accepting = true; - csock->quota = ssock->pquota; + csock->accept_cb = csock->server->accept_cb; + csock->accept_cbarg = csock->server->accept_cbarg; + csock->recv_cb = csock->server->recv_cb; + csock->recv_cbarg = csock->server->recv_cbarg; + csock->read_timeout = atomic_load_relaxed(&csock->worker->netmgr->init); - worker = csock->worker; - - r = uv_tcp_init(&worker->loop->loop, &csock->uv_handle.tcp); + r = uv_tcp_init(&csock->worker->loop->loop, &csock->uv_handle.tcp); UV_RUNTIME_CHECK(uv_tcp_init, r); uv_handle_set_data(&csock->uv_handle.handle, csock); - r = uv_timer_init(&worker->loop->loop, &csock->read_timer); + r = uv_timer_init(&csock->worker->loop->loop, &csock->read_timer); UV_RUNTIME_CHECK(uv_timer_init, r); uv_handle_set_data((uv_handle_t *)&csock->read_timer, csock); - r = uv_accept(&ssock->uv_handle.stream, &csock->uv_handle.stream); + /* + * We need to initialize the tcp and timer before failing because + * isc__nm_tcp_close() can't handle uninitalized TCP nmsocket. + */ + if (isc__nmsocket_closing(csock)) { + result = ISC_R_CANCELED; + goto failure; + } + + r = uv_accept(&csock->server->uv_handle.stream, + &csock->uv_handle.stream); if (r != 0) { result = isc_uverr2result(r); goto failure; @@ -951,7 +909,7 @@ accept_connection(isc_nmsocket_t *ssock) { handle = isc__nmhandle_get(csock, NULL, &local); - result = ssock->accept_cb(handle, ISC_R_SUCCESS, ssock->accept_cbarg); + result = csock->accept_cb(handle, ISC_R_SUCCESS, csock->accept_cbarg); if (result != ISC_R_SUCCESS) { isc_nmhandle_detach(&handle); goto failure; @@ -961,8 +919,6 @@ accept_connection(isc_nmsocket_t *ssock) { isc__nm_incstats(csock, STATID_ACCEPT); - csock->read_timeout = atomic_load_relaxed(&csock->worker->netmgr->init); - /* * The acceptcb needs to attach to the handle if it wants to keep the * connection alive @@ -978,8 +934,14 @@ accept_connection(isc_nmsocket_t *ssock) { failure: csock->active = false; + csock->accepting = false; - failed_accept_cb(csock, result); + if (result != ISC_R_NOTCONNECTED) { + /* IGNORE: The client disconnected before we could accept */ + isc__nmsocket_log(csock, ISC_LOG_ERROR, + "Accepting TCP connection failed: %s", + isc_result_totext(result)); + } isc__nmsocket_prep_destroy(csock); @@ -1153,6 +1115,9 @@ tcp_close_sock(isc_nmsocket_t *sock) { isc__nm_incstats(sock, STATID_CLOSE); if (sock->server != NULL) { + if (sock->server->pquota != NULL) { + isc_quota_release(sock->server->pquota); + } isc__nmsocket_detach(&sock->server); } @@ -1178,10 +1143,6 @@ isc__nm_tcp_close(isc_nmsocket_t *sock) { sock->closing = true; - if (sock->quota != NULL) { - isc_quota_detach(&sock->quota); - } - /* * The order of the close operation is important here, the uv_close() * gets scheduled in the reverse order, so we need to close the timer diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 5fea2e8f33..44de0fa515 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -944,11 +944,6 @@ udp_close_cb(uv_handle_t *handle) { isc__nm_incstats(sock, STATID_CLOSE); - if (sock->server != NULL) { - /* server socket (accept) */ - isc__nmsocket_detach(&sock->server); - } - if (sock->parent != NULL) { /* listening socket (listen) */ isc__nmsocket_detach(&sock); diff --git a/lib/isc/quota.c b/lib/isc/quota.c index 5465db5b73..4dbdbc5781 100644 --- a/lib/isc/quota.c +++ b/lib/isc/quota.c @@ -22,45 +22,28 @@ #define QUOTA_MAGIC ISC_MAGIC('Q', 'U', 'O', 'T') #define VALID_QUOTA(p) ISC_MAGIC_VALID(p, QUOTA_MAGIC) -#define QUOTA_CB_MAGIC ISC_MAGIC('Q', 'T', 'C', 'B') -#define VALID_QUOTA_CB(p) ISC_MAGIC_VALID(p, QUOTA_CB_MAGIC) - void isc_quota_init(isc_quota_t *quota, unsigned int max) { atomic_init("a->max, max); atomic_init("a->used, 0); atomic_init("a->soft, 0); atomic_init("a->waiting, 0); - ISC_LIST_INIT(quota->cbs); + ISC_LIST_INIT(quota->jobs); isc_mutex_init("a->cblock); ISC_LINK_INIT(quota, link); quota->magic = QUOTA_MAGIC; } -void -isc_quota_destroy(isc_quota_t *quota) { - REQUIRE(VALID_QUOTA(quota)); - quota->magic = 0; - - INSIST(atomic_load("a->used) == 0); - INSIST(atomic_load("a->waiting) == 0); - INSIST(ISC_LIST_EMPTY(quota->cbs)); - atomic_store_release("a->max, 0); - atomic_store_release("a->used, 0); - atomic_store_release("a->soft, 0); - isc_mutex_destroy("a->cblock); -} - void isc_quota_soft(isc_quota_t *quota, unsigned int soft) { REQUIRE(VALID_QUOTA(quota)); - atomic_store_release("a->soft, soft); + atomic_store_relaxed("a->soft, soft); } void isc_quota_max(isc_quota_t *quota, unsigned int max) { REQUIRE(VALID_QUOTA(quota)); - atomic_store_release("a->max, max); + atomic_store_relaxed("a->max, max); } unsigned int @@ -81,46 +64,27 @@ isc_quota_getused(isc_quota_t *quota) { return (atomic_load_relaxed("a->used)); } -static isc_result_t -quota_reserve(isc_quota_t *quota) { - isc_result_t result; - uint_fast32_t max = atomic_load_acquire("a->max); - uint_fast32_t soft = atomic_load_acquire("a->soft); - uint_fast32_t used = atomic_load_acquire("a->used); - do { - if (max != 0 && used >= max) { - return (ISC_R_QUOTA); - } - if (soft != 0 && used >= soft) { - result = ISC_R_SOFTQUOTA; - } else { - result = ISC_R_SUCCESS; - } - } while (!atomic_compare_exchange_weak_acq_rel("a->used, &used, - used + 1)); - return (result); -} - -/* Must be quota->cbslock locked */ +/* Must be quota->cblock locked */ static void -enqueue(isc_quota_t *quota, isc_quota_cb_t *cb) { +enqueue(isc_quota_t *quota, isc_job_t *cb) { REQUIRE(cb != NULL); - ISC_LIST_ENQUEUE(quota->cbs, cb, link); - atomic_fetch_add_release("a->waiting, 1); + ISC_LIST_ENQUEUE(quota->jobs, cb, link); + atomic_fetch_add_relaxed("a->waiting, 1); } -/* Must be quota->cbslock locked */ -static isc_quota_cb_t * +/* Must be quota->cblock locked */ +static isc_job_t * dequeue(isc_quota_t *quota) { - isc_quota_cb_t *cb = ISC_LIST_HEAD(quota->cbs); - INSIST(cb != NULL); - ISC_LIST_DEQUEUE(quota->cbs, cb, link); - atomic_fetch_sub_relaxed("a->waiting, 1); + isc_job_t *cb = ISC_LIST_HEAD(quota->jobs); + if (cb != NULL) { + ISC_LIST_DEQUEUE(quota->jobs, cb, link); + atomic_fetch_sub_relaxed("a->waiting, 1); + } return (cb); } -static void -quota_release(isc_quota_t *quota) { +void +isc_quota_release(isc_quota_t *quota) { uint_fast32_t used; /* @@ -131,14 +95,12 @@ quota_release(isc_quota_t *quota) { */ if (atomic_load_acquire("a->waiting) > 0) { - isc_quota_cb_t *cb = NULL; + isc_job_t *cb = NULL; LOCK("a->cblock); - if (atomic_load_relaxed("a->waiting) > 0) { - cb = dequeue(quota); - } + cb = dequeue(quota); UNLOCK("a->cblock); if (cb != NULL) { - cb->cb_func(quota, cb->data); + cb->cb(cb->cbarg); return; } } @@ -147,56 +109,42 @@ quota_release(isc_quota_t *quota) { INSIST(used > 0); } -static isc_result_t -doattach(isc_quota_t *quota, isc_quota_t **p) { - isc_result_t result; - REQUIRE(p != NULL && *p == NULL); +isc_result_t +isc_quota_acquire_cb(isc_quota_t *quota, isc_job_t *job, isc_job_cb cb, + void *cbarg) { + REQUIRE(VALID_QUOTA(quota)); + REQUIRE(job == NULL || cb != NULL); - result = quota_reserve(quota); - if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA) { - *p = quota; + uint_fast32_t used = atomic_fetch_add_release("a->used, 1); + + uint_fast32_t max = atomic_load_relaxed("a->max); + if (max != 0 && used >= max) { + (void)atomic_fetch_sub_relaxed("a->used, 1); + if (job != NULL) { + job->cb = cb; + job->cbarg = cbarg; + LOCK("a->cblock); + enqueue(quota, job); + UNLOCK("a->cblock); + } + return (ISC_R_QUOTA); } - return (result); -} - -isc_result_t -isc_quota_attach(isc_quota_t *quota, isc_quota_t **quotap) { - REQUIRE(VALID_QUOTA(quota)); - REQUIRE(quotap != NULL && *quotap == NULL); - - return (isc_quota_attach_cb(quota, quotap, NULL)); -} - -isc_result_t -isc_quota_attach_cb(isc_quota_t *quota, isc_quota_t **quotap, - isc_quota_cb_t *cb) { - REQUIRE(VALID_QUOTA(quota)); - REQUIRE(cb == NULL || VALID_QUOTA_CB(cb)); - REQUIRE(quotap != NULL && *quotap == NULL); - - isc_result_t result = doattach(quota, quotap); - if (result == ISC_R_QUOTA && cb != NULL) { - LOCK("a->cblock); - enqueue(quota, cb); - UNLOCK("a->cblock); + uint_fast32_t soft = atomic_load_relaxed("a->soft); + if (soft != 0 && used >= soft) { + return (ISC_R_SOFTQUOTA); } - return (result); + + return (ISC_R_SUCCESS); } void -isc_quota_cb_init(isc_quota_cb_t *cb, isc_quota_cb_func_t cb_func, void *data) { - ISC_LINK_INIT(cb, link); - cb->cb_func = cb_func; - cb->data = data; - cb->magic = QUOTA_CB_MAGIC; -} +isc_quota_destroy(isc_quota_t *quota) { + REQUIRE(VALID_QUOTA(quota)); + quota->magic = 0; -void -isc_quota_detach(isc_quota_t **quotap) { - REQUIRE(quotap != NULL && VALID_QUOTA(*quotap)); - isc_quota_t *quota = *quotap; - *quotap = NULL; - - quota_release(quota); + INSIST(atomic_load("a->used) == 0); + INSIST(atomic_load("a->waiting) == 0); + INSIST(ISC_LIST_EMPTY(quota->jobs)); + isc_mutex_destroy("a->cblock); } diff --git a/lib/ns/client.c b/lib/ns/client.c index 37a08b3210..5e6f14f780 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -254,13 +254,6 @@ ns_client_endrequest(ns_client_t *client) { dns_ecs_init(&client->ecs); dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE); - /* - * Ensure there are no recursions that still need to be cleaned up. - */ - for (int i = 0; i < RECTYPE_COUNT; i++) { - INSIST(client->query.recursions[i].quota == NULL); - } - /* * Clear all client attributes that are specific to the request */ @@ -1760,10 +1753,6 @@ ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult, client->attributes |= NS_CLIENTATTR_TCP; } - for (int i = 0; i < RECTYPE_COUNT; i++) { - INSIST(client->query.recursions[i].quota == NULL); - } - INSIST(client->state == NS_CLIENTSTATE_READY); (void)atomic_fetch_add_relaxed(&ns_client_requests, 1); diff --git a/lib/ns/include/ns/query.h b/lib/ns/include/ns/query.h index abb18fbd99..96bcbf9b39 100644 --- a/lib/ns/include/ns/query.h +++ b/lib/ns/include/ns/query.h @@ -80,21 +80,6 @@ typedef enum { #define FETCH_RECTYPE_HOOK(client) \ ((client)->query.recursions[RECTYPE_HOOK].fetch) -/*% - * Helper macros for accessing isc_quota_t pointers for a specific recursion a - * given client is associated with. - */ -#define QUOTA_RECTYPE_NORMAL(client) \ - ((client)->query.recursions[RECTYPE_NORMAL].quota) -#define QUOTA_RECTYPE_PREFETCH(client) \ - ((client)->query.recursions[RECTYPE_PREFETCH].quota) -#define QUOTA_RECTYPE_RPZ(client) \ - ((client)->query.recursions[RECTYPE_RPZ].quota) -#define QUOTA_RECTYPE_STALE_REFRESH(client) \ - ((client)->query.recursions[RECTYPE_STALE_REFRESH].quota) -#define QUOTA_RECTYPE_HOOK(client) \ - ((client)->query.recursions[RECTYPE_HOOK].quota) - /*% * nameserver recursion parameters, to uniquely identify a recursion * query; this is used to detect a recursion loop @@ -152,7 +137,6 @@ struct ns_query { struct { isc_nmhandle_t *handle; dns_fetch_t *fetch; - isc_quota_t *quota; } recursions[RECTYPE_COUNT]; ns_query_recparam_t recparam; diff --git a/lib/ns/query.c b/lib/ns/query.c index 83413ec0ec..5d223e5483 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -2483,13 +2483,10 @@ free_fresp(ns_client_t *client, dns_fetchresponse_t **frespp) { } static isc_result_t -recursionquotatype_attach(ns_client_t *client, - ns_query_rectype_t recursion_type, bool soft_limit) { - isc_quota_t **quotap = &client->query.recursions[recursion_type].quota; +recursionquotatype_attach(ns_client_t *client, bool soft_limit) { isc_result_t result; - result = isc_quota_attach(&client->manager->sctx->recursionquota, - quotap); + result = isc_quota_acquire(&client->manager->sctx->recursionquota); switch (result) { case ISC_R_SUCCESS: break; @@ -2503,7 +2500,7 @@ recursionquotatype_attach(ns_client_t *client, break; } - isc_quota_detach(quotap); + isc_quota_release(&client->manager->sctx->recursionquota); FALLTHROUGH; default: return (result); @@ -2516,21 +2513,18 @@ recursionquotatype_attach(ns_client_t *client, } static isc_result_t -recursionquotatype_attach_hard(ns_client_t *client, - ns_query_rectype_t recursion_type) { - return (recursionquotatype_attach(client, recursion_type, false)); +recursionquotatype_attach_hard(ns_client_t *client) { + return (recursionquotatype_attach(client, false)); } static isc_result_t -recursionquotatype_attach_soft(ns_client_t *client, - ns_query_rectype_t recursion_type) { - return (recursionquotatype_attach(client, recursion_type, true)); +recursionquotatype_attach_soft(ns_client_t *client) { + return (recursionquotatype_attach(client, true)); } static void -recursionquotatype_detach(ns_client_t *client, - ns_query_rectype_t recursion_type) { - isc_quota_detach(&client->query.recursions[recursion_type].quota); +recursionquotatype_detach(ns_client_t *client) { + isc_quota_release(&client->manager->sctx->recursionquota); ns_stats_decrement(client->manager->sctx->nsstats, ns_statscounter_recursclients); } @@ -2646,7 +2640,7 @@ cleanup_after_fetch(dns_fetchresponse_t *resp, const char *ctracestr, stale_refresh_aftermath(client, result); } - recursionquotatype_detach(client, recursion_type); + recursionquotatype_detach(client); free_fresp(client, &resp); isc_nmhandle_detach(handlep); } @@ -2685,7 +2679,7 @@ fetch_and_forget(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t qtype, dns_fetch_t **fetchp; isc_result_t result; - result = recursionquotatype_attach_hard(client, recursion_type); + result = recursionquotatype_attach_hard(client); if (result != ISC_R_SUCCESS) { return; } @@ -2726,7 +2720,7 @@ fetch_and_forget(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t qtype, if (result != ISC_R_SUCCESS) { ns_client_putrdataset(client, &tmprdataset); isc_nmhandle_detach(handlep); - recursionquotatype_detach(client, recursion_type); + recursionquotatype_detach(client); } } @@ -6299,7 +6293,7 @@ fetch_callback(void *arg) { * the manager's recursing-clients list. */ - recursionquotatype_detach(client, RECTYPE_NORMAL); + recursionquotatype_detach(client); LOCK(&client->manager->reclock); if (ISC_LINK_LINKED(client, rlink)) { @@ -6431,17 +6425,16 @@ static atomic_uint_fast32_t last_soft, last_hard; * Check recursion quota before making the current client "recursing". */ static isc_result_t -check_recursionquota(ns_client_t *client, ns_query_rectype_t recursion_type) { - isc_quota_t **quotap = &client->query.recursions[recursion_type].quota; +check_recursionquota(ns_client_t *client) { isc_result_t result; - result = recursionquotatype_attach_soft(client, recursion_type); + result = recursionquotatype_attach_soft(client); switch (result) { case ISC_R_SOFTQUOTA: recursionquota_log(client, &last_soft, "recursive-clients soft limit exceeded " "(%u/%u/%u), aborting oldest query", - *quotap); + &client->manager->sctx->recursionquota); ns_client_killoldestquery(client); FALLTHROUGH; case ISC_R_SUCCESS: @@ -6488,7 +6481,7 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, inc_stats(client, ns_statscounter_recursion); } - result = check_recursionquota(client, RECTYPE_NORMAL); + result = check_recursionquota(client); if (result != ISC_R_SUCCESS) { return (result); } @@ -6534,7 +6527,7 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, if (sigrdataset != NULL) { ns_client_putrdataset(client, &sigrdataset); } - recursionquotatype_detach(client, RECTYPE_NORMAL); + recursionquotatype_detach(client); } /* @@ -6764,7 +6757,7 @@ query_hookresume(void *arg) { UNLOCK(&client->query.fetchlock); SAVE(hctx, rev->ctx); - recursionquotatype_detach(client, RECTYPE_HOOK); + recursionquotatype_detach(client); LOCK(&client->manager->reclock); if (ISC_LINK_LINKED(client, rlink)) { @@ -6895,7 +6888,7 @@ ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync, REQUIRE(client->query.hookactx == NULL); REQUIRE(FETCH_RECTYPE_NORMAL(client) == NULL); - result = check_recursionquota(client, RECTYPE_HOOK); + result = check_recursionquota(client); if (result != ISC_R_SUCCESS) { goto cleanup; } @@ -6924,7 +6917,7 @@ ns_query_hookasync(query_ctx_t *qctx, ns_query_starthookasync_t runasync, return (ISC_R_SUCCESS); cleanup_and_detach_from_quota: - recursionquotatype_detach(client, RECTYPE_HOOK); + recursionquotatype_detach(client); cleanup: /* * If we fail, send SERVFAIL now. It may be better to let the caller diff --git a/lib/ns/update.c b/lib/ns/update.c index e99afc1b01..bd3d3af3d4 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -1882,8 +1882,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) { update_log(client, zone, LOGLEVEL_DEBUG, "update section prescan OK"); - result = isc_quota_attach(&client->manager->sctx->updquota, - &(isc_quota_t *){ NULL }); + result = isc_quota_acquire(&client->manager->sctx->updquota); if (result != ISC_R_SUCCESS) { update_log(client, zone, LOGLEVEL_PROTOCOL, "update failed: too many DNS UPDATEs queued (%s)", @@ -3608,7 +3607,7 @@ updatedone_action(void *arg) { respond(client, uev->result); - isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota }); + isc_quota_release(&client->manager->sctx->updquota); if (uev->zone != NULL) { dns_zone_detach(&uev->zone); } @@ -3626,7 +3625,7 @@ forward_fail(void *arg) { respond(client, DNS_R_SERVFAIL); - isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota }); + isc_quota_release(&client->manager->sctx->updquota); isc_mem_put(client->manager->mctx, uev, sizeof(*uev)); isc_nmhandle_detach(&client->updatehandle); } @@ -3658,7 +3657,7 @@ forward_done(void *arg) { ns_client_sendraw(client, uev->answer); dns_message_detach(&uev->answer); - isc_quota_detach(&(isc_quota_t *){ &client->manager->sctx->updquota }); + isc_quota_release(&client->manager->sctx->updquota); isc_mem_put(client->manager->mctx, uev, sizeof(*uev)); isc_nmhandle_detach(&client->reqhandle); isc_nmhandle_detach(&client->updatehandle); @@ -3696,9 +3695,11 @@ send_forward(ns_client_t *client, dns_zone_t *zone) { return (result); } - result = isc_quota_attach(&client->manager->sctx->updquota, - &(isc_quota_t *){ NULL }); + result = isc_quota_acquire(&client->manager->sctx->updquota); if (result != ISC_R_SUCCESS) { + if (result == ISC_R_SOFTQUOTA) { + isc_quota_release(&client->manager->sctx->updquota); + } update_log(client, zone, LOGLEVEL_PROTOCOL, "update failed: too many DNS UPDATEs queued (%s)", isc_result_totext(result)); diff --git a/lib/ns/xfrout.c b/lib/ns/xfrout.c index b42c08cc6a..041c6a109f 100644 --- a/lib/ns/xfrout.c +++ b/lib/ns/xfrout.c @@ -649,7 +649,6 @@ typedef struct { dns_zone_t *zone; /* (necessary for stats) */ dns_db_t *db; dns_dbversion_t *ver; - isc_quota_t *quota; rrstream_t *stream; /* The XFR RR stream */ bool question_added; /* QUESTION section sent? */ bool end_of_stream; /* EOS has been reached */ @@ -681,7 +680,7 @@ static void xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, dns_rdataclass_t qclass, dns_zone_t *zone, dns_db_t *db, - dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream, + dns_dbversion_t *ver, rrstream_t *stream, dns_tsigkey_t *tsigkey, isc_buffer_t *lasttsig, bool verified_tsig, unsigned int maxtime, unsigned int idletime, bool many_answers, @@ -736,7 +735,6 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { isc_mem_t *mctx = client->manager->mctx; dns_message_t *request = client->message; xfrout_ctx_t *xfr = NULL; - isc_quota_t *quota = NULL; dns_transfer_format_t format = client->view->transfer_format; isc_netaddr_t na; dns_peer_t *peer = NULL; @@ -766,12 +764,12 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { /* * Apply quota. */ - result = isc_quota_attach(&client->manager->sctx->xfroutquota, "a); + result = isc_quota_acquire(&client->manager->sctx->xfroutquota); if (result != ISC_R_SUCCESS) { isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING, "%s request denied: %s", mnemonic, isc_result_totext(result)); - goto failure; + goto max_quota; } /* @@ -1084,7 +1082,7 @@ have_stream: if (is_dlz) { xfrout_ctx_create(mctx, client, request->id, question_name, - reqtype, question_class, zone, db, ver, quota, + reqtype, question_class, zone, db, ver, stream, dns_message_gettsigkey(request), tsigbuf, request->verified_sig, 3600, 3600, (format == dns_many_answers) ? true : false, @@ -1092,7 +1090,7 @@ have_stream: } else { xfrout_ctx_create( mctx, client, request->id, question_name, reqtype, - question_class, zone, db, ver, quota, stream, + question_class, zone, db, ver, stream, dns_message_gettsigkey(request), tsigbuf, request->verified_sig, dns_zone_getmaxxfrout(zone), dns_zone_getidleout(zone), @@ -1102,7 +1100,6 @@ have_stream: xfr->end_serial = current_serial; xfr->mnemonic = mnemonic; stream = NULL; - quota = NULL; CHECK(xfr->stream->methods->first(xfr->stream)); @@ -1172,9 +1169,6 @@ failure: if (result == DNS_R_REFUSED) { inc_stats(client, zone, ns_statscounter_xfrrej); } - if (quota != NULL) { - isc_quota_detach("a); - } if (current_soa_tuple != NULL) { dns_difftuple_free(¤t_soa_tuple); } @@ -1196,10 +1190,12 @@ failure: if (zone != NULL) { dns_zone_detach(&zone); } - /* XXX kludge */ + if (xfr != NULL) { xfrout_fail(xfr, result, "setting up zone transfer"); } else if (result != ISC_R_SUCCESS) { + isc_quota_release(&client->manager->sctx->xfroutquota); + max_quota: ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3), "zone transfer setup failed"); @@ -1212,7 +1208,7 @@ static void xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, dns_rdataclass_t qclass, dns_zone_t *zone, dns_db_t *db, - dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream, + dns_dbversion_t *ver, rrstream_t *stream, dns_tsigkey_t *tsigkey, isc_buffer_t *lasttsig, bool verified_tsig, unsigned int maxtime, unsigned int idletime, bool many_answers, @@ -1279,7 +1275,6 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, * These MUST be after the last "goto failure;" / CHECK to * prevent a double free by the caller. */ - xfr->quota = quota; xfr->stream = stream; *xfrp = xfr; @@ -1608,9 +1603,9 @@ xfrout_ctx_destroy(xfrout_ctx_t **xfrp) { if (xfr->lasttsig != NULL) { isc_buffer_free(&xfr->lasttsig); } - if (xfr->quota != NULL) { - isc_quota_detach(&xfr->quota); - } + + isc_quota_release(&xfr->client->manager->sctx->xfroutquota); + if (xfr->ver != NULL) { dns_db_closeversion(xfr->db, &xfr->ver, false); } diff --git a/tests/isc/quota_test.c b/tests/isc/quota_test.c index d4ae843a4a..cbf2724ea2 100644 --- a/tests/isc/quota_test.c +++ b/tests/isc/quota_test.c @@ -23,6 +23,7 @@ #define UNIT_TESTING #include +#include #include #include #include @@ -31,10 +32,10 @@ #include +isc_quota_t quota; + ISC_RUN_TEST_IMPL(isc_quota_get_set) { UNUSED(state); - isc_quota_t quota; - isc_quota_t *quota2 = NULL; isc_quota_init("a, 100); assert_int_equal(isc_quota_getmax("a), 100); @@ -47,30 +48,26 @@ ISC_RUN_TEST_IMPL(isc_quota_get_set) { assert_int_equal(isc_quota_getsoft("a), 30); assert_int_equal(isc_quota_getused("a), 0); - isc_quota_attach("a, "a2); + isc_quota_acquire("a); assert_int_equal(isc_quota_getused("a), 1); - isc_quota_detach("a2); + isc_quota_release("a); assert_int_equal(isc_quota_getused("a), 0); isc_quota_destroy("a); } static void -add_quota(isc_quota_t *source, isc_quota_t **target, - isc_result_t expected_result, int expected_used) { +add_quota(isc_quota_t *source, isc_result_t expected_result, + int expected_used) { isc_result_t result; - *target = NULL; - - result = isc_quota_attach(source, target); + result = isc_quota_acquire(source); assert_int_equal(result, expected_result); switch (expected_result) { case ISC_R_SUCCESS: case ISC_R_SOFTQUOTA: - assert_ptr_equal(*target, source); break; default: - assert_null(*target); break; } @@ -78,30 +75,26 @@ add_quota(isc_quota_t *source, isc_quota_t **target, } ISC_RUN_TEST_IMPL(isc_quota_hard) { - isc_quota_t quota; - isc_quota_t *quotas[110]; int i; UNUSED(state); isc_quota_init("a, 100); for (i = 0; i < 100; i++) { - add_quota("a, "as[i], ISC_R_SUCCESS, i + 1); + add_quota("a, ISC_R_SUCCESS, i + 1); } - add_quota("a, "as[100], ISC_R_QUOTA, 100); + add_quota("a, ISC_R_QUOTA, 100); assert_int_equal(isc_quota_getused("a), 100); - isc_quota_detach("as[0]); - assert_null(quotas[0]); + isc_quota_release("a); - add_quota("a, "as[100], ISC_R_SUCCESS, 100); - add_quota("a, "as[101], ISC_R_QUOTA, 100); + add_quota("a, ISC_R_SUCCESS, 100); + add_quota("a, ISC_R_QUOTA, 100); for (i = 100; i > 0; i--) { - isc_quota_detach("as[i]); - assert_null(quotas[i]); + isc_quota_release("a); assert_int_equal(isc_quota_getused("a), i - 1); } assert_int_equal(isc_quota_getused("a), 0); @@ -109,8 +102,6 @@ ISC_RUN_TEST_IMPL(isc_quota_hard) { } ISC_RUN_TEST_IMPL(isc_quota_soft) { - isc_quota_t quota; - isc_quota_t *quotas[110]; int i; UNUSED(state); @@ -118,17 +109,16 @@ ISC_RUN_TEST_IMPL(isc_quota_soft) { isc_quota_soft("a, 50); for (i = 0; i < 50; i++) { - add_quota("a, "as[i], ISC_R_SUCCESS, i + 1); + add_quota("a, ISC_R_SUCCESS, i + 1); } for (i = 50; i < 100; i++) { - add_quota("a, "as[i], ISC_R_SOFTQUOTA, i + 1); + add_quota("a, ISC_R_SOFTQUOTA, i + 1); } - add_quota("a, "as[i], ISC_R_QUOTA, 100); + add_quota("a, ISC_R_QUOTA, 100); for (i = 99; i >= 0; i--) { - isc_quota_detach("as[i]); - assert_null(quotas[i]); + isc_quota_release("a); assert_int_equal(isc_quota_getused("a), i); } assert_int_equal(isc_quota_getused("a), 0); @@ -136,18 +126,14 @@ ISC_RUN_TEST_IMPL(isc_quota_soft) { } static atomic_uint_fast32_t cb_calls = 0; -static isc_quota_cb_t cbs[30]; -static isc_quota_t *qp; +static isc_job_t cbs[30]; static void -callback(isc_quota_t *quota, void *data) { +callback(void *data) { int val = *(int *)data; /* Callback is not called if we get the quota directly */ assert_int_not_equal(val, -1); - /* We get the proper quota pointer */ - assert_ptr_equal(quota, qp); - /* Verify that the callbacks are called in order */ int v = atomic_fetch_add_relaxed(&cb_calls, 1); assert_int_equal(v, val); @@ -157,15 +143,12 @@ callback(isc_quota_t *quota, void *data) { * for the last 5 - do a 'chain detach'. */ if (v >= 5) { - isc_quota_detach("a); + isc_quota_release("a); } } ISC_RUN_TEST_IMPL(isc_quota_callback) { isc_result_t result; - isc_quota_t quota; - isc_quota_t *quotas[30]; - qp = "a; /* * - 10 calls that end with SUCCESS * - 10 calls that end with SOFTQUOTA @@ -181,51 +164,45 @@ ISC_RUN_TEST_IMPL(isc_quota_callback) { isc_quota_soft("a, 10); for (i = 0; i < 10; i++) { - quotas[i] = NULL; - isc_quota_cb_init(&cbs[i], callback, &ints[i]); - result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + cbs[i] = (isc_job_t)ISC_JOB_INITIALIZER; + result = isc_quota_acquire_cb("a, &cbs[i], callback, + &ints[i]); assert_int_equal(result, ISC_R_SUCCESS); - assert_ptr_equal(quotas[i], "a); assert_int_equal(isc_quota_getused("a), i + 1); } for (i = 10; i < 20; i++) { - quotas[i] = NULL; - isc_quota_cb_init(&cbs[i], callback, &ints[i]); - result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + cbs[i] = (isc_job_t)ISC_JOB_INITIALIZER; + result = isc_quota_acquire_cb("a, &cbs[i], callback, + &ints[i]); assert_int_equal(result, ISC_R_SOFTQUOTA); - assert_ptr_equal(quotas[i], "a); assert_int_equal(isc_quota_getused("a), i + 1); } for (i = 20; i < 30; i++) { - quotas[i] = NULL; - isc_quota_cb_init(&cbs[i], callback, &ints[i]); - result = isc_quota_attach_cb("a, "as[i], &cbs[i]); + cbs[i] = (isc_job_t)ISC_JOB_INITIALIZER; + result = isc_quota_acquire_cb("a, &cbs[i], callback, + &ints[i]); assert_int_equal(result, ISC_R_QUOTA); - assert_ptr_equal(quotas[i], NULL); assert_int_equal(isc_quota_getused("a), 20); } assert_int_equal(atomic_load(&cb_calls), 0); for (i = 0; i < 5; i++) { - isc_quota_detach("as[i]); - assert_null(quotas[i]); + isc_quota_release("a); assert_int_equal(isc_quota_getused("a), 20); assert_int_equal(atomic_load(&cb_calls), i + 1); } /* That should cause a chain reaction */ - isc_quota_detach("as[5]); + isc_quota_release("a); assert_int_equal(atomic_load(&cb_calls), 10); /* Release the quotas that we did not released in the callback */ for (i = 0; i < 5; i++) { - qp = "a; - isc_quota_detach(&qp); + isc_quota_release("a); } for (i = 6; i < 20; i++) { - isc_quota_detach("as[i]); - assert_null(quotas[i]); + isc_quota_release("a); assert_int_equal(isc_quota_getused("a), 19 - i); } assert_int_equal(atomic_load(&cb_calls), 10); @@ -244,8 +221,7 @@ ISC_RUN_TEST_IMPL(isc_quota_callback) { typedef struct qthreadinfo { atomic_uint_fast32_t direct; atomic_uint_fast32_t callback; - isc_quota_t *quota; - isc_quota_cb_t callbacks[100]; + isc_job_t callbacks[100]; } qthreadinfo_t; static atomic_uint_fast32_t g_tnum = 0; @@ -253,33 +229,31 @@ static atomic_uint_fast32_t g_tnum = 0; isc_thread_t g_threads[10 * 100]; static void * -quota_detach(void *quotap) { - isc_quota_t *quota = (isc_quota_t *)quotap; +quota_release(void *arg) { uv_sleep(10); - isc_quota_detach("a); + isc_quota_release((isc_quota_t *)arg); return ((isc_threadresult_t)0); } static void -quota_callback(isc_quota_t *quota, void *data) { +quota_callback(void *data) { qthreadinfo_t *qti = (qthreadinfo_t *)data; atomic_fetch_add_relaxed(&qti->callback, 1); int tnum = atomic_fetch_add_relaxed(&g_tnum, 1); - isc_thread_create(quota_detach, quota, &g_threads[tnum]); + isc_thread_create(quota_release, "a, &g_threads[tnum]); } static isc_threadresult_t quota_thread(void *qtip) { qthreadinfo_t *qti = (qthreadinfo_t *)qtip; for (int i = 0; i < 100; i++) { - isc_quota_cb_init(&qti->callbacks[i], quota_callback, qti); - isc_quota_t *quota = NULL; - isc_result_t result = isc_quota_attach_cb(qti->quota, "a, - &qti->callbacks[i]); + qti->callbacks[i] = (isc_job_t)ISC_JOB_INITIALIZER; + isc_result_t result = isc_quota_acquire_cb( + "a, &qti->callbacks[i], quota_callback, qti); if (result == ISC_R_SUCCESS) { atomic_fetch_add_relaxed(&qti->direct, 1); int tnum = atomic_fetch_add_relaxed(&g_tnum, 1); - isc_thread_create(quota_detach, quota, + isc_thread_create(quota_release, "a, &g_threads[tnum]); } } @@ -288,7 +262,6 @@ quota_thread(void *qtip) { ISC_RUN_TEST_IMPL(isc_quota_callback_mt) { UNUSED(state); - isc_quota_t quota; int i; isc_quota_init("a, 100); @@ -297,7 +270,6 @@ ISC_RUN_TEST_IMPL(isc_quota_callback_mt) { for (i = 0; i < 10; i++) { atomic_init(&qtis[i].direct, 0); atomic_init(&qtis[i].callback, 0); - qtis[i].quota = "a; isc_thread_create(quota_thread, &qtis[i], &threads[i]); } for (i = 0; i < 10; i++) { diff --git a/tests/ns/query_test.c b/tests/ns/query_test.c index 2c538c4320..6dcf5f102f 100644 --- a/tests/ns/query_test.c +++ b/tests/ns/query_test.c @@ -861,7 +861,6 @@ run_hookasync_test(const ns__query_hookasync_test_params_t *test) { .action = ns_test_qctx_destroy_hook, .action_data = &asdata, }; - isc_quota_t *quota = NULL; isc_statscounter_t srvfail_cnt; bool expect_servfail = false; @@ -899,7 +898,7 @@ run_hookasync_test(const ns__query_hookasync_test_params_t *test) { */ isc_quota_max(&sctx->recursionquota, 1); if (!test->quota_ok) { - result = isc_quota_attach(&sctx->recursionquota, "a); + result = isc_quota_acquire(&sctx->recursionquota); INSIST(result == ISC_R_SUCCESS); } @@ -953,7 +952,6 @@ run_hookasync_test(const ns__query_hookasync_test_params_t *test) { /* Confirm necessary cleanup has been performed. */ INSIST(qctx->client->query.hookactx == NULL); INSIST(qctx->client->state == NS_CLIENTSTATE_WORKING); - INSIST(QUOTA_RECTYPE_HOOK(qctx->client) == NULL); INSIST(ns_stats_get_counter( qctx->client->manager->sctx->nsstats, ns_statscounter_recursclients) == 0); @@ -993,8 +991,8 @@ run_hookasync_test(const ns__query_hookasync_test_params_t *test) { */ ns_test_qctx_destroy(&qctx); ns_hooktable_free(mctx, (void **)&ns__hook_table); - if (quota != NULL) { - isc_quota_detach("a); + if (!test->quota_ok) { + isc_quota_release(&sctx->recursionquota); } }