diff --git a/libcli/auth/netlogon_creds_cli.c b/libcli/auth/netlogon_creds_cli.c index 716a565128d..fec192bdae2 100644 --- a/libcli/auth/netlogon_creds_cli.c +++ b/libcli/auth/netlogon_creds_cli.c @@ -813,7 +813,8 @@ struct tevent_req *netlogon_creds_cli_lock_send(TALLOC_CTX *mem_ctx, subreq = g_lock_lock_send(state, ev, context->db.g_ctx, string_term_tdb_data(context->db.key_name), - G_LOCK_WRITE); + G_LOCK_WRITE, + NULL, NULL); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -1027,7 +1028,8 @@ struct tevent_req *netlogon_creds_cli_lck_send( subreq = g_lock_lock_send(state, ev, context->db.g_ctx, string_term_tdb_data(context->db.key_name), - gtype); + gtype, + NULL, NULL); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } diff --git a/source3/include/g_lock.h b/source3/include/g_lock.h index e3dd1b5c076..c96431346a6 100644 --- a/source3/include/g_lock.h +++ b/source3/include/g_lock.h @@ -74,7 +74,9 @@ struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct g_lock_ctx *ctx, TDB_DATA key, - enum g_lock_type type); + enum g_lock_type type, + g_lock_lock_cb_fn_t cb_fn, + void *cb_private); NTSTATUS g_lock_lock_recv(struct tevent_req *req); NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, TDB_DATA key, enum g_lock_type lock_type, struct timeval timeout); diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c index 7868a69a337..a22f9dcad06 100644 --- a/source3/lib/g_lock.c +++ b/source3/lib/g_lock.c @@ -990,7 +990,9 @@ struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct g_lock_ctx *ctx, TDB_DATA key, - enum g_lock_type type) + enum g_lock_type type, + g_lock_lock_cb_fn_t cb_fn, + void *cb_private) { struct tevent_req *req; struct g_lock_lock_state *state; @@ -1008,11 +1010,24 @@ struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx, state->ctx = ctx; state->key = key; state->type = type; + state->cb_fn = cb_fn; + state->cb_private = cb_private; fn_state = (struct g_lock_lock_fn_state) { .req_state = state, }; + /* + * We allow a cn_fn only for G_LOCK_WRITE for now. + * + * It's all we currently need and it makes a few things + * easier to implement. + */ + if (unlikely(cb_fn != NULL && type != G_LOCK_WRITE)) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_6); + return tevent_req_post(req, ev); + } + status = dbwrap_do_locked(ctx->db, key, g_lock_lock_fn, &fn_state); if (tevent_req_nterror(req, status)) { DBG_DEBUG("dbwrap_do_locked failed: %s\n", @@ -1113,6 +1128,9 @@ NTSTATUS g_lock_lock_recv(struct tevent_req *req) NTSTATUS status; if (tevent_req_is_nterror(req, &status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_WAS_UNLOCKED)) { + return NT_STATUS_OK; + } return status; } @@ -1278,7 +1296,7 @@ NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, TDB_DATA key, if (ev == NULL) { goto fail; } - req = g_lock_lock_send(frame, ev, ctx, key, type); + req = g_lock_lock_send(frame, ev, ctx, key, type, cb_fn, cb_private); if (req == NULL) { goto fail; } diff --git a/source3/torture/test_g_lock.c b/source3/torture/test_g_lock.c index 51133393960..57899e9e337 100644 --- a/source3/torture/test_g_lock.c +++ b/source3/torture/test_g_lock.c @@ -526,7 +526,7 @@ bool run_g_lock4(int dummy) goto fail; } - req = g_lock_lock_send(ev, ev, ctx, key, G_LOCK_WRITE); + req = g_lock_lock_send(ev, ev, ctx, key, G_LOCK_WRITE, NULL, NULL); if (req == NULL) { fprintf(stderr, "g_lock_lock send failed\n"); goto fail; @@ -657,7 +657,7 @@ bool run_g_lock4a(int dummy) goto fail; } - req = g_lock_lock_send(ev, ev, ctx, key, G_LOCK_WRITE); + req = g_lock_lock_send(ev, ev, ctx, key, G_LOCK_WRITE, NULL, NULL); if (req == NULL) { fprintf(stderr, "g_lock_lock send failed\n"); goto fail; @@ -1135,7 +1135,8 @@ bool run_g_lock7(int dummy) ev, ctx, key, - G_LOCK_UPGRADE); + G_LOCK_UPGRADE, + NULL, NULL); if (req == NULL) { fprintf(stderr, "g_lock_lock_send(UPGRADE) failed\n"); exit(1);