r23204: Add MSG_SMB_BRL_VALIDATE. Tridge, this is a bit different from your bzr
authorVolker Lendecke <vlendec@samba.org>
Tue, 29 May 2007 14:49:19 +0000 (14:49 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:22:53 +0000 (12:22 -0500)
branch, please check if it fulfils your needs.

Two changes: The validation is not done inside the brlock.c traverse_fn,
it's done as a separate routine.

Secondly, this patch does not call the checker routines in smbcontrol
directly but depends on a running smbd.
(This used to be commit 7e39d77c1f90d9025cab08918385d140e20ca25b)

source3/include/messages.h
source3/lib/messages.c
source3/locking/brlock.c
source3/smbd/server.c
source3/utils/smbcontrol.c

index cde104e8978b1124a8951dbd259a0ba23ffe984f..5ba2f45bd251df5da66b3645d522f5e57fdded0b 100644 (file)
  * Samba4 compatibility
  */
 #define MSG_PVFS_NOTIFY                        0x0310
+/*
+ * cluster reconfigure events
+ */
+#define MSG_SMB_BRL_VALIDATE           0x0311
+#define MSG_SMB_RELEASE_IP             0x0312
 
 /* winbind messages */
 #define MSG_WINBIND_FINISHED           0x0401
index 01683bf9eca3dbefe8390c51ce62efa21a0b9d3f..256d4d097ce9f039831d9db8fd559606a22b7b3a 100644 (file)
@@ -199,7 +199,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
        status = messaging_tdb_init(ctx, ctx, &ctx->local);
 
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(0, ("message_init failed: %s\n", nt_errstr(status)));
+               DEBUG(0, ("messaging_tdb_init failed: %s\n", nt_errstr(status)));
                TALLOC_FREE(ctx);
        }
 
index b51076bf433e4689e444d55b3f46ea04502c6bf0..a50d4faa52a96ea0aa75df310bf17149dbe770e9 100644 (file)
@@ -1686,3 +1686,109 @@ struct byte_range_lock *brl_get_locks_readonly(TALLOC_CTX *mem_ctx,
 {
        return brl_get_locks_internal(mem_ctx, fsp, True);
 }
+
+struct brl_revalidate_state {
+       ssize_t array_size;
+       uint32 num_pids;
+       struct server_id *pids;
+};
+
+/*
+ * Collect PIDs of all processes with pending entries
+ */
+
+static void brl_revalidate_collect(struct file_id id, struct server_id pid,
+                                  enum brl_type lock_type,
+                                  enum brl_flavour lock_flav,
+                                  br_off start, br_off size,
+                                  void *private_data)
+{
+       struct brl_revalidate_state *state =
+               (struct brl_revalidate_state *)private_data;
+
+       if (!IS_PENDING_LOCK(lock_type)) {
+               return;
+       }
+
+       add_to_large_array(state, sizeof(pid), (void *)&pid,
+                          &state->pids, &state->num_pids,
+                          &state->array_size);
+}
+
+/*
+ * qsort callback to sort the processes
+ */
+
+static int compare_procids(const void *p1, const void *p2)
+{
+       const struct server_id *i1 = (struct server_id *)i1;
+       const struct server_id *i2 = (struct server_id *)i2;
+
+       if (i1->pid < i2->pid) return -1;
+       if (i2->pid > i2->pid) return 1;
+       return 0;
+}
+
+/*
+ * Send a MSG_SMB_UNLOCK message to all processes with pending byte range
+ * locks so that they retry. Mainly used in the cluster code after a node has
+ * died.
+ *
+ * Done in two steps to avoid double-sends: First we collect all entries in an
+ * array, then qsort that array and only send to non-dupes.
+ */
+
+static void brl_revalidate(struct messaging_context *msg_ctx,
+                          void *private_data,
+                          uint32_t msg_type,
+                          struct server_id server_id,
+                          DATA_BLOB *data)
+{
+       struct brl_revalidate_state *state;
+       uint32 i;
+       struct server_id last_pid;
+
+       if (!(state = TALLOC_ZERO_P(NULL, struct brl_revalidate_state))) {
+               DEBUG(0, ("talloc failed\n"));
+               return;
+       }
+
+       brl_forall(brl_revalidate_collect, state);
+
+       if (state->array_size == -1) {
+               DEBUG(0, ("talloc failed\n"));
+               goto done;
+       }
+
+       if (state->num_pids == 0) {
+               goto done;
+       }
+
+       qsort(state->pids, state->num_pids, sizeof(state->pids[0]),
+             compare_procids);
+
+       ZERO_STRUCT(last_pid);
+
+       for (i=0; i<state->num_pids; i++) {
+               if (procid_equal(&last_pid, &state->pids[i])) {
+                       /*
+                        * We've seen that one already
+                        */
+                       continue;
+               }
+
+               messaging_send(msg_ctx, state->pids[i], MSG_SMB_UNLOCK,
+                              &data_blob_null);
+               last_pid = state->pids[i];
+       }
+
+ done:
+       TALLOC_FREE(state);
+       return;
+}
+
+void brl_register_msgs(struct messaging_context *msg_ctx)
+{
+       messaging_register(msg_ctx, NULL, MSG_SMB_BRL_VALIDATE,
+                          brl_revalidate);
+}
index fc1faa9d36c4e095ecd5e8f2ea08acd5cbe63556..f837d38ac6d908c133fb76cd80fd29109a65c0c7 100644 (file)
@@ -375,6 +375,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_
                           MSG_SMB_CONF_UPDATED, smb_conf_updated); 
        messaging_register(smbd_messaging_context(), NULL,
                           MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete);
