mirror of
https://github.com/samba-team/samba.git
synced 2025-03-20 22:50:26 +03:00
merge from tridge
(This used to be ctdb commit 3457af559a5d54fd9eb787f18ff15d7c19271f60)
This commit is contained in:
commit
1bb55c1f77
@ -95,6 +95,7 @@ int ctdb_call_local(struct ctdb_db_context *ctdb_db, struct ctdb_call *call,
|
||||
}
|
||||
|
||||
if (c->new_data) {
|
||||
/* XXX check that we always have the lock here? */
|
||||
if (ctdb_ltdb_store(ctdb_db, call->key, header, *c->new_data) != 0) {
|
||||
ctdb_set_error(ctdb, "ctdb_call tdb_store failed\n");
|
||||
talloc_free(c);
|
||||
@ -292,6 +293,50 @@ static void ctdb_call_send_dmaster(struct ctdb_db_context *ctdb_db,
|
||||
talloc_free(r);
|
||||
}
|
||||
|
||||
/*
|
||||
called when a CTDB_REPLY_DMASTER packet comes in, or when the lmaster
|
||||
gets a CTDB_REQUEST_DMASTER for itself. We become the dmaster.
|
||||
|
||||
must be called with the chainlock held. This function releases the chainlock
|
||||
*/
|
||||
static void ctdb_become_dmaster(struct ctdb_context *ctdb,
|
||||
uint32_t reqid, TDB_DATA data)
|
||||
{
|
||||
struct ctdb_call_state *state;
|
||||
struct ctdb_db_context *ctdb_db;
|
||||
|
||||
state = idr_find_type(ctdb->idr, reqid, struct ctdb_call_state);
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctdb_db = state->ctdb_db;
|
||||
|
||||
DEBUG(2,("vnn %u dmaster response %08x\n",
|
||||
ctdb->vnn, ctdb_hash(&state->call.key)));
|
||||
|
||||
/* we're now the dmaster - update our local ltdb with new header
|
||||
and data */
|
||||
state->header.dmaster = ctdb->vnn;
|
||||
|
||||
if (ctdb_ltdb_store(ctdb_db, state->call.key, &state->header, data) != 0) {
|
||||
ctdb_fatal(ctdb, "ctdb_reply_dmaster store failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ctdb_call_local(ctdb_db, &state->call, &state->header, &data, ctdb->vnn);
|
||||
|
||||
ctdb_ltdb_unlock(ctdb_db, state->call.key);
|
||||
|
||||
talloc_steal(state, state->call.reply_data.dptr);
|
||||
|
||||
state->state = CTDB_CALL_DONE;
|
||||
if (state->async.fn) {
|
||||
state->async.fn(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
called when a CTDB_REQ_DMASTER packet comes in
|
||||
@ -331,17 +376,32 @@ void ctdb_request_dmaster(struct ctdb_context *ctdb, struct ctdb_req_header *hdr
|
||||
DEBUG(2,(__location__ " deferring ctdb_request_dmaster\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (ctdb_lmaster(ctdb, &key) != ctdb->vnn) {
|
||||
DEBUG(0,("vnn %u dmaster request to non-lmaster lmaster=%u\n",
|
||||
ctdb->vnn, ctdb_lmaster(ctdb, &key)));
|
||||
ctdb_fatal(ctdb, "ctdb_req_dmaster to non-lmaster");
|
||||
}
|
||||
|
||||
DEBUG(2,("vnn %u dmaster request on %08x for %u from %u\n",
|
||||
ctdb->vnn, ctdb_hash(&key), c->dmaster, c->hdr.srcnode));
|
||||
|
||||
/* its a protocol error if the sending node is not the current dmaster */
|
||||
if (header.dmaster != hdr->srcnode) {
|
||||
DEBUG(0,("vnn=%u dmaster request non-master %u dmaster=%u\n",
|
||||
ctdb->vnn, hdr->srcnode, header.dmaster));
|
||||
DEBUG(0,("vnn %u dmaster request non-master %u dmaster=%u key %08x\n",
|
||||
ctdb->vnn, hdr->srcnode, header.dmaster, ctdb_hash(&key)));
|
||||
ctdb_fatal(ctdb, "ctdb_req_dmaster from non-master");
|
||||
return;
|
||||
}
|
||||
|
||||
ctdb_send_dmaster_reply(ctdb_db, &header, key, data, c->dmaster, hdr->reqid);
|
||||
ctdb_ltdb_unlock(ctdb_db, key);
|
||||
/* check if the new dmaster is the lmaster, in which case we
|
||||
skip the dmaster reply */
|
||||
if (c->dmaster == ctdb->vnn) {
|
||||
ctdb_become_dmaster(ctdb, hdr->reqid, data);
|
||||
} else {
|
||||
ctdb_send_dmaster_reply(ctdb_db, &header, key, data, c->dmaster, hdr->reqid);
|
||||
ctdb_ltdb_unlock(ctdb_db, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -404,6 +464,8 @@ void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
|
||||
((header.laccessor == c->hdr.srcnode
|
||||
&& header.lacount >= ctdb->max_lacount)
|
||||
|| (c->flags&CTDB_IMMEDIATE_MIGRATION)) ) {
|
||||
DEBUG(2,("vnn %u starting migration of %08x to %u\n",
|
||||
ctdb->vnn, ctdb_hash(&call.key), c->hdr.srcnode));
|
||||
ctdb_call_send_dmaster(ctdb_db, c, &header, &call.key, &data);
|
||||
talloc_free(data.dptr);
|
||||
ctdb_ltdb_unlock(ctdb_db, call.key);
|
||||
@ -466,6 +528,7 @@ void ctdb_reply_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
called when a CTDB_REPLY_DMASTER packet comes in
|
||||
|
||||
@ -501,28 +564,7 @@ void ctdb_reply_dmaster(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
|
||||
data.dptr = c->data;
|
||||
data.dsize = c->datalen;
|
||||
|
||||
talloc_steal(state, c);
|
||||
|
||||
/* we're now the dmaster - update our local ltdb with new header
|
||||
and data */
|
||||
state->header.dmaster = ctdb->vnn;
|
||||
|
||||
if (ctdb_ltdb_store(ctdb_db, state->call.key, &state->header, data) != 0) {
|
||||
ctdb_ltdb_unlock(ctdb_db, state->call.key);
|
||||
ctdb_fatal(ctdb, "ctdb_reply_dmaster store failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ctdb_call_local(ctdb_db, &state->call, &state->header, &data, ctdb->vnn);
|
||||
|
||||
ctdb_ltdb_unlock(ctdb_db, state->call.key);
|
||||
|
||||
talloc_steal(state, state->call.reply_data.dptr);
|
||||
|
||||
state->state = CTDB_CALL_DONE;
|
||||
if (state->async.fn) {
|
||||
state->async.fn(state);
|
||||
}
|
||||
ctdb_become_dmaster(ctdb, hdr->reqid, data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -225,7 +225,11 @@ int ctdb_ltdb_lock(struct ctdb_db_context *ctdb_db, TDB_DATA key)
|
||||
*/
|
||||
int ctdb_ltdb_unlock(struct ctdb_db_context *ctdb_db, TDB_DATA key)
|
||||
{
|
||||
return tdb_chainunlock(ctdb_db->ltdb->tdb, key);
|
||||
int ret = tdb_chainunlock(ctdb_db->ltdb->tdb, key);
|
||||
if (ret != 0) {
|
||||
DEBUG(0,("tdb_chainunlock failed\n"));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct lock_fetch_state {
|
||||
|
@ -36,15 +36,25 @@ static void usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct node_info {
|
||||
uint32_t num_nodes;
|
||||
uint32_t vnn;
|
||||
};
|
||||
|
||||
static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *p)
|
||||
{
|
||||
int *num_nodes = (int *)p;
|
||||
struct node_info *info = (struct node_info *)p;
|
||||
struct id {
|
||||
dev_t dev;
|
||||
ino_t inode;
|
||||
} *id;
|
||||
struct ctdb_ltdb_header *h = (struct ctdb_ltdb_header *)data.dptr;
|
||||
char *keystr;
|
||||
uint32_t lmaster;
|
||||
int authoritative=0;
|
||||
|
||||
lmaster = ctdb_hash(&key) % info->num_nodes;
|
||||
|
||||
id = (struct id *)key.dptr;
|
||||
if (key.dsize == sizeof(*id)) {
|
||||
keystr = talloc_asprintf(NULL, "%llu:%llu",
|
||||
@ -52,10 +62,12 @@ static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi
|
||||
} else {
|
||||
keystr = hex_encode(NULL, key.dptr, key.dsize);
|
||||
}
|
||||
printf(" rec %s lmaster=%u dmaster=%u\n",
|
||||
authoritative = (info->vnn == lmaster || info->vnn == h->dmaster);
|
||||
printf(" rec %s lmaster=%u dmaster=%u %c\n",
|
||||
keystr,
|
||||
ctdb_hash(&key) % (*num_nodes),
|
||||
h->dmaster);
|
||||
lmaster,
|
||||
h->dmaster,
|
||||
authoritative?'A':' ');
|
||||
talloc_free(keystr);
|
||||
return 0;
|
||||
}
|
||||
@ -75,6 +87,7 @@ int main(int argc, const char *argv[])
|
||||
int i, extra_argc = 0;
|
||||
poptContext pc;
|
||||
struct tdb_wrap *db;
|
||||
struct node_info info;
|
||||
|
||||
pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
|
||||
|
||||
@ -107,7 +120,9 @@ int main(int argc, const char *argv[])
|
||||
}
|
||||
|
||||
printf("db %s\n", extra_argv[i]);
|
||||
tdb_traverse(db->tdb, traverse_fn, &extra_argc);
|
||||
info.vnn = i;
|
||||
info.num_nodes = extra_argc;
|
||||
tdb_traverse(db->tdb, traverse_fn, &info);
|
||||
|
||||
talloc_free(db);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ static void show_status(struct ctdb_status *s)
|
||||
printf(" req_status %u\n", s->client.req_status);
|
||||
printf(" node_packets_sent %u\n", s->node_packets_sent);
|
||||
printf(" node_packets_recv %u\n", s->node_packets_recv);
|
||||
printf(" req_call %u\n", s->client.req_call);
|
||||
printf(" req_call %u\n", s->count.req_call);
|
||||
printf(" reply_call %u\n", s->count.reply_call);
|
||||
printf(" reply_redirect %u\n", s->count.reply_redirect);
|
||||
printf(" req_dmaster %u\n", s->count.req_dmaster);
|
||||
|
Loading…
x
Reference in New Issue
Block a user