summaryrefslogtreecommitdiff
path: root/source3/lib/serverid.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib/serverid.c')
-rw-r--r--source3/lib/serverid.c291
1 files changed, 247 insertions, 44 deletions
diff --git a/source3/lib/serverid.c b/source3/lib/serverid.c
index 00dd6c4f8d..cb49520564 100644
--- a/source3/lib/serverid.c
+++ b/source3/lib/serverid.c
@@ -21,11 +21,16 @@
#include "system/filesys.h"
#include "serverid.h"
#include "util_tdb.h"
-#include "dbwrap.h"
-#include "lib/util/tdb_wrap.h"
+#include "dbwrap/dbwrap.h"
+#include "dbwrap/dbwrap_open.h"
+#include "lib/tdb_wrap/tdb_wrap.h"
+#include "lib/param/param.h"
+#include "ctdbd_conn.h"
+#include "messages.h"
struct serverid_key {
pid_t pid;
+ uint32_t task_id;
uint32_t vnn;
};
@@ -37,6 +42,13 @@ struct serverid_data {
bool serverid_parent_init(TALLOC_CTX *mem_ctx)
{
struct tdb_wrap *db;
+ struct loadparm_context *lp_ctx;
+
+ lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers());
+ if (lp_ctx == NULL) {
+ DEBUG(0, ("loadparm_init_s3 failed\n"));
+ return false;
+ }
/*
* Open the tdb in the parent process (smbd) so that our
@@ -46,7 +58,8 @@ bool serverid_parent_init(TALLOC_CTX *mem_ctx)
db = tdb_wrap_open(mem_ctx, lock_path("serverid.tdb"),
0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, O_RDWR|O_CREAT,
- 0644);
+ 0644, lp_ctx);
+ talloc_unlink(mem_ctx, lp_ctx);
if (db == NULL) {
DEBUG(1, ("could not open serverid.tdb: %s\n",
strerror(errno)));
@@ -63,7 +76,8 @@ static struct db_context *serverid_db(void)
return db;
}
db = db_open(NULL, lock_path("serverid.tdb"), 0,
- TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, O_RDWR|O_CREAT, 0644);
+ TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
+ O_RDWR|O_CREAT, 0644, DBWRAP_LOCK_ORDER_2);
return db;
}
@@ -72,6 +86,7 @@ static void serverid_fill_key(const struct server_id *id,
{
ZERO_STRUCTP(key);
key->pid = id->pid;
+ key->task_id = id->task_id;
key->vnn = id->vnn;
}
@@ -93,7 +108,7 @@ bool serverid_register(const struct server_id id, uint32_t msg_flags)
serverid_fill_key(&id, &key);
tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
- rec = db->fetch_locked(db, talloc_tos(), tdbkey);
+ rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey);
if (rec == NULL) {
DEBUG(1, ("Could not fetch_lock serverid.tdb record\n"));
return false;
@@ -104,12 +119,17 @@ bool serverid_register(const struct server_id id, uint32_t msg_flags)
data.msg_flags = msg_flags;
tdbdata = make_tdb_data((uint8_t *)&data, sizeof(data));
- status = rec->store(rec, tdbdata, 0);
+ status = dbwrap_record_store(rec, tdbdata, 0);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Storing serverid.tdb record failed: %s\n",
nt_errstr(status)));
goto done;
}
+#ifdef HAVE_CTDB_CONTROL_CHECK_SRVIDS_DECL
+ if (lp_clustering()) {
+ register_with_ctdbd(messaging_ctdbd_connection(), id.unique_id);
+ }
+#endif
ret = true;
done:
TALLOC_FREE(rec);
@@ -124,6 +144,7 @@ bool serverid_register_msg_flags(const struct server_id id, bool do_reg,
struct serverid_data *data;
struct db_record *rec;
TDB_DATA tdbkey;
+ TDB_DATA value;
NTSTATUS status;
bool ret = false;
@@ -135,20 +156,22 @@ bool serverid_register_msg_flags(const struct server_id id, bool do_reg,
serverid_fill_key(&id, &key);
tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
- rec = db->fetch_locked(db, talloc_tos(), tdbkey);
+ rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey);
if (rec == NULL) {
DEBUG(1, ("Could not fetch_lock serverid.tdb record\n"));
return false;
}
- if (rec->value.dsize != sizeof(struct serverid_data)) {
+ value = dbwrap_record_get_value(rec);
+
+ if (value.dsize != sizeof(struct serverid_data)) {
DEBUG(1, ("serverid record has unexpected size %d "
- "(wanted %d)\n", (int)rec->value.dsize,
+ "(wanted %d)\n", (int)value.dsize,
(int)sizeof(struct serverid_data)));
goto done;
}
- data = (struct serverid_data *)rec->value.dptr;
+ data = (struct serverid_data *)value.dptr;
if (do_reg) {
data->msg_flags |= msg_flags;
@@ -156,7 +179,7 @@ bool serverid_register_msg_flags(const struct server_id id, bool do_reg,
data->msg_flags &= ~msg_flags;
}
- status = rec->store(rec, rec->value, 0);
+ status = dbwrap_record_store(rec, value, 0);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Storing serverid.tdb record failed: %s\n",
nt_errstr(status)));
@@ -185,13 +208,13 @@ bool serverid_deregister(struct server_id id)
serverid_fill_key(&id, &key);
tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
- rec = db->fetch_locked(db, talloc_tos(), tdbkey);
+ rec = dbwrap_fetch_locked(db, talloc_tos(), tdbkey);
if (rec == NULL) {
DEBUG(1, ("Could not fetch_lock serverid.tdb record\n"));
return false;
}
- status = rec->delete_rec(rec);
+ status = dbwrap_record_delete(rec);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Deleting serverid.tdb record failed: %s\n",
nt_errstr(status)));
@@ -208,13 +231,14 @@ struct serverid_exists_state {
bool exists;
};
-static int server_exists_parse(TDB_DATA key, TDB_DATA data, void *priv)
+static void server_exists_parse(TDB_DATA key, TDB_DATA data, void *priv)
{
struct serverid_exists_state *state =
(struct serverid_exists_state *)priv;
if (data.dsize != sizeof(struct serverid_data)) {
- return -1;
+ state->exists = false;
+ return;
}
/*
@@ -223,43 +247,209 @@ static int server_exists_parse(TDB_DATA key, TDB_DATA data, void *priv)
*/
state->exists = (memcmp(&state->id->unique_id, data.dptr,
sizeof(state->id->unique_id)) == 0);
- return 0;
}
bool serverid_exists(const struct server_id *id)
{
- struct db_context *db;
- struct serverid_exists_state state;
- struct serverid_key key;
- TDB_DATA tdbkey;
+ bool result = false;
+ bool ok = false;
- if (procid_is_me(id)) {
- return true;
- }
-
- if (!process_exists(*id)) {
+ ok = serverids_exist(id, 1, &result);
+ if (!ok) {
return false;
}
- if (id->unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) {
- return true;
- }
+ return result;
+}
+
+bool serverids_exist(const struct server_id *ids, int num_ids, bool *results)
+{
+ int *todo_idx = NULL;
+ struct server_id *todo_ids = NULL;
+ bool *todo_results = NULL;
+ int todo_num = 0;
+ int *remote_idx = NULL;
+ int remote_num = 0;
+ int *verify_idx = NULL;
+ int verify_num = 0;
+ int t, idx;
+ bool result = false;
+ struct db_context *db;
db = serverid_db();
if (db == NULL) {
return false;
}
- serverid_fill_key(id, &key);
- tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
+ todo_idx = talloc_array(talloc_tos(), int, num_ids);
+ if (todo_idx == NULL) {
+ goto fail;
+ }
+ todo_ids = talloc_array(talloc_tos(), struct server_id, num_ids);
+ if (todo_ids == NULL) {
+ goto fail;
+ }
+ todo_results = talloc_array(talloc_tos(), bool, num_ids);
+ if (todo_results == NULL) {
+ goto fail;
+ }
+
+ remote_idx = talloc_array(talloc_tos(), int, num_ids);
+ if (remote_idx == NULL) {
+ goto fail;
+ }
+ verify_idx = talloc_array(talloc_tos(), int, num_ids);
+ if (verify_idx == NULL) {
+ goto fail;
+ }
- state.id = id;
- state.exists = false;
+ for (idx=0; idx<num_ids; idx++) {
+ results[idx] = false;
- if (db->parse_record(db, tdbkey, server_exists_parse, &state) == -1) {
- return false;
+ if (server_id_is_disconnected(&ids[idx])) {
+ continue;
+ }
+
+ if (procid_is_me(&ids[idx])) {
+ results[idx] = true;
+ continue;
+ }
+
+ if (procid_is_local(&ids[idx])) {
+ bool exists = process_exists_by_pid(ids[idx].pid);
+
+ if (!exists) {
+ continue;
+ }
+
+ if (ids[idx].unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) {
+ results[idx] = true;
+ continue;
+ }
+
+ verify_idx[verify_num] = idx;
+ verify_num += 1;
+ continue;
+ }
+
+ if (!lp_clustering()) {
+ continue;
+ }
+
+ remote_idx[remote_num] = idx;
+ remote_num += 1;
+ }
+
+#ifdef HAVE_CTDB_CONTROL_CHECK_SRVIDS_DECL
+ if (remote_num != 0) {
+ int old_remote_num = remote_num;
+
+ remote_num = 0;
+ todo_num = 0;
+
+ for (t=0; t<old_remote_num; t++) {
+ idx = remote_idx[t];
+
+ if (ids[idx].unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) {
+ remote_idx[remote_num] = idx;
+ remote_num += 1;
+ continue;
+ }
+
+ todo_idx[todo_num] = idx;
+ todo_ids[todo_num] = ids[idx];
+ todo_results[todo_num] = false;
+ todo_num += 1;
+ }
+
+ /*
+ * Note: this only uses CTDB_CONTROL_CHECK_SRVIDS
+ * to verify that the server_id still exists,
+ * which means only the server_id.unique_id and
+ * server_id.vnn are verified, while server_id.pid
+ * is not verified at all.
+ *
+ * TODO: do we want to verify server_id.pid somehow?
+ */
+ if (!ctdb_serverids_exist(messaging_ctdbd_connection(),
+ todo_ids, todo_num, todo_results))
+ {
+ goto fail;
+ }
+
+ for (t=0; t<todo_num; t++) {
+ idx = todo_idx[t];
+
+ results[idx] = todo_results[t];
+ }
}
- return state.exists;
+#endif
+
+ if (remote_num != 0) {
+ todo_num = 0;
+
+ for (t=0; t<remote_num; t++) {
+ idx = remote_idx[t];
+ todo_idx[todo_num] = idx;
+ todo_ids[todo_num] = ids[idx];
+ todo_results[todo_num] = false;
+ todo_num += 1;
+ }
+
+#ifdef CLUSTER_SUPPORT
+ if (!ctdb_processes_exist(messaging_ctdbd_connection(),
+ todo_ids, todo_num,
+ todo_results)) {
+ goto fail;
+ }
+#endif
+
+ for (t=0; t<todo_num; t++) {
+ idx = todo_idx[t];
+
+ if (!todo_results[t]) {
+ continue;
+ }
+
+ if (ids[idx].unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) {
+ results[idx] = true;
+ continue;
+ }
+
+ verify_idx[verify_num] = idx;
+ verify_num += 1;
+ }
+ }
+
+ for (t=0; t<verify_num; t++) {
+ struct serverid_exists_state state;
+ struct serverid_key key;
+ TDB_DATA tdbkey;
+ NTSTATUS status;
+
+ idx = verify_idx[t];
+
+ serverid_fill_key(&ids[idx], &key);
+ tdbkey = make_tdb_data((uint8_t *)&key, sizeof(key));
+
+ state.id = &ids[idx];
+ state.exists = false;
+ status = dbwrap_parse_record(db, tdbkey, server_exists_parse, &state);
+ if (!NT_STATUS_IS_OK(status)) {
+ results[idx] = false;
+ continue;
+ }
+ results[idx] = state.exists;
+ }
+
+ result = true;
+fail:
+ TALLOC_FREE(verify_idx);
+ TALLOC_FREE(remote_idx);
+ TALLOC_FREE(todo_results);
+ TALLOC_FREE(todo_ids);
+ TALLOC_FREE(todo_idx);
+ return result;
}
static bool serverid_rec_parse(const struct db_record *rec,
@@ -267,22 +457,28 @@ static bool serverid_rec_parse(const struct db_record *rec,
{
struct serverid_key key;
struct serverid_data data;
+ TDB_DATA tdbkey;
+ TDB_DATA tdbdata;
- if (rec->key.dsize != sizeof(key)) {
+ tdbkey = dbwrap_record_get_key(rec);
+ tdbdata = dbwrap_record_get_value(rec);
+
+ if (tdbkey.dsize != sizeof(key)) {
DEBUG(1, ("Found invalid key length %d in serverid.tdb\n",
- (int)rec->key.dsize));
+ (int)tdbkey.dsize));
return false;
}
- if (rec->value.dsize != sizeof(data)) {
+ if (tdbdata.dsize != sizeof(data)) {
DEBUG(1, ("Found invalid value length %d in serverid.tdb\n",
- (int)rec->value.dsize));
+ (int)tdbdata.dsize));
return false;
}
- memcpy(&key, rec->key.dptr, sizeof(key));
- memcpy(&data, rec->value.dptr, sizeof(data));
+ memcpy(&key, tdbkey.dptr, sizeof(key));
+ memcpy(&data, tdbdata.dptr, sizeof(data));
id->pid = key.pid;
+ id->task_id = key.task_id;
id->vnn = key.vnn;
id->unique_id = data.unique_id;
*msg_flags = data.msg_flags;
@@ -314,6 +510,7 @@ bool serverid_traverse_read(int (*fn)(const struct server_id *id,
{
struct db_context *db;
struct serverid_traverse_read_state state;
+ NTSTATUS status;
db = serverid_db();
if (db == NULL) {
@@ -321,7 +518,10 @@ bool serverid_traverse_read(int (*fn)(const struct server_id *id,
}
state.fn = fn;
state.private_data = private_data;
- return db->traverse_read(db, serverid_traverse_read_fn, &state);
+
+ status = dbwrap_traverse_read(db, serverid_traverse_read_fn, &state,
+ NULL);
+ return NT_STATUS_IS_OK(status);
}
struct serverid_traverse_state {
@@ -350,6 +550,7 @@ bool serverid_traverse(int (*fn)(struct db_record *rec,
{
struct db_context *db;
struct serverid_traverse_state state;
+ NTSTATUS status;
db = serverid_db();
if (db == NULL) {
@@ -357,7 +558,9 @@ bool serverid_traverse(int (*fn)(struct db_record *rec,
}
state.fn = fn;
state.private_data = private_data;
- return db->traverse(db, serverid_traverse_fn, &state);
+
+ status = dbwrap_traverse(db, serverid_traverse_fn, &state, NULL);
+ return NT_STATUS_IS_OK(status);
}
uint64_t serverid_get_random_unique_id(void)
@@ -366,7 +569,7 @@ uint64_t serverid_get_random_unique_id(void)
while (unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) {
generate_random_buffer((uint8_t *)&unique_id,
- sizeof(unique_id));
+ sizeof(unique_id));
}
return unique_id;