ctdb: when we fill the client packet queue we need to drop the client master
authorAndrew Tridgell <tridge@samba.org>
Thu, 4 Feb 2010 03:36:14 +0000 (14:36 +1100)
committerAndrew Tridgell <tridge@samba.org>
Thu, 4 Feb 2010 04:35:30 +0000 (15:35 +1100)
We can't just drop packets to the list, as those packets could be part
of the core protocol the client is using. This happens (for example)
when Samba is doing a traverse. If we drop a traverse packet then
Samba hangs indefinately. We are better off dropping the ctdb socket
to Samba.

server/ctdb_daemon.c

index 7fbbf3fffb73842a115db7b93e46c5d5fbc30d2e..5903f69635de40915bec544a56c7ff57fac74de3 100644 (file)
@@ -100,8 +100,9 @@ static int daemon_queue_send(struct ctdb_client *client, struct ctdb_req_header
        client->ctdb->statistics.client_packets_sent++;
        if (hdr->operation == CTDB_REQ_MESSAGE) {
                if (ctdb_queue_length(client->queue) > client->ctdb->tunable.max_queue_depth_drop_msg) {
-                       DEBUG(DEBUG_ERR,("Drop CTDB_REQ_MESSAGE to client. Queue full.\n"));
-                       return 0;
+                       DEBUG(DEBUG_ERR,("CTDB_REQ_MESSAGE queue full - killing client connection.\n"));
+                       talloc_free(client);
+                       return -1;
                }
        }
        return ctdb_queue_send(client->queue, (uint8_t *)hdr, hdr->length);
@@ -280,6 +281,10 @@ static void daemon_call_from_client_callback(struct ctdb_call_state *state)
        memcpy(&r->data[0], dstate->call->reply_data.dptr, r->datalen);
 
        res = daemon_queue_send(client, &r->hdr);
+       if (res == -1) {
+               /* client is dead - return immediately */
+               return;
+       }
        if (res != 0) {
                DEBUG(DEBUG_ERR, (__location__ " Failed to queue packet from daemon to client\n"));
        }
@@ -890,6 +895,7 @@ static void daemon_control_callback(struct ctdb_context *ctdb,
        struct ctdb_client *client = state->client;
        struct ctdb_reply_control *r;
        size_t len;
+       int ret;
 
        /* construct a message to send to the client containing the data */
        len = offsetof(struct ctdb_reply_control, data) + data.dsize;
@@ -910,9 +916,10 @@ static void daemon_control_callback(struct ctdb_context *ctdb,
                memcpy(&r->data[r->datalen], errormsg, r->errorlen);
        }
 
-       daemon_queue_send(client, &r->hdr);
-
-       talloc_free(state);
+       ret = daemon_queue_send(client, &r->hdr);
+       if (ret != -1) {
+               talloc_free(state);
+       }
 }
 
 /*