diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c | 226 |
1 files changed, 189 insertions, 37 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c index 19a3cf7b10d..0c78596fec0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c @@ -1760,8 +1760,11 @@ out: * state, i.e either both would be hosting bricks or both would not be hosting * bricks, then a decision can't be taken and a peer-reject will happen. * - * glusterd_compare_and_update_snap() implements the following algorithm to - * perform the above task: + * glusterd_compare_snap() & glusterd_update_snaps () implement the following + * algorithm to perform the above task. Please note the former function tries to + * iterate over the snaps one at a time and updating the relevant fields in the + * dictionary and then glusterd_update_snaps () go over all the snaps and update + * them at one go as part of a synctask. * Step 1: Start. * Step 2: Check if the peer is missing a delete or restore on the said snap. * If yes, goto step 6. @@ -1786,21 +1789,18 @@ out: * */ int32_t -glusterd_compare_and_update_snap (dict_t *peer_data, int32_t snap_count, - char *peername, uuid_t peerid) +glusterd_compare_snap (dict_t *peer_data, int32_t snap_count, + char *peername, uuid_t peerid) { char buf[NAME_MAX] = ""; char prefix[NAME_MAX] = ""; char *peer_snap_name = NULL; char *peer_snap_id = NULL; - dict_t *dict = NULL; glusterd_snap_t *snap = NULL; gf_boolean_t conflict = _gf_false; gf_boolean_t is_local = _gf_false; gf_boolean_t is_hosted = _gf_false; gf_boolean_t missed_delete = _gf_false; - gf_boolean_t remove_lvm = _gf_true; - int32_t ret = -1; int32_t volcount = 0; xlator_t *this = NULL; @@ -1812,6 +1812,14 @@ glusterd_compare_and_update_snap (dict_t *peer_data, int32_t snap_count, snprintf (prefix, sizeof(prefix), "snap%d", snap_count); + ret = dict_set_uint32 (peer_data, buf, 0); + snprintf (buf, sizeof(buf), "%s.accept_peer_data", prefix); + ret = dict_set_uint32 (peer_data, buf, 0); + snprintf (buf, sizeof(buf), "%s.remove_lvm", prefix); + ret = dict_set_uint32 (peer_data, buf, 0); + snprintf (buf, sizeof(buf), "%s.remove_my_data", prefix); + ret = dict_set_uint32 (peer_data, buf, 0); + /* Fetch the peer's snapname */ snprintf (buf, sizeof(buf), "%s.snapname", prefix); ret = dict_get_str (peer_data, buf, &peer_snap_name); @@ -1868,7 +1876,10 @@ glusterd_compare_and_update_snap (dict_t *peer_data, int32_t snap_count, /* Peer has snap with the same snapname * and snap_id, which local node doesn't have. */ - goto accept_peer_data; + snprintf (buf, sizeof(buf), "%s.accept_peer_data", + prefix); + ret = dict_set_uint32 (peer_data, buf, 1); + goto out; } /* Peer has snap with the same snapname * and snap_id. Now check if peer has a @@ -1895,12 +1906,15 @@ glusterd_compare_and_update_snap (dict_t *peer_data, int32_t snap_count, * When removing data from local node, make sure * we are not removing backend lvm of the snap. */ - remove_lvm = _gf_false; - goto remove_my_data; + snprintf (buf, sizeof(buf), "%s.remove_lvm", prefix); + ret = dict_set_uint32 (peer_data, buf, 0); + snprintf (buf, sizeof(buf), "%s.remove_my_data", + prefix); + ret = dict_set_uint32 (peer_data, buf, 1); } else { ret = 0; - goto out; } + goto out; } /* There is a conflict. Check if the current node is @@ -1952,50 +1966,176 @@ glusterd_compare_and_update_snap (dict_t *peer_data, int32_t snap_count, * And local node isn't. Hence remove local node's * data and accept peer data */ - gf_msg_debug (this->name, 0, "Peer hosts bricks for conflicting " "snap(%s). Removing local data. Accepting peer data.", peer_snap_name); - remove_lvm = _gf_true; + snprintf (buf, sizeof(buf), "%s.remove_lvm", prefix); + ret = dict_set_uint32 (peer_data, buf, 1); + snprintf (buf, sizeof(buf), "%s.remove_my_data", + prefix); + ret = dict_set_uint32 (peer_data, buf, 1); + snprintf (buf, sizeof(buf), "%s.accept_peer_data", prefix); + ret = dict_set_uint32 (peer_data, buf, 1); -remove_my_data: +out: + gf_msg_trace (this->name, 0, "Returning %d", ret); + return ret; +} - dict = dict_new(); - if (!dict) { - gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_DICT_CREATE_FAIL, - "Unable to create dict"); - ret = -1; - goto out; +int32_t +glusterd_update_snaps_synctask (void *opaque) +{ + int32_t ret = -1; + int32_t snap_count = 0; + int i = 1; + xlator_t *this = NULL; + dict_t *peer_data = NULL; + char buf[NAME_MAX] = ""; + char prefix[NAME_MAX] = ""; + char *peer_snap_name = NULL; + char *peer_snap_id = NULL; + char *peername = NULL; + gf_boolean_t remove_lvm = _gf_false; + gf_boolean_t remove_my_data = _gf_false; + gf_boolean_t accept_peer_data = _gf_false; + int32_t val = 0; + glusterd_snap_t *snap = NULL; + dict_t *dict = NULL; + glusterd_conf_t *conf = NULL; + + this = THIS; + GF_ASSERT (this); + + conf = this->private; + GF_ASSERT (conf); + + peer_data = (dict_t *)opaque; + GF_ASSERT (peer_data); + + synclock_lock (&conf->big_lock); + + while (conf->restart_bricks) { + synclock_unlock (&conf->big_lock); + sleep (2); + synclock_lock (&conf->big_lock); } + conf->restart_bricks = _gf_true; - ret = glusterd_snap_remove (dict, snap, remove_lvm, _gf_false, - _gf_false); + ret = dict_get_int32 (peer_data, "snap_count", &snap_count); if (ret) { gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_SNAP_REMOVE_FAIL, - "Failed to remove snap %s", snap->snapname); + GD_MSG_DICT_GET_FAILED, "Failed to fetch snap_count"); goto out; } - -accept_peer_data: - - /* Accept Peer Data */ - ret = glusterd_import_friend_snap (peer_data, snap_count, - peer_snap_name, peer_snap_id); + ret = dict_get_str (peer_data, "peername", &peername); if (ret) { gf_msg (this->name, GF_LOG_ERROR, 0, - GD_MSG_SNAP_IMPORT_FAIL, - "Failed to import snap %s from peer %s", - peer_snap_name, peername); + GD_MSG_DICT_GET_FAILED, "Failed to fetch peername"); goto out; } + for (i = 1; i <= snap_count; i++) { + snprintf (prefix, sizeof(prefix), "snap%d", i); + + /* Fetch the peer's snapname */ + snprintf (buf, sizeof(buf), "%s.snapname", prefix); + ret = dict_get_str (peer_data, buf, &peer_snap_name); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_DICT_GET_FAILED, + "Unable to fetch snapname from peer: %s", + peername); + goto out; + } + + /* Fetch the peer's snap_id */ + snprintf (buf, sizeof(buf), "%s.snap_id", prefix); + ret = dict_get_str (peer_data, buf, &peer_snap_id); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_DICT_GET_FAILED, + "Unable to fetch snap_id from peer: %s", + peername); + goto out; + } + + /* remove_my_data */ + snprintf (buf, sizeof(buf), "%s.remove_my_data", prefix); + ret = dict_get_int32 (peer_data, buf, &val); + if (val) + remove_my_data = _gf_true; + else + remove_my_data = _gf_false; + + if (remove_my_data) { + snprintf (buf, sizeof(buf), "%s.remove_lvm", prefix); + ret = dict_get_int32 (peer_data, buf, &val); + if (val) + remove_lvm = _gf_true; + else + remove_lvm = _gf_false; + + dict = dict_new(); + if (!dict) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_DICT_CREATE_FAIL, + "Unable to create dict"); + ret = -1; + goto out; + } + snap = glusterd_find_snap_by_name (peer_snap_name); + if (!snap) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_MISSED_SNAP_PRESENT, + "Snapshot %s from peer %s missing on " + "localhost", peer_snap_name, + peername); + ret = -1; + goto out; + } + + ret = glusterd_snap_remove (dict, snap, remove_lvm, + _gf_false, _gf_false); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_SNAP_REMOVE_FAIL, + "Failed to remove snap %s", + snap->snapname); + goto out; + } + if (dict) + dict_unref (dict); + } + snprintf (buf, sizeof(buf), "%s.accept_peer_data", prefix); + ret = dict_get_int32 (peer_data, buf, &val); + if (val) + accept_peer_data = _gf_true; + else + accept_peer_data = _gf_false; + + if (accept_peer_data) { + /* Accept Peer Data */ + ret = glusterd_import_friend_snap (peer_data, + i, + peer_snap_name, + peer_snap_id); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_SNAP_IMPORT_FAIL, + "Failed to import snap %s from peer %s", + peer_snap_name, peername); + goto out; + } + } + } + out: + if (peer_data) + dict_unref (peer_data); if (dict) dict_unref (dict); + conf->restart_bricks = _gf_false; - gf_msg_trace (this->name, 0, "Returning %d", ret); return ret; } @@ -2010,6 +2150,7 @@ glusterd_compare_friend_snapshots (dict_t *peer_data, char *peername, int32_t snap_count = 0; int i = 1; xlator_t *this = NULL; + dict_t *peer_data_copy = NULL; this = THIS; GF_ASSERT (this); @@ -2025,8 +2166,7 @@ glusterd_compare_friend_snapshots (dict_t *peer_data, char *peername, for (i = 1; i <= snap_count; i++) { /* Compare one snapshot from peer_data at a time */ - ret = glusterd_compare_and_update_snap (peer_data, i, peername, - peerid); + ret = glusterd_compare_snap (peer_data, i, peername, peerid); if (ret) { gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_SNAPSHOT_OP_FAILED, @@ -2035,6 +2175,18 @@ glusterd_compare_friend_snapshots (dict_t *peer_data, char *peername, goto out; } } + /* Update the snaps at one go */ + peer_data_copy = dict_copy_with_ref (peer_data, NULL); + ret = dict_set_str (peer_data_copy, "peername", peername); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, + "Failed to set peername into the dict"); + if (peer_data_copy) + dict_unref (peer_data_copy); + goto out; + } + glusterd_launch_synctask (glusterd_update_snaps_synctask, + peer_data_copy); out: gf_msg_trace (this->name, 0, "Returning %d", ret); |