]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
dbwrap: Add "blocker" to record_watch_send
authorVolker Lendecke <vl@samba.org>
Thu, 10 Mar 2016 13:37:12 +0000 (14:37 +0100)
committerVolker Lendecke <vl@samba.org>
Fri, 15 Jul 2016 14:56:13 +0000 (16:56 +0200)
Typicall, when we watch a record, we wait for a process to give up some
resource. Be it an oplock, a share mode or the g_lock. If everything goes well,
the blocker sends us a message. If the blocker dies hard, we want to also be
informed immediately.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/lib/dbwrap/dbwrap_watch.c
source3/lib/dbwrap/dbwrap_watch.h
source3/lib/g_lock.c
source3/smbd/open.c
source3/smbd/smb2_setinfo.c
source3/smbd/smbXsrv_session.c
source3/torture/test_dbwrap_watch.c

index 09e67fb35b685ff2986bacc72cc48c47d51ffd0c..714c54d596f3f070027085d76740a9dd06c71216 100644 (file)
@@ -24,6 +24,7 @@
 #include "dbwrap_open.h"
 #include "lib/util/util_tdb.h"
 #include "lib/util/tevent_ntstatus.h"
+#include "server_id_watch.h"
 
 static struct db_context *dbwrap_record_watchers_db(void)
 {
@@ -199,18 +200,22 @@ struct dbwrap_record_watch_state {
        struct tevent_req *req;
        struct messaging_context *msg;
        TDB_DATA w_key;
+       bool blockerdead;
+       struct server_id blocker;
 };
 
 static bool dbwrap_record_watch_filter(struct messaging_rec *rec,
                                       void *private_data);
 static void dbwrap_record_watch_done(struct tevent_req *subreq);
+static void dbwrap_record_watch_blocker_died(struct tevent_req *subreq);
 static int dbwrap_record_watch_state_destructor(
        struct dbwrap_record_watch_state *state);
 
 struct tevent_req *dbwrap_record_watch_send(TALLOC_CTX *mem_ctx,
                                            struct tevent_context *ev,
                                            struct db_record *rec,
-                                           struct messaging_context *msg)
+                                           struct messaging_context *msg,
+                                           struct server_id blocker)
 {
        struct tevent_req *req, *subreq;
        struct dbwrap_record_watch_state *state;
@@ -226,6 +231,7 @@ struct tevent_req *dbwrap_record_watch_send(TALLOC_CTX *mem_ctx,
        state->ev = ev;
        state->req = req;
        state->msg = msg;
+       state->blocker = blocker;
 
        watchers_db = dbwrap_record_watchers_db();
        if (watchers_db == NULL) {
@@ -250,6 +256,15 @@ struct tevent_req *dbwrap_record_watch_send(TALLOC_CTX *mem_ctx,
        }
        tevent_req_set_callback(subreq, dbwrap_record_watch_done, req);
 
+       if (blocker.pid != 0) {
+               subreq = server_id_watch_send(state, ev, msg, blocker);
+               if (tevent_req_nomem(subreq, req)) {
+                       return tevent_req_post(req, ev);
+               }
+               tevent_req_set_callback(
+                       subreq, dbwrap_record_watch_blocker_died, req);
+       }
+
        status = dbwrap_record_add_watcher(
                state->w_key, messaging_server_id(state->msg));
        if (tevent_req_nterror(req, status)) {
@@ -371,9 +386,29 @@ static void dbwrap_record_watch_done(struct tevent_req *subreq)
        tevent_req_done(req);
 }
 
+static void dbwrap_record_watch_blocker_died(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct dbwrap_record_watch_state *state = tevent_req_data(
+               req, struct dbwrap_record_watch_state);
+       int ret;
+
+       ret = server_id_watch_recv(subreq, NULL);
+       TALLOC_FREE(subreq);
+       if (ret != 0) {
+               tevent_req_nterror(req, map_nt_error_from_unix(ret));
+               return;
+       }
+       state->blockerdead = true;
+       tevent_req_done(req);
+}
+
 NTSTATUS dbwrap_record_watch_recv(struct tevent_req *req,
                                  TALLOC_CTX *mem_ctx,
-                                 struct db_record **prec)
+                                 struct db_record **prec,
+                                 bool *blockerdead,
+                                 struct server_id *blocker)
 {
        struct dbwrap_record_watch_state *state = tevent_req_data(
                req, struct dbwrap_record_watch_state);
@@ -385,6 +420,12 @@ NTSTATUS dbwrap_record_watch_recv(struct tevent_req *req,
        if (tevent_req_is_nterror(req, &status)) {
                return status;
        }
+       if (blockerdead != NULL) {
+               *blockerdead = state->blockerdead;
+       }
+       if (blocker != NULL) {
+               *blocker = state->blocker;
+       }
        if (prec == NULL) {
                return NT_STATUS_OK;
        }
index 3362e45aba13fccea2b74342d540e3ca108baf16..b14128cb5d6ce29d66b9c5b4040aa3b69359ab7d 100644 (file)
@@ -29,10 +29,13 @@ void dbwrap_watch_db(struct db_context *db, struct messaging_context *msg);
 struct tevent_req *dbwrap_record_watch_send(TALLOC_CTX *mem_ctx,
                                            struct tevent_context *ev,
                                            struct db_record *rec,
-                                           struct messaging_context *msg);
+                                           struct messaging_context *msg,
+                                           struct server_id blocker);
 NTSTATUS dbwrap_record_watch_recv(struct tevent_req *req,
                                  TALLOC_CTX *mem_ctx,
-                                 struct db_record **prec);
+                                 struct db_record **prec,
+                                 bool *blockerdead,
+                                 struct server_id *blocker);
 
 void dbwrap_watchers_traverse_read(
        int (*fn)(const uint8_t *db_id, size_t db_id_len, const TDB_DATA key,
index 1928f5e56cb4aea2c910d1fd6052176e4fe972d9..1976291e896e5bdf2bdaa4fb1a2132caba8908d3 100644 (file)
@@ -237,7 +237,8 @@ struct tevent_req *g_lock_lock_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
        subreq = dbwrap_record_watch_send(state, state->ev, rec,
-                                         state->ctx->msg);
+                                         state->ctx->msg,
+                                         (struct server_id){0});
        TALLOC_FREE(rec);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
@@ -262,7 +263,8 @@ static void g_lock_lock_retry(struct tevent_req *subreq)
        struct db_record *rec;
        NTSTATUS status;
 
-       status = dbwrap_record_watch_recv(subreq, talloc_tos(), &rec);
+       status = dbwrap_record_watch_recv(subreq, talloc_tos(), &rec, NULL,
+                                         NULL);
        TALLOC_FREE(subreq);
 
        if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
@@ -291,7 +293,8 @@ static void g_lock_lock_retry(struct tevent_req *subreq)
                return;
        }
        subreq = dbwrap_record_watch_send(state, state->ev, rec,
-                                         state->ctx->msg);
+                                         state->ctx->msg,
+                                         (struct server_id){0});
        TALLOC_FREE(rec);
        if (tevent_req_nomem(subreq, req)) {
                return;
index 883c6ae46b7105096158f3de7a14db60a4c09ece..57cd4f1c1afa98cb020c1b5e8a2841dedf6083d9 100644 (file)
@@ -1954,7 +1954,7 @@ static void defer_open(struct share_mode_lock *lck,
 
                watch_req = dbwrap_record_watch_send(
                        watch_state, req->sconn->ev_ctx, lck->data->record,
-                       req->sconn->msg_ctx);
+                       req->sconn->msg_ctx, (struct server_id){0});
                if (watch_req == NULL) {
                        exit_server("Could not watch share mode record");
                }
@@ -1981,7 +1981,8 @@ static void defer_open_done(struct tevent_req *req)
        NTSTATUS status;
        bool ret;
 
-       status = dbwrap_record_watch_recv(req, talloc_tos(), NULL);
+       status = dbwrap_record_watch_recv(req, talloc_tos(), NULL, NULL,
+                                         NULL);
        TALLOC_FREE(req);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5, ("dbwrap_record_watch_recv returned %s\n",
index 2a0261042b0152716627948103d6448e7dd064d9..0a678ea04881ef790e93eab162235f0fdbe19dce 100644 (file)
@@ -252,7 +252,8 @@ static struct tevent_req *delay_rename_for_lease_break(struct tevent_req *req,
                                rename_state,
                                ev,
                                lck->data->record,
-                               fsp->conn->sconn->msg_ctx);
+                               fsp->conn->sconn->msg_ctx,
+                               (struct server_id){0});
 
        if (subreq == NULL) {
                exit_server("Could not watch share mode record for rename\n");
@@ -279,7 +280,8 @@ static void defer_rename_done(struct tevent_req *subreq)
        int ret_size = 0;
        bool ok;
 
-       status = dbwrap_record_watch_recv(subreq, state->req, NULL);
+       status = dbwrap_record_watch_recv(subreq, state->req, NULL, NULL,
+                                         NULL);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(5, ("dbwrap_record_watch_recv returned %s\n",
index cdad47f0e3d025b95f3c36c413f55850617300ec..51668c22a472821eb782e0b2d7cade3427450343 100644 (file)
@@ -1066,7 +1066,8 @@ static void smb2srv_session_close_previous_check(struct tevent_req *req)
        }
 
        subreq = dbwrap_record_watch_send(state, state->ev,
-                                         state->db_rec, conn->msg_ctx);
+                                         state->db_rec, conn->msg_ctx,
+                                         (struct server_id){0});
        if (tevent_req_nomem(subreq, req)) {
                TALLOC_FREE(state->db_rec);
                return;
@@ -1120,7 +1121,8 @@ static void smb2srv_session_close_previous_modified(struct tevent_req *subreq)
                struct smb2srv_session_close_previous_state);
        NTSTATUS status;
 
-       status = dbwrap_record_watch_recv(subreq, state, &state->db_rec);
+       status = dbwrap_record_watch_recv(subreq, state, &state->db_rec, NULL,
+                                         NULL);
        TALLOC_FREE(subreq);
        if (tevent_req_nterror(req, status)) {
                return;
index ab9330fffe985cd88ee84a3719e2a56d7ae6dc82..a912bd2d335aa30b89f909078756375a5e8757fa 100644 (file)
@@ -60,7 +60,8 @@ bool run_dbwrap_watch1(int dummy)
                fprintf(stderr, "dbwrap_fetch_locked failed\n");
                goto fail;
        }
-       req = dbwrap_record_watch_send(talloc_tos(), ev, rec, msg);
+       req = dbwrap_record_watch_send(talloc_tos(), ev, rec, msg,
+                                      (struct server_id){0});
        if (req == NULL) {
                fprintf(stderr, "dbwrap_record_watch_send failed\n");
                goto fail;
@@ -86,7 +87,8 @@ bool run_dbwrap_watch1(int dummy)
                goto fail;
        }
 
-       status = dbwrap_record_watch_recv(req, talloc_tos(), &rec);
+       status = dbwrap_record_watch_recv(req, talloc_tos(), &rec, NULL,
+                                         NULL);
        if (!NT_STATUS_IS_OK(status)) {
                fprintf(stderr, "dbwrap_record_watch_recv failed: %s\n",
                        nt_errstr(status));