]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:g_lock: add g_lock_ctx->busy and assert it to false
authorStefan Metzmacher <metze@samba.org>
Sun, 28 Aug 2022 09:41:46 +0000 (11:41 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 20 Sep 2022 00:34:35 +0000 (00:34 +0000)
This prepares some helper functions in order to
allow callers of g_lock_lock() to pass in a callback function
that will run under the tdb chainlock when G_LOCK_WRITE was granted.

The idea is that the callers callback function would run with
g_lock_ctx->busy == true and all key based function are not be allowed
during the execution of the callback function. Only the
g_lock_lock_cb_state based helper function are allowed to be used.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15125

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/lib/g_lock.c

index 28b1dd8382cda7892581132e530a74ad3367b715..ec10e5b85148830695f9c5d9dad1b19ccff492e0 100644 (file)
@@ -37,6 +37,7 @@ struct g_lock_ctx {
        struct db_context *db;
        struct messaging_context *msg;
        enum dbwrap_lock_order lock_order;
+       bool busy;
 };
 
 struct g_lock {
@@ -198,7 +199,7 @@ struct g_lock_ctx *g_lock_ctx_init_backend(
 {
        struct g_lock_ctx *result;
 
-       result = talloc(mem_ctx, struct g_lock_ctx);
+       result = talloc_zero(mem_ctx, struct g_lock_ctx);
        if (result == NULL) {
                return NULL;
        }
@@ -938,6 +939,8 @@ struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx,
        NTSTATUS status;
        bool ok;
 
+       SMB_ASSERT(!ctx->busy);
+
        req = tevent_req_create(mem_ctx, &state, struct g_lock_lock_state);
        if (req == NULL) {
                return NULL;
@@ -1134,6 +1137,8 @@ NTSTATUS g_lock_lock(struct g_lock_ctx *ctx, TDB_DATA key,
        struct timeval end;
        NTSTATUS status;
 
+       SMB_ASSERT(!ctx->busy);
+
        if ((type == G_LOCK_READ) || (type == G_LOCK_WRITE)) {
                /*
                 * This is an abstraction violation: Normally we do
@@ -1291,6 +1296,8 @@ NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, TDB_DATA key)
        };
        NTSTATUS status;
 
+       SMB_ASSERT(!ctx->busy);
+
        status = dbwrap_do_locked(ctx->db, key, g_lock_unlock_fn, &state);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_WARNING("dbwrap_do_locked failed: %s\n",
@@ -1390,6 +1397,8 @@ NTSTATUS g_lock_writev_data(
        };
        NTSTATUS status;
 
+       SMB_ASSERT(!ctx->busy);
+
        status = dbwrap_do_locked(
                ctx->db, key, g_lock_writev_data_fn, &state);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1438,6 +1447,8 @@ int g_lock_locks(struct g_lock_ctx *ctx,
        NTSTATUS status;
        int count;
 
+       SMB_ASSERT(!ctx->busy);
+
        state.fn = fn;
        state.private_data = private_data;
 
@@ -1522,6 +1533,8 @@ NTSTATUS g_lock_dump(struct g_lock_ctx *ctx, TDB_DATA key,
        };
        NTSTATUS status;
 
+       SMB_ASSERT(!ctx->busy);
+
        status = dbwrap_parse_record(ctx->db, key, g_lock_dump_fn, &state);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_DEBUG("dbwrap_parse_record returned %s\n",
@@ -1554,6 +1567,8 @@ struct tevent_req *g_lock_dump_send(
        struct tevent_req *req = NULL, *subreq = NULL;
        struct g_lock_dump_state *state = NULL;
 
+       SMB_ASSERT(!ctx->busy);
+
        req = tevent_req_create(mem_ctx, &state, struct g_lock_dump_state);
        if (req == NULL) {
                return NULL;
@@ -1563,6 +1578,8 @@ struct tevent_req *g_lock_dump_send(
        state->fn = fn;
        state->private_data = private_data;
 
+       SMB_ASSERT(!ctx->busy);
+
        subreq = dbwrap_parse_record_send(
                state,
                ev,
@@ -1664,6 +1681,8 @@ struct tevent_req *g_lock_watch_data_send(
        struct g_lock_watch_data_state *state = NULL;
        NTSTATUS status;
 
+       SMB_ASSERT(!ctx->busy);
+
        req = tevent_req_create(
                mem_ctx, &state, struct g_lock_watch_data_state);
        if (req == NULL) {
@@ -1840,6 +1859,8 @@ void g_lock_wake_watchers(struct g_lock_ctx *ctx, TDB_DATA key)
 {
        NTSTATUS status;
 
+       SMB_ASSERT(!ctx->busy);
+
        status = dbwrap_do_locked(ctx->db, key, g_lock_wake_watchers_fn, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                DBG_DEBUG("dbwrap_do_locked returned %s\n",