+       brl_register_msgs(smbd_messaging_context());
 
 #ifdef DEVELOPER
        messaging_register(smbd_messaging_context(), NULL,
@@ -991,6 +992,7 @@ extern void build_options(BOOL screen);
        }
 
        /* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
+
        if (smbd_messaging_context() == NULL)
                exit(1);
 
index 2b927adb9650d955a961e74d487e06f606afa02e..1a1a190957b7671142b812658f4b29e3cbf275eb 100644 (file)
@@ -698,6 +698,34 @@ static BOOL do_closeshare(struct messaging_context *msg_ctx,
                            strlen(argv[1]) + 1);
 }
 
+/* force a blocking lock retry */
+
+static BOOL do_lockretry(struct messaging_context *msg_ctx,
+                        const struct server_id pid,
+                        const int argc, const char **argv)
+{
+       if (argc != 1) {
+               fprintf(stderr, "Usage: smbcontrol <dest> lockretry\n");
+               return False;
+       }
+
+       return send_message(msg_ctx, pid, MSG_SMB_UNLOCK, NULL, 0);
+}
+
+/* force a validation of all brl entries, including re-sends. */
+
+static BOOL do_brl_revalidate(struct messaging_context *msg_ctx,
+                             const struct server_id pid,
+                             const int argc, const char **argv)
+{
+       if (argc != 1) {
+               fprintf(stderr, "Usage: smbcontrol <dest> brl-revalidate\n");
+               return False;
+       }
+
+       return send_message(msg_ctx, pid, MSG_SMB_BRL_VALIDATE, NULL, 0);
+}
+
 /* Force a SAM synchronisation */
 
 static BOOL do_samsync(struct messaging_context *msg_ctx,
@@ -1037,6 +1065,8 @@ static const struct {
        { "debuglevel", do_debuglevel, "Display current debuglevels" },
        { "printnotify", do_printnotify, "Send a print notify message" },
        { "close-share", do_closeshare, "Forcibly disconnect a share" },
+       { "lockretry", do_lockretry, "Force a blocking lock retry" },
+       { "brl-revalidate", do_brl_revalidate, "Revalidate all brl entries" },
         { "samsync", do_samsync, "Initiate SAM synchronisation" },
         { "samrepl", do_samrepl, "Initiate SAM replication" },
        { "pool-usage", do_poolusage, "Display talloc memory usage" },