vacuum: in ctdb_vacuum_db, fix the length of the array of vacuum fetch lists
authorMichael Adam <obnox@samba.org>
Thu, 3 Feb 2011 11:18:58 +0000 (12:18 +0100)
committerMichael Adam <obnox@samba.org>
Wed, 9 Mar 2011 22:21:23 +0000 (23:21 +0100)
This patch fixes segfaults in the vacuum child when at least one
node has been stopped or removed from the cluster:

The size of the vnn_map is only the number of active nodes
(that can be lmaster). But the node numbers that are referenced
by the vnn_map spread over all configured nodes.

Since the array of vacuum fetch lists is referenced by the
key's lmaster's node number later on, the array needs to
be of size num_nodes instad of vnn_map->size.

server/ctdb_vacuum.c

index f299007380f3760a0337c91ed3a2842d1afad7bb..d6a16f52d65ab87344f4ba4bc18fa9dc94c3cf0a 100644 (file)
@@ -238,12 +238,12 @@ static int ctdb_vacuum_db(struct ctdb_db_context *ctdb_db, struct vacuum_data *v
 
        ctdb->pnn = pnn;
        /* the list needs to be of length num_nodes */
-       vdata->list = talloc_array(vdata, struct ctdb_marshall_buffer *, ctdb->vnn_map->size);
+       vdata->list = talloc_array(vdata, struct ctdb_marshall_buffer *, ctdb->num_nodes);
        if (vdata->list == NULL) {
                DEBUG(DEBUG_ERR,(__location__ " Out of memory\n"));
                return -1;
        }
-       for (i = 0; i < ctdb->vnn_map->size; i++) {
+       for (i = 0; i < ctdb->num_nodes; i++) {
                vdata->list[i] = (struct ctdb_marshall_buffer *)
                        talloc_zero_size(vdata->list, 
                                                         offsetof(struct ctdb_marshall_buffer, data));
@@ -261,22 +261,24 @@ static int ctdb_vacuum_db(struct ctdb_db_context *ctdb_db, struct vacuum_data *v
                return -1;              
        }
 
-       for ( i = 0; i < ctdb->vnn_map->size; i++) {
+       for (i = 0; i < ctdb->num_nodes; i++) {
                if (vdata->list[i]->count == 0) {
                        continue;
                }
 
                /* for records where we are not the lmaster, tell the lmaster to fetch the record */
-               if (ctdb->vnn_map->map[i] != ctdb->pnn) {
+               if (ctdb->nodes[i]->pnn != ctdb->pnn) {
                        TDB_DATA data;
-                       DEBUG(DEBUG_INFO,("Found %u records for lmaster %u in '%s'\n", 
-                                                               vdata->list[i]->count, i, name));
+                       DEBUG(DEBUG_INFO,
+                             ("Found %u records for lmaster %u in '%s'\n",
+                              vdata->list[i]->count, ctdb->nodes[i]->pnn,
+                              name));
 
                        data.dsize = talloc_get_size(vdata->list[i]);
                        data.dptr  = (void *)vdata->list[i];
-                       if (ctdb_client_send_message(ctdb, ctdb->vnn_map->map[i], CTDB_SRVID_VACUUM_FETCH, data) != 0) {
+                       if (ctdb_client_send_message(ctdb, ctdb->nodes[i]->pnn, CTDB_SRVID_VACUUM_FETCH, data) != 0) {
                                DEBUG(DEBUG_ERR,(__location__ " Failed to send vacuum fetch message to %u\n",
-                                        ctdb->vnn_map->map[i]));
+                                        ctdb->nodes[i]->pnn));
                                return -1;              
                        }
                        continue;