diff options
author | Avra Sengupta <asengupt@redhat.com> | 2015-01-06 07:40:32 +0000 |
---|---|---|
committer | Krishnan Parthasarathi <kparthas@redhat.com> | 2015-01-08 05:32:11 -0800 |
commit | 4056ed598f642d2d23a65b79495b0247d84db2f4 (patch) | |
tree | 71953b85a6d00edc22f71730499294371e27c7fc /xlators/mgmt/glusterd/src/glusterd-utils.c | |
parent | d0b07fae1fece688333888cfc408bc7c031ae8bf (diff) |
glusterd: Refactor glusterd-utils.c
Refactor glusterd-utils.c to create
glusterd-snapshot-utils.c consisting of all snapshot
utility functions.
Change-Id: Id9823a2aec9b115f9c040c9940f288d4fe753d9b
BUG: 1176770
Signed-off-by: Avra Sengupta <asengupt@redhat.com>
Reviewed-on: http://review.gluster.org/9391
Reviewed-by: Kaushal M <kaushal@redhat.com>
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
Tested-by: Krishnan Parthasarathi <kparthas@redhat.com>
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-utils.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 3681 |
1 files changed, 4 insertions, 3677 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 06ac43aaf4b..a7c7bd9cb88 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -52,6 +52,7 @@ #include "glusterd-locks.h" #include "glusterd-messages.h" #include "glusterd-volgen.h" +#include "glusterd-snapshot-utils.h" #include "xdr-generic.h" #include <sys/resource.h> @@ -648,223 +649,6 @@ gd_vol_is_geo_rep_active (glusterd_volinfo_t *volinfo) return active; } -/* - * glusterd_snap_geo_rep_restore: - * This function restores the atime and mtime of marker.tstamp - * if present from snapped marker.tstamp file. - */ -static int -glusterd_snap_geo_rep_restore (glusterd_volinfo_t *snap_volinfo, - glusterd_volinfo_t *new_volinfo) -{ - char vol_tstamp_file[PATH_MAX] = {0,}; - char snap_tstamp_file[PATH_MAX] = {0,}; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - int geo_rep_indexing_on = 0; - int ret = 0; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (snap_volinfo); - GF_ASSERT (new_volinfo); - - priv = this->private; - GF_ASSERT (priv); - - /* Check if geo-rep indexing is enabled, if yes, we need restore - * back the mtime of 'marker.tstamp' file. - */ - geo_rep_indexing_on = glusterd_volinfo_get_boolean (new_volinfo, - VKEY_MARKER_XTIME); - if (geo_rep_indexing_on == -1) { - gf_log (this->name, GF_LOG_DEBUG, "Failed" - " to check whether geo-rep-indexing enabled or not"); - ret = 0; - goto out; - } - - if (geo_rep_indexing_on == 1) { - GLUSTERD_GET_VOLUME_DIR (vol_tstamp_file, new_volinfo, priv); - strncat (vol_tstamp_file, "/marker.tstamp", - PATH_MAX - strlen(vol_tstamp_file) - 1); - GLUSTERD_GET_VOLUME_DIR (snap_tstamp_file, snap_volinfo, priv); - strncat (snap_tstamp_file, "/marker.tstamp", - PATH_MAX - strlen(snap_tstamp_file) - 1); - ret = gf_set_timestamp (snap_tstamp_file, vol_tstamp_file); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set atime and mtime of %s as of %s", - vol_tstamp_file, snap_tstamp_file); - goto out; - } - } - -out: - return ret; -} - -/* This function will copy snap volinfo to the new - * passed volinfo and regenerate backend store files - * for the restored snap. - * - * @param new_volinfo new volinfo - * @param snap_volinfo volinfo of snap volume - * - * @return 0 on success and -1 on failure - * - * TODO: Duplicate all members of volinfo, e.g. geo-rep sync slaves - */ -int32_t -glusterd_snap_volinfo_restore (dict_t *dict, dict_t *rsp_dict, - glusterd_volinfo_t *new_volinfo, - glusterd_volinfo_t *snap_volinfo, - int32_t volcount) -{ - char *value = NULL; - char key[PATH_MAX] = ""; - int32_t brick_count = -1; - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - glusterd_brickinfo_t *new_brickinfo = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (rsp_dict); - - GF_VALIDATE_OR_GOTO (this->name, new_volinfo, out); - GF_VALIDATE_OR_GOTO (this->name, snap_volinfo, out); - - brick_count = 0; - list_for_each_entry (brickinfo, &snap_volinfo->bricks, brick_list) { - brick_count++; - ret = glusterd_brickinfo_new (&new_brickinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to create " - "new brickinfo"); - goto out; - } - - /* Duplicate brickinfo */ - ret = glusterd_brickinfo_dup (brickinfo, new_brickinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to dup " - "brickinfo"); - goto out; - } - - /* Fetch values if present in dict These values won't - * be present in case of a missed restore. In that case - * it's fine to use the local node's value - */ - snprintf (key, sizeof (key), "snap%d.brick%d.path", - volcount, brick_count); - ret = dict_get_str (dict, key, &value); - if (!ret) - strncpy (new_brickinfo->path, value, - sizeof(new_brickinfo->path)); - - snprintf (key, sizeof (key), "snap%d.brick%d.snap_status", - volcount, brick_count); - ret = dict_get_int32 (dict, key, &new_brickinfo->snap_status); - - snprintf (key, sizeof (key), "snap%d.brick%d.device_path", - volcount, brick_count); - ret = dict_get_str (dict, key, &value); - if (!ret) - strncpy (new_brickinfo->device_path, value, - sizeof(new_brickinfo->device_path)); - - snprintf (key, sizeof (key), "snap%d.brick%d.fs_type", - volcount, brick_count); - ret = dict_get_str (dict, key, &value); - if (!ret) - strncpy (new_brickinfo->fstype, value, - sizeof(new_brickinfo->fstype)); - - snprintf (key, sizeof (key), "snap%d.brick%d.mnt_opts", - volcount, brick_count); - ret = dict_get_str (dict, key, &value); - if (!ret) - strncpy (new_brickinfo->mnt_opts, value, - sizeof(new_brickinfo->mnt_opts)); - - /* If the brick is not of this peer, or snapshot is missed * - * for the brick do not replace the xattr for it */ - if ((!uuid_compare (brickinfo->uuid, MY_UUID)) && - (brickinfo->snap_status != -1)) { - /* We need to replace the volume id of all the bricks - * to the volume id of the origin volume. new_volinfo - * has the origin volume's volume id*/ - ret = sys_lsetxattr (new_brickinfo->path, - GF_XATTR_VOL_ID_KEY, - new_volinfo->volume_id, - sizeof (new_volinfo->volume_id), - XATTR_REPLACE); - if (ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "Failed to " - "set extended attribute %s on %s. " - "Reason: %s, snap: %s", - GF_XATTR_VOL_ID_KEY, - new_brickinfo->path, strerror (errno), - new_volinfo->volname); - goto out; - } - } - - /* If a snapshot is pending for this brick then - * restore should also be pending - */ - if (brickinfo->snap_status == -1) { - /* Adding missed delete to the dict */ - ret = glusterd_add_missed_snaps_to_dict - (rsp_dict, - snap_volinfo, - brickinfo, - brick_count, - GF_SNAP_OPTION_TYPE_RESTORE); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to add missed snapshot info " - "for %s:%s in the rsp_dict", - brickinfo->hostname, - brickinfo->path); - goto out; - } - } - - list_add_tail (&new_brickinfo->brick_list, - &new_volinfo->bricks); - /* ownership of new_brickinfo is passed to new_volinfo */ - new_brickinfo = NULL; - } - - /* Regenerate all volfiles */ - ret = glusterd_create_volfiles_and_notify_services (new_volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to regenerate volfiles"); - goto out; - } - - /* Restore geo-rep marker.tstamp's timestamp */ - ret = glusterd_snap_geo_rep_restore (snap_volinfo, new_volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Geo-rep: marker.tstamp's timestamp restoration failed"); - goto out; - } - -out: - if (ret && (NULL != new_brickinfo)) { - (void) glusterd_brickinfo_delete (new_brickinfo); - } - - return ret; -} - void glusterd_auth_cleanup (glusterd_volinfo_t *volinfo) { @@ -1530,42 +1314,6 @@ glusterd_volinfo_find_by_volume_id (uuid_t volume_id, glusterd_volinfo_t **volin return ret; } -int -glusterd_snap_volinfo_find_by_volume_id (uuid_t volume_id, - glusterd_volinfo_t **volinfo) -{ - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_volinfo_t *voliter = NULL; - glusterd_snap_t *snap = NULL; - glusterd_conf_t *priv = NULL; - - this = THIS; - priv = this->private; - GF_ASSERT (priv); - GF_ASSERT (volinfo); - - if (uuid_is_null(volume_id)) { - gf_log (this->name, GF_LOG_WARNING, "Volume UUID is NULL"); - goto out; - } - - list_for_each_entry (snap, &priv->snapshots, snap_list) { - list_for_each_entry (voliter, &snap->volumes, vol_list) { - if (uuid_compare (volume_id, voliter->volume_id)) - continue; - *volinfo = voliter; - ret = 0; - goto out; - } - } - - gf_log (this->name, GF_LOG_WARNING, "Snap volume not found"); -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - int32_t glusterd_volinfo_find (char *volname, glusterd_volinfo_t **volinfo) { @@ -1596,68 +1344,6 @@ glusterd_volinfo_find (char *volname, glusterd_volinfo_t **volinfo) } int32_t -glusterd_snap_volinfo_find (char *snap_volname, glusterd_snap_t *snap, - glusterd_volinfo_t **volinfo) -{ - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_volinfo_t *snap_vol = NULL; - glusterd_conf_t *priv = NULL; - - this = THIS; - priv = this->private; - GF_ASSERT (priv); - GF_ASSERT (snap); - GF_ASSERT (snap_volname); - - list_for_each_entry (snap_vol, &snap->volumes, vol_list) { - if (!strcmp (snap_vol->volname, snap_volname)) { - ret = 0; - *volinfo = snap_vol; - goto out; - } - } - - gf_log (this->name, GF_LOG_WARNING, "Snap volume %s not found", - snap_volname); -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int32_t -glusterd_snap_volinfo_find_from_parent_volname (char *origin_volname, - glusterd_snap_t *snap, - glusterd_volinfo_t **volinfo) -{ - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_volinfo_t *snap_vol = NULL; - glusterd_conf_t *priv = NULL; - - this = THIS; - priv = this->private; - GF_ASSERT (priv); - GF_ASSERT (snap); - GF_ASSERT (origin_volname); - - list_for_each_entry (snap_vol, &snap->volumes, vol_list) { - if (!strcmp (snap_vol->parent_volname, origin_volname)) { - ret = 0; - *volinfo = snap_vol; - goto out; - } - } - - gf_log (this->name, GF_LOG_DEBUG, "Snap volume not found(snap: %s, " - "origin-volume: %s", snap->snapname, origin_volname); - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int32_t glusterd_service_stop (const char *service, char *pidfile, int sig, gf_boolean_t force_kill) { @@ -2368,154 +2054,6 @@ out: return ret; } -/* Exports a bricks snapshot details only if required - * - * The details will be exported only if the cluster op-version is greather than - * 4, ie. snapshot is supported in the cluster - */ -int -gd_add_brick_snap_details_to_dict (dict_t *dict, char *prefix, - glusterd_brickinfo_t *brickinfo) -{ - int ret = -1; - xlator_t *this = NULL; - glusterd_conf_t *conf = NULL; - char key[256] = {0,}; - - this = THIS; - GF_ASSERT (this != NULL); - conf = this->private; - GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); - - GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (brickinfo != NULL), out); - - if (conf->op_version < GD_OP_VERSION_3_6_0) { - ret = 0; - goto out; - } - - snprintf (key, sizeof (key), "%s.snap_status", prefix); - ret = dict_set_int32 (dict, key, brickinfo->snap_status); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set snap_status for %s:%s", - brickinfo->hostname, brickinfo->path); - goto out; - } - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.device_path", prefix); - ret = dict_set_str (dict, key, brickinfo->device_path); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set snap_device for %s:%s", - brickinfo->hostname, brickinfo->path); - goto out; - } - - snprintf (key, sizeof (key), "%s.fs_type", prefix); - ret = dict_set_str (dict, key, brickinfo->fstype); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set fstype for %s:%s", - brickinfo->hostname, brickinfo->path); - goto out; - } - - snprintf (key, sizeof (key), "%s.mnt_opts", prefix); - ret = dict_set_str (dict, key, brickinfo->mnt_opts); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set mnt_opts for %s:%s", - brickinfo->hostname, brickinfo->path); - goto out; - } - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.mount_dir", prefix); - ret = dict_set_str (dict, key, brickinfo->mount_dir); - if (ret) - gf_log (this->name, GF_LOG_ERROR, - "Failed to set mount_dir for %s:%s", - brickinfo->hostname, brickinfo->path); - -out: - return ret; -} - -/* Exports a volumes snapshot details only if required. - * - * The snapshot details will only be exported if the cluster op-version is - * greater than 4, ie. snapshot is supported in the cluster - */ -int -gd_add_vol_snap_details_to_dict (dict_t *dict, char *prefix, - glusterd_volinfo_t *volinfo) -{ - int ret = -1; - xlator_t *this = NULL; - glusterd_conf_t *conf = NULL; - char key[256] = {0,}; - - this = THIS; - GF_ASSERT (this != NULL); - conf = this->private; - GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); - - GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (volinfo != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out); - - if (conf->op_version < GD_OP_VERSION_3_6_0) { - ret =0; - goto out; - } - - snprintf (key, sizeof (key), "%s.restored_from_snap", prefix); - ret = dict_set_dynstr_with_alloc - (dict, key, - uuid_utoa (volinfo->restored_from_snap)); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Unable to set %s for volume" - "%s", key, volinfo->volname); - goto out; - } - - if (strlen (volinfo->parent_volname) > 0) { - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.parent_volname", prefix); - ret = dict_set_dynstr_with_alloc (dict, key, - volinfo->parent_volname); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Unable to set %s " - "for volume %s", key, volinfo->volname); - goto out; - } - } - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.is_snap_volume", prefix); - ret = dict_set_uint32 (dict, key, volinfo->is_snap_volume); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Unable to set %s for volume" - "%s", key, volinfo->volname); - goto out; - } - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.snap-max-hard-limit", prefix); - ret = dict_set_uint64 (dict, key, volinfo->snap_max_hard_limit); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Unable to set %s for volume" - "%s", key, volinfo->volname); - } - -out: - return ret; -} - /* The prefix represents the type of volume to be added. * It will be "volume" for normal volumes, and snap# like * snap1, snap2, for snapshot volumes @@ -2933,241 +2471,6 @@ out: } int32_t -glusterd_add_missed_snaps_to_export_dict (dict_t *peer_data) -{ - char name_buf[PATH_MAX] = ""; - char value[PATH_MAX] = ""; - int32_t missed_snap_count = 0; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_missed_snap_info *missed_snapinfo = NULL; - glusterd_snap_op_t *snap_opinfo = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (peer_data); - - priv = this->private; - GF_ASSERT (priv); - - /* Add the missed_entries in the dict */ - list_for_each_entry (missed_snapinfo, &priv->missed_snaps_list, - missed_snaps) { - list_for_each_entry (snap_opinfo, - &missed_snapinfo->snap_ops, - snap_ops_list) { - snprintf (name_buf, sizeof(name_buf), - "missed_snaps_%d", missed_snap_count); - snprintf (value, sizeof(value), "%s:%s=%s:%d:%s:%d:%d", - missed_snapinfo->node_uuid, - missed_snapinfo->snap_uuid, - snap_opinfo->snap_vol_id, - snap_opinfo->brick_num, - snap_opinfo->brick_path, - snap_opinfo->op, - snap_opinfo->status); - - ret = dict_set_dynstr_with_alloc (peer_data, name_buf, - value); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set %s", - name_buf); - goto out; - } - missed_snap_count++; - } - } - - ret = dict_set_int32 (peer_data, "missed_snap_count", - missed_snap_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set missed_snap_count"); - goto out; - } - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int32_t -glusterd_add_snap_to_dict (glusterd_snap_t *snap, dict_t *peer_data, - int32_t snap_count) -{ - char buf[NAME_MAX] = ""; - char prefix[NAME_MAX] = ""; - int32_t ret = -1; - int32_t volcount = 0; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - gf_boolean_t host_bricks = _gf_false; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (snap); - GF_ASSERT (peer_data); - - snprintf (prefix, sizeof(prefix), "snap%d", snap_count); - - list_for_each_entry (volinfo, &snap->volumes, vol_list) { - volcount++; - ret = glusterd_add_volume_to_dict (volinfo, peer_data, - volcount, prefix); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to add snap:%s volume:%s " - "to peer_data dict for handshake", - snap->snapname, volinfo->volname); - goto out; - } - - if (glusterd_is_volume_quota_enabled (volinfo)) { - - ret = glusterd_vol_add_quota_conf_to_dict (volinfo, - peer_data, - volcount, - prefix); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to add quota conf for " - "snap:%s volume:%s to peer_data " - "dict for handshake", snap->snapname, - volinfo->volname); - goto out; - } - } - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (!uuid_compare (brickinfo->uuid, MY_UUID)) { - host_bricks = _gf_true; - break; - } - } - } - - snprintf (buf, sizeof(buf), "%s.host_bricks", prefix); - ret = dict_set_int8 (peer_data, buf, (int8_t) host_bricks); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set host_bricks for snap %s", - snap->snapname); - goto out; - } - - snprintf (buf, sizeof(buf), "%s.volcount", prefix); - ret = dict_set_int32 (peer_data, buf, volcount); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set volcount for snap %s", - snap->snapname); - goto out; - } - - snprintf (buf, sizeof(buf), "%s.snapname", prefix); - ret = dict_set_dynstr_with_alloc (peer_data, buf, snap->snapname); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set snapname for snap %s", - snap->snapname); - goto out; - } - - snprintf (buf, sizeof(buf), "%s.snap_id", prefix); - ret = dict_set_dynstr_with_alloc (peer_data, buf, - uuid_utoa (snap->snap_id)); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set snap_id for snap %s", - snap->snapname); - goto out; - } - - if (snap->description) { - snprintf (buf, sizeof(buf), "%s.snapid", prefix); - ret = dict_set_dynstr_with_alloc (peer_data, buf, - snap->description); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set description for snap %s", - snap->snapname); - goto out; - } - } - - snprintf (buf, sizeof(buf), "%s.time_stamp", prefix); - ret = dict_set_int64 (peer_data, buf, (int64_t)snap->time_stamp); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set time_stamp for snap %s", - snap->snapname); - goto out; - } - - snprintf (buf, sizeof(buf), "%s.snap_restored", prefix); - ret = dict_set_int8 (peer_data, buf, snap->snap_restored); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set snap_restored for snap %s", - snap->snapname); - goto out; - } - - snprintf (buf, sizeof(buf), "%s.snap_status", prefix); - ret = dict_set_int32 (peer_data, buf, snap->snap_status); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set snap_status for snap %s", - snap->snapname); - goto out; - } -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int32_t -glusterd_add_snapshots_to_export_dict (dict_t *peer_data) -{ - int32_t snap_count = 0; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_snap_t *snap = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - GF_ASSERT (peer_data); - - list_for_each_entry (snap, &priv->snapshots, snap_list) { - snap_count++; - ret = glusterd_add_snap_to_dict (snap, peer_data, snap_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to add snap(%s) to the " - " peer_data dict for handshake", - snap->snapname); - goto out; - } - } - - ret = dict_set_int32 (peer_data, "snap_count", snap_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to set snap_count"); - goto out; - } - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int32_t glusterd_add_volumes_to_export_dict (dict_t **peer_data) { int32_t ret = -1; @@ -3781,82 +3084,6 @@ out: return ret; } -/* Imports the snapshot details of a brick if required and available - * - * Snapshot details will be imported only if the cluster op-verison is >= 4 - */ -int -gd_import_new_brick_snap_details (dict_t *dict, char *prefix, - glusterd_brickinfo_t *brickinfo) -{ - int ret = -1; - xlator_t *this = NULL; - glusterd_conf_t *conf = NULL; - char key[512] = {0,}; - char *snap_device = NULL; - char *fs_type = NULL; - char *mnt_opts = NULL; - char *mount_dir = NULL; - - this = THIS; - GF_ASSERT (this != NULL); - conf = this->private; - GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); - - GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (brickinfo != NULL), out); - - if (conf->op_version < GD_OP_VERSION_3_6_0) { - ret = 0; - goto out; - } - - snprintf (key, sizeof (key), "%s.snap_status", prefix); - ret = dict_get_int32 (dict, key, &brickinfo->snap_status); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s missing in payload", key); - goto out; - } - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.device_path", prefix); - ret = dict_get_str (dict, key, &snap_device); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s missing in payload", key); - goto out; - } - strcpy (brickinfo->device_path, snap_device); - - snprintf (key, sizeof (key), "%s.fs_type", prefix); - ret = dict_get_str (dict, key, &fs_type); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s missing in payload", key); - goto out; - } - strcpy (brickinfo->fstype, fs_type); - - snprintf (key, sizeof (key), "%s.mnt_opts", prefix); - ret = dict_get_str (dict, key, &mnt_opts); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s missing in payload", key); - goto out; - } - strcpy (brickinfo->mnt_opts, mnt_opts); - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.mount_dir", prefix); - ret = dict_get_str (dict, key, &mount_dir); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s missing in payload", key); - goto out; - } - strcpy (brickinfo->mount_dir, mount_dir); - -out: - return ret; -} - /* The prefix represents the type of volume to be added. * It will be "volume" for normal volumes, and snap# like * snap1, snap2, for snapshot volumes @@ -3987,7 +3214,7 @@ out: * It will be "volume" for normal volumes, and snap# like * snap1, snap2, for snapshot volumes */ -static int +int glusterd_import_quota_conf (dict_t *peer_data, int vol_idx, glusterd_volinfo_t *new_volinfo, char *prefix) @@ -4137,67 +3364,6 @@ out: return ret; } -/* - * Imports the snapshot details of a volume if required and available - * - * Snapshot details will be imported only if cluster.op_version is greater than - * or equal to GD_OP_VERSION_3_6_0, the op-version from which volume snapshot is - * supported. - */ -int -gd_import_volume_snap_details (dict_t *dict, glusterd_volinfo_t *volinfo, - char *prefix, char *volname) -{ - int ret = -1; - xlator_t *this = NULL; - glusterd_conf_t *conf = NULL; - char key[256] = {0,}; - char *restored_snap = NULL; - - this = THIS; - GF_ASSERT (this != NULL); - conf = this->private; - GF_VALIDATE_OR_GOTO (this->name, (conf != NULL), out); - - GF_VALIDATE_OR_GOTO (this->name, (dict != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (volinfo != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (prefix != NULL), out); - GF_VALIDATE_OR_GOTO (this->name, (volname != NULL), out); - - if (conf->op_version < GD_OP_VERSION_3_6_0) { - ret = 0; - goto out; - } - - snprintf (key, sizeof (key), "%s.is_snap_volume", prefix); - ret = dict_get_uint32 (dict, key, &volinfo->is_snap_volume); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s missing in payload " - "for %s", key, volname); - goto out; - } - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.restored_from_snap", prefix); - ret = dict_get_str (dict, key, &restored_snap); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s missing in payload " - "for %s", key, volname); - goto out; - } - - uuid_parse (restored_snap, volinfo->restored_from_snap); - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.snap-max-hard-limit", prefix); - ret = dict_get_uint64 (dict, key, - &volinfo->snap_max_hard_limit); - if (ret) - gf_log (this->name, GF_LOG_ERROR, "%s missing in payload " - "for %s", key, volname); -out: - return ret; -} /* The prefix represents the type of volume to be added. * It will be "volume" for normal volumes, and snap# like * snap1, snap2, for snapshot volumes @@ -4934,831 +4100,6 @@ out: } int32_t -glusterd_perform_missed_op (glusterd_snap_t *snap, int32_t op) -{ - dict_t *dict = NULL; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - glusterd_volinfo_t *snap_volinfo = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_volinfo_t *tmp = NULL; - xlator_t *this = NULL; - uuid_t null_uuid = {0}; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - GF_ASSERT (snap); - - dict = dict_new(); - if (!dict) { - gf_log (this->name, GF_LOG_ERROR, "Unable to create dict"); - ret = -1; - goto out; - } - - switch (op) { - case GF_SNAP_OPTION_TYPE_DELETE: - ret = glusterd_snap_remove (dict, snap, _gf_true, _gf_false); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to remove snap"); - goto out; - } - - break; - case GF_SNAP_OPTION_TYPE_RESTORE: - list_for_each_entry_safe (snap_volinfo, tmp, - &snap->volumes, vol_list) { - ret = glusterd_volinfo_find - (snap_volinfo->parent_volname, - &volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Could not get volinfo of %s", - snap_volinfo->parent_volname); - goto out; - } - - volinfo->version--; - uuid_copy (volinfo->restored_from_snap, null_uuid); - - /* gd_restore_snap_volume() uses the dict and volcount - * to fetch snap brick info from other nodes, which were - * collected during prevalidation. As this is an ad-hoc - * op and only local node's data matter, hence sending - * volcount as 0 and re-using the same dict because we - * need not record any missed creates in the rsp_dict. - */ - ret = gd_restore_snap_volume (dict, dict, volinfo, - snap_volinfo, 0); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to restore snap for %s", - snap->snapname); - volinfo->version++; - goto out; - } - - ret = glusterd_snapshot_restore_cleanup (dict, volinfo, - snap); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to perform snapshot restore " - "cleanup for %s volume", - snap_volinfo->parent_volname); - goto out; - } - } - - break; - default: - /* The entry must be a create, delete, or - * restore entry - */ - gf_log (this->name, GF_LOG_ERROR, "Invalid missed snap entry"); - ret = -1; - goto out; - } - -out: - dict_unref (dict); - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -/* Perform missed deletes and restores on this node */ -int32_t -glusterd_perform_missed_snap_ops () -{ - int32_t ret = -1; - int32_t op_status = -1; - glusterd_conf_t *priv = NULL; - glusterd_missed_snap_info *missed_snapinfo = NULL; - glusterd_snap_op_t *snap_opinfo = NULL; - glusterd_snap_t *snap = NULL; - uuid_t snap_uuid = {0,}; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - list_for_each_entry (missed_snapinfo, &priv->missed_snaps_list, - missed_snaps) { - /* If the pending snap_op is not for this node then continue */ - if (strcmp (missed_snapinfo->node_uuid, uuid_utoa (MY_UUID))) - continue; - - /* Find the snap id */ - uuid_parse (missed_snapinfo->snap_uuid, snap_uuid); - snap = NULL; - snap = glusterd_find_snap_by_id (snap_uuid); - if (!snap) { - /* If the snap is not found, then a delete or a - * restore can't be pending on that snap_uuid. - */ - gf_log (this->name, GF_LOG_DEBUG, - "Not a pending delete or restore op"); - continue; - } - - op_status = GD_MISSED_SNAP_PENDING; - list_for_each_entry (snap_opinfo, &missed_snapinfo->snap_ops, - snap_ops_list) { - /* If the snap_op is create or its status is - * GD_MISSED_SNAP_DONE then continue - */ - if ((snap_opinfo->status == GD_MISSED_SNAP_DONE) || - (snap_opinfo->op == GF_SNAP_OPTION_TYPE_CREATE)) - continue; - - /* Perform the actual op for the first time for - * this snap, and mark the snap_status as - * GD_MISSED_SNAP_DONE. For other entries for the same - * snap, just mark the entry as done. - */ - if (op_status == GD_MISSED_SNAP_PENDING) { - ret = glusterd_perform_missed_op - (snap, - snap_opinfo->op); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to perform missed snap op"); - goto out; - } - op_status = GD_MISSED_SNAP_DONE; - } - - snap_opinfo->status = GD_MISSED_SNAP_DONE; - } - } - - ret = 0; -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -/* Import friend volumes missed_snap_list and update * - * missed_snap_list if need be */ -int32_t -glusterd_import_friend_missed_snap_list (dict_t *peer_data) -{ - int32_t missed_snap_count = -1; - int32_t ret = -1; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (peer_data); - - priv = this->private; - GF_ASSERT (priv); - - /* Add the friends missed_snaps entries to the in-memory list */ - ret = dict_get_int32 (peer_data, "missed_snap_count", - &missed_snap_count); - if (ret) { - gf_log (this->name, GF_LOG_INFO, - "No missed snaps"); - ret = 0; - goto out; - } - - ret = glusterd_add_missed_snaps_to_list (peer_data, - missed_snap_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to add missed snaps to list"); - goto out; - } - - ret = glusterd_perform_missed_snap_ops (); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to perform snap operations"); - /* Not going to out at this point coz some * - * missed ops might have been performed. We * - * need to persist the current list * - */ - } - - ret = glusterd_store_update_missed_snaps (); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to update missed_snaps_list"); - goto out; - } - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -/* Check for the peer_snap_name in the list of existing snapshots. - * If a snap exists with the same name and a different snap_id, then - * there is a conflict. Set conflict as _gf_true, and snap to the - * conflicting snap object. If a snap exists with the same name, and the - * same snap_id, then there is no conflict. Set conflict as _gf_false - * and snap to the existing snap object. If no snap exists with the - * peer_snap_name, then there is no conflict. Set conflict as _gf_false - * and snap to NULL. - */ -void -glusterd_is_peer_snap_conflicting (char *peer_snap_name, char *peer_snap_id, - gf_boolean_t *conflict, - glusterd_snap_t **snap, char *hostname) -{ - uuid_t peer_snap_uuid = {0,}; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (peer_snap_name); - GF_ASSERT (peer_snap_id); - GF_ASSERT (conflict); - GF_ASSERT (snap); - GF_ASSERT (hostname); - - *snap = glusterd_find_snap_by_name (peer_snap_name); - if (*snap) { - uuid_parse (peer_snap_id, peer_snap_uuid); - if (!uuid_compare (peer_snap_uuid, (*snap)->snap_id)) { - /* Current node contains the same snap having - * the same snapname and snap_id - */ - gf_log (this->name, GF_LOG_DEBUG, - "Snapshot %s from peer %s present in " - "localhost", peer_snap_name, hostname); - *conflict = _gf_false; - } else { - /* Current node contains the same snap having - * the same snapname but different snap_id - */ - gf_log (this->name, GF_LOG_DEBUG, - "Snapshot %s from peer %s conflicts with " - "snapshot in localhost", peer_snap_name, - hostname); - *conflict = _gf_true; - } - } else { - /* Peer contains snapshots missing on the current node */ - gf_log (this->name, GF_LOG_INFO, - "Snapshot %s from peer %s missing on localhost", - peer_snap_name, hostname); - *conflict = _gf_false; - } -} - -/* Check if the local node is hosting any bricks for the given snapshot */ -gf_boolean_t -glusterd_are_snap_bricks_local (glusterd_snap_t *snap) -{ - gf_boolean_t is_local = _gf_false; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (snap); - - list_for_each_entry (volinfo, &snap->volumes, vol_list) { - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (!uuid_compare (brickinfo->uuid, MY_UUID)) { - is_local = _gf_true; - goto out; - } - } - } - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", is_local); - return is_local; -} - -/* Check if the peer has missed any snap delete - * or restore for the given snap_id - */ -gf_boolean_t -glusterd_peer_has_missed_snap_delete (glusterd_peerinfo_t *peerinfo, - char *peer_snap_id) -{ - char *peer_uuid = NULL; - gf_boolean_t missed_delete = _gf_false; - glusterd_conf_t *priv = NULL; - glusterd_missed_snap_info *missed_snapinfo = NULL; - glusterd_snap_op_t *snap_opinfo = NULL; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - GF_ASSERT (peerinfo); - GF_ASSERT (peer_snap_id); - - peer_uuid = uuid_utoa (peerinfo->uuid); - - list_for_each_entry (missed_snapinfo, &priv->missed_snaps_list, - missed_snaps) { - /* Look for missed snap for the same peer, and - * the same snap_id - */ - if ((!strcmp (peer_uuid, missed_snapinfo->node_uuid)) && - (!strcmp (peer_snap_id, missed_snapinfo->snap_uuid))) { - /* Check if the missed snap's op is delete and the - * status is pending - */ - list_for_each_entry (snap_opinfo, - &missed_snapinfo->snap_ops, - snap_ops_list) { - if (((snap_opinfo->op == - GF_SNAP_OPTION_TYPE_DELETE) || - (snap_opinfo->op == - GF_SNAP_OPTION_TYPE_RESTORE)) && - (snap_opinfo->status == - GD_MISSED_SNAP_PENDING)) { - missed_delete = _gf_true; - goto out; - } - } - } - } - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", missed_delete); - return missed_delete; -} - -/* Genrate and store snap volfiles for imported snap object */ -int32_t -glusterd_gen_snap_volfiles (glusterd_volinfo_t *snap_vol, char *peer_snap_name) -{ - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_volinfo_t *parent_volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (snap_vol); - GF_ASSERT (peer_snap_name); - - ret = glusterd_store_volinfo (snap_vol, GLUSTERD_VOLINFO_VER_AC_NONE); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to store snapshot " - "volinfo (%s) for snap %s", snap_vol->volname, - peer_snap_name); - goto out; - } - - ret = generate_brick_volfiles (snap_vol); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "generating the brick volfiles for the " - "snap %s failed", peer_snap_name); - goto out; - } - - ret = generate_client_volfiles (snap_vol, GF_CLIENT_TRUSTED); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "generating the trusted client volfiles for " - "the snap %s failed", peer_snap_name); - goto out; - } - - ret = generate_client_volfiles (snap_vol, GF_CLIENT_OTHER); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "generating the client volfiles for the " - "snap %s failed", peer_snap_name); - goto out; - } - - ret = glusterd_volinfo_find (snap_vol->parent_volname, - &parent_volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Parent volinfo " - "not found for %s volume of snap %s", - snap_vol->volname, peer_snap_name); - goto out; - } - - glusterd_list_add_snapvol (parent_volinfo, snap_vol); - - snap_vol->status = GLUSTERD_STATUS_STARTED; - - ret = glusterd_store_volinfo (snap_vol, GLUSTERD_VOLINFO_VER_AC_NONE); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to store snap volinfo"); - goto out; - } -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -/* Import snapshot info from peer_data and add it to priv */ -int32_t -glusterd_import_friend_snap (dict_t *peer_data, int32_t snap_count, - char *peer_snap_name, char *peer_snap_id) -{ - char buf[NAME_MAX] = ""; - char prefix[NAME_MAX] = ""; - dict_t *dict = NULL; - glusterd_snap_t *snap = NULL; - glusterd_volinfo_t *snap_vol = NULL; - glusterd_conf_t *priv = NULL; - int32_t ret = -1; - int32_t volcount = -1; - int32_t i = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - GF_ASSERT (peer_data); - GF_ASSERT (peer_snap_name); - GF_ASSERT (peer_snap_id); - - snprintf (prefix, sizeof(prefix), "snap%d", snap_count); - - snap = glusterd_new_snap_object (); - if (!snap) { - gf_log (this->name, GF_LOG_ERROR, "Could not create " - "the snap object for snap %s", peer_snap_name); - goto out; - } - - dict = dict_new (); - if (!dict) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to create dict"); - ret = -1; - goto out; - } - - strcpy (snap->snapname, peer_snap_name); - uuid_parse (peer_snap_id, snap->snap_id); - - snprintf (buf, sizeof(buf), "%s.snapid", prefix); - ret = dict_get_str (peer_data, buf, &snap->description); - - snprintf (buf, sizeof(buf), "%s.time_stamp", prefix); - ret = dict_get_int64 (peer_data, buf, &snap->time_stamp); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to get time_stamp for snap %s", - peer_snap_name); - goto out; - } - - snprintf (buf, sizeof(buf), "%s.snap_restored", prefix); - ret = dict_get_int8 (peer_data, buf, (int8_t *) &snap->snap_restored); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to get snap_restored for snap %s", - peer_snap_name); - goto out; - } - - snprintf (buf, sizeof(buf), "%s.snap_status", prefix); - ret = dict_get_int32 (peer_data, buf, (int32_t *) &snap->snap_status); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to get snap_status for snap %s", - peer_snap_name); - goto out; - } - - /* If the snap is scheduled to be decommissioned, then - * don't accept the snap */ - if (snap->snap_status == GD_SNAP_STATUS_DECOMMISSION) { - gf_log (this->name, GF_LOG_DEBUG, - "The snap(%s) is scheduled to be decommissioned " - "Not accepting the snap.", peer_snap_name); - glusterd_snap_remove (dict, snap, - _gf_true, _gf_true); - ret = 0; - goto out; - } - - snprintf (buf, sizeof(buf), "%s.volcount", prefix); - ret = dict_get_int32 (peer_data, buf, &volcount); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to get volcount for snap %s", - peer_snap_name); - goto out; - } - - ret = glusterd_store_create_snap_dir (snap); - if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, "Failed to create snap dir"); - goto out; - } - - list_add_order (&snap->snap_list, &priv->snapshots, - glusterd_compare_snap_time); - - for (i = 1; i <= volcount; i++) { - ret = glusterd_import_volinfo (peer_data, i, - &snap_vol, prefix); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to import snap volinfo for " - "snap %s", peer_snap_name); - goto out; - } - - snap_vol->snapshot = snap; - - ret = glusterd_gen_snap_volfiles (snap_vol, peer_snap_name); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to generate snap vol files " - "for snap %s", peer_snap_name); - goto out; - } - - ret = glusterd_import_quota_conf (peer_data, i, - snap_vol, prefix); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to import quota conf " - "for snap %s", peer_snap_name); - goto out; - } - - snap_vol = NULL; - } - - ret = glusterd_store_snap (snap); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, "Could not store snap" - "object %s", peer_snap_name); - goto out; - } - -out: - if (ret) - glusterd_snap_remove (dict, snap, - _gf_true, _gf_true); - - if (dict) - dict_unref (dict); - - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -/* During a peer-handshake, after the volumes have synced, and the list of - * missed snapshots have synced, the node will perform the pending deletes - * and restores on this list. At this point, the current snapshot list in - * the node will be updated, and hence in case of conflicts arising during - * snapshot handshake, the peer hosting the bricks will be given precedence - * Likewise, if there will be a conflict, and both peers will be in the same - * 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: - * Step 1: Start. - * Step 2: Check if the peer is missing a delete or restore on the said snap. - * If yes, goto step 6. - * Step 3: Check if there is a conflict between the peer's data and the - * local snap. If no, goto step 5. - * Step 4: As there is a conflict, check if both the peer and the local nodes - * are hosting bricks. Based on the results perform the following: - * Peer Hosts Bricks Local Node Hosts Bricks Action - * Yes Yes Goto Step 7 - * No No Goto Step 7 - * Yes No Goto Step 8 - * No Yes Goto Step 6 - * Step 5: Check if the local node is missing the peer's data. - * If yes, goto step 9. - * Step 6: It's a no-op. Goto step 10 - * Step 7: Peer Reject. Goto step 10 - * Step 8: Delete local node's data. - * Step 9: Accept Peer Data. - * Step 10: Stop - * - */ -int32_t -glusterd_compare_and_update_snap (dict_t *peer_data, int32_t snap_count, - glusterd_peerinfo_t *peerinfo) -{ - 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; - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (peer_data); - GF_ASSERT (peerinfo); - - snprintf (prefix, sizeof(prefix), "snap%d", snap_count); - - /* 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_log (this->name, GF_LOG_ERROR, - "Unable to fetch snapname from peer: %s", - peerinfo->hostname); - 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_log (this->name, GF_LOG_ERROR, - "Unable to fetch snap_id from peer: %s", - peerinfo->hostname); - goto out; - } - - /* Check if the peer has missed a snap delete or restore - * resulting in stale data for the snap in question - */ - missed_delete = glusterd_peer_has_missed_snap_delete (peerinfo, - peer_snap_id); - if (missed_delete == _gf_true) { - /* Peer has missed delete on the missing/conflicting snap_id */ - gf_log (this->name, GF_LOG_INFO, "Peer %s has missed a delete " - "on snap %s", peerinfo->hostname, peer_snap_name); - ret = 0; - goto out; - } - - /* Check if there is a conflict, and if the - * peer data is already present - */ - glusterd_is_peer_snap_conflicting (peer_snap_name, peer_snap_id, - &conflict, &snap, - peerinfo->hostname); - if (conflict == _gf_false) { - if (snap) { - /* Peer has snap with the same snapname - * and snap_id. No need to accept peer data - */ - ret = 0; - goto out; - } else { - /* Peer has snap with the same snapname - * and snap_id, which local node doesn't have. - */ - goto accept_peer_data; - } - } - - /* There is a conflict. Check if the current node is - * hosting bricks for the conflicted snap. - */ - is_local = glusterd_are_snap_bricks_local (snap); - - /* Check if the peer is hosting any bricks for the - * conflicting snap - */ - snprintf (buf, sizeof(buf), "%s.host_bricks", prefix); - ret = dict_get_int8 (peer_data, buf, (int8_t *) &is_hosted); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to fetch host_bricks from peer: %s " - "for %s", peerinfo->hostname, peer_snap_name); - goto out; - } - - /* As there is a conflict at this point of time, the data of the - * node that hosts a brick takes precedence. If both the local - * node and the peer are in the same state, i.e if both of them - * are either hosting or not hosting the bricks, for the snap, - * then it's a peer reject - */ - if (is_hosted == is_local) { - gf_log (this->name, GF_LOG_ERROR, - "Conflict in snapshot %s with peer %s", - peer_snap_name, peerinfo->hostname); - ret = -1; - goto out; - } - - if (is_hosted == _gf_false) { - /* If there was a conflict, and the peer is not hosting - * any brick, then don't accept peer data - */ - gf_log (this->name, GF_LOG_DEBUG, - "Peer doesn't hosts bricks for conflicting " - "snap(%s). Not accepting peer data.", - peer_snap_name); - ret = 0; - goto out; - } - - /* The peer is hosting a brick in case of conflict - * And local node isn't. Hence remove local node's - * data and accept peer data - */ - - gf_log (this->name, GF_LOG_DEBUG, "Peer hosts bricks for conflicting " - "snap(%s). Removing local data. Accepting peer data.", - peer_snap_name); - - dict = dict_new(); - if (!dict) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to create dict"); - ret = -1; - goto out; - } - - ret = glusterd_snap_remove (dict, snap, _gf_true, _gf_false); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to remove snap %s", snap->snapname); - goto out; - } - -accept_peer_data: - - /* Accept Peer Data */ - ret = glusterd_import_friend_snap (peer_data, snap_count, - peer_snap_name, peer_snap_id); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to import snap %s from peer %s", - peer_snap_name, peerinfo->hostname); - goto out; - } - -out: - if (dict) - dict_unref (dict); - - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -/* Compare snapshots present in peer_data, with the snapshots in - * the current node - */ -int32_t -glusterd_compare_friend_snapshots (dict_t *peer_data, - glusterd_peerinfo_t *peerinfo) -{ - int32_t ret = -1; - int32_t snap_count = 0; - int i = 1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (peer_data); - GF_ASSERT (peerinfo); - - ret = dict_get_int32 (peer_data, "snap_count", &snap_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to fetch snap_count"); - goto out; - } - - 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, peerinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to compare snapshots with peer %s", - peerinfo->hostname); - goto out; - } - } - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int32_t glusterd_compare_friend_data (dict_t *peer_data, int32_t *status, char *hostname) { @@ -5976,12 +4317,6 @@ out: return rpc; } -static inline struct rpc_clnt* -glusterd_snapd_get_rpc (glusterd_volinfo_t *volinfo) -{ - return volinfo->snapd.rpc; -} - struct rpc_clnt* glusterd_nodesvc_get_rpc (char *server) { @@ -7701,67 +6036,6 @@ out: } int32_t -glusterd_add_snapd_to_dict (glusterd_volinfo_t *volinfo, - dict_t *dict, int32_t count) -{ - - int ret = -1; - int32_t pid = -1; - int32_t brick_online = -1; - char key[1024] = {0}; - char base_key[1024] = {0}; - char pidfile[PATH_MAX] = {0}; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - - - GF_ASSERT (volinfo); - GF_ASSERT (dict); - - this = THIS; - GF_ASSERT (this); - - priv = this->private; - - snprintf (base_key, sizeof (base_key), "brick%d", count); - snprintf (key, sizeof (key), "%s.hostname", base_key); - ret = dict_set_str (dict, key, "Snapshot Daemon"); - if (ret) - goto out; - - snprintf (key, sizeof (key), "%s.path", base_key); - ret = dict_set_dynstr (dict, key, gf_strdup (uuid_utoa (MY_UUID))); - if (ret) - goto out; - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.port", base_key); - ret = dict_set_int32 (dict, key, volinfo->snapd.port); - if (ret) - goto out; - - glusterd_get_snapd_pidfile (volinfo, pidfile, sizeof (pidfile)); - - brick_online = gf_is_service_running (pidfile, &pid); - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.pid", base_key); - ret = dict_set_int32 (dict, key, pid); - if (ret) - goto out; - - memset (key, 0, sizeof (key)); - snprintf (key, sizeof (key), "%s.status", base_key); - ret = dict_set_int32 (dict, key, brick_online); - -out: - if (ret) - gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); - - return ret; -} - -int32_t glusterd_get_all_volnames (dict_t *dict) { int ret = -1; @@ -10401,418 +8675,6 @@ out: } int -glusterd_snap_config_use_rsp_dict (dict_t *dst, dict_t *src) -{ - char buf[PATH_MAX] = ""; - char *volname = NULL; - int ret = -1; - int config_command = 0; - uint64_t i = 0; - uint64_t hard_limit = GLUSTERD_SNAPS_MAX_HARD_LIMIT; - uint64_t soft_limit = GLUSTERD_SNAPS_DEF_SOFT_LIMIT_PERCENT; - uint64_t value = 0; - uint64_t voldisplaycount = 0; - - if (!dst || !src) { - gf_log ("", GF_LOG_ERROR, "Source or Destination " - "dict is empty."); - goto out; - } - - ret = dict_get_int32 (dst, "config-command", &config_command); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "failed to get config-command type"); - goto out; - } - - switch (config_command) { - case GF_SNAP_CONFIG_DISPLAY: - ret = dict_get_uint64 (src, - GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT, - &hard_limit); - if (!ret) { - ret = dict_set_uint64 (dst, - GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT, - hard_limit); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set snap_max_hard_limit"); - goto out; - } - } else { - /* Received dummy response from other nodes */ - ret = 0; - goto out; - } - - ret = dict_get_uint64 (src, - GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT, - &soft_limit); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to get snap_max_soft_limit"); - goto out; - } - - ret = dict_set_uint64 (dst, - GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT, - soft_limit); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set snap_max_soft_limit"); - goto out; - } - - ret = dict_get_uint64 (src, "voldisplaycount", - &voldisplaycount); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to get voldisplaycount"); - goto out; - } - - ret = dict_set_uint64 (dst, "voldisplaycount", - voldisplaycount); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set voldisplaycount"); - goto out; - } - - for (i = 0; i < voldisplaycount; i++) { - snprintf (buf, sizeof(buf), "volume%"PRIu64"-volname", i); - ret = dict_get_str (src, buf, &volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to get %s", buf); - goto out; - } - ret = dict_set_str (dst, buf, volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set %s", buf); - goto out; - } - - snprintf (buf, sizeof(buf), - "volume%"PRIu64"-snap-max-hard-limit", i); - ret = dict_get_uint64 (src, buf, &value); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to get %s", buf); - goto out; - } - ret = dict_set_uint64 (dst, buf, value); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set %s", buf); - goto out; - } - - snprintf (buf, sizeof(buf), - "volume%"PRIu64"-active-hard-limit", i); - ret = dict_get_uint64 (src, buf, &value); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to get %s", buf); - goto out; - } - ret = dict_set_uint64 (dst, buf, value); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set %s", buf); - goto out; - } - - snprintf (buf, sizeof(buf), - "volume%"PRIu64"-snap-max-soft-limit", i); - ret = dict_get_uint64 (src, buf, &value); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to get %s", buf); - goto out; - } - ret = dict_set_uint64 (dst, buf, value); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Unable to set %s", buf); - goto out; - } - } - - break; - default: - break; - } - - ret = 0; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -int -glusterd_merge_brick_status (dict_t *dst, dict_t *src) -{ - int64_t volume_count = 0; - int64_t index = 0; - int64_t j = 0; - int64_t brick_count = 0; - int64_t brick_order = 0; - char key[PATH_MAX] = {0, }; - char snapbrckcnt[PATH_MAX] = {0, }; - char snapbrckord[PATH_MAX] = {0, }; - int ret = -1; - int32_t brick_online = 0; - xlator_t *this = NULL; - int32_t snap_command = 0; - - this = THIS; - GF_ASSERT (this); - - if (!dst || !src) { - gf_log (this->name, GF_LOG_ERROR, "Source or Destination " - "dict is empty."); - goto out; - } - - ret = dict_get_int32 (dst, "type", &snap_command); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "unable to get the type of " - "the snapshot command"); - goto out; - } - - if (snap_command == GF_SNAP_OPTION_TYPE_DELETE) { - gf_log (this->name, GF_LOG_DEBUG, "snapshot delete command." - " Need not merge the status of the bricks"); - ret = 0; - goto out; - } - - ret = dict_get_int64 (src, "volcount", &volume_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "get the volume count"); - goto out; - } - - for (index = 0; index < volume_count; index++) { - ret = snprintf (snapbrckcnt, sizeof(snapbrckcnt) - 1, - "snap-vol%"PRId64"_brickcount", index+1); - ret = dict_get_int64 (src, snapbrckcnt, &brick_count); - if (ret) { - gf_log (this->name, GF_LOG_TRACE, - "No bricks for this volume in this dict (%s)", - snapbrckcnt); - continue; - } - - for (j = 0; j < brick_count; j++) { - /* Fetching data from source dict */ - snprintf (snapbrckord, sizeof(snapbrckord) - 1, - "snap-vol%"PRId64".brick%"PRId64".order", index+1, j); - - ret = dict_get_int64 (src, snapbrckord, &brick_order); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to get brick order (%s)", - snapbrckord); - goto out; - } - - snprintf (key, sizeof (key) - 1, - "snap-vol%"PRId64".brick%"PRId64".status", index+1, - brick_order); - ret = dict_get_int32 (src, key, &brick_online); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "get the brick status (%s)", key); - goto out; - } - - ret = dict_set_int32 (dst, key, brick_online); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "set the brick status (%s)", key); - goto out; - } - brick_online = 0; - } - } - - ret = 0; - -out: - return ret; -} - -/* Aggregate missed_snap_counts from different nodes and save it * - * in the req_dict of the originator node */ -int -glusterd_snap_create_use_rsp_dict (dict_t *dst, dict_t *src) -{ - char *buf = NULL; - char *tmp_str = NULL; - char name_buf[PATH_MAX] = ""; - int32_t i = -1; - int32_t ret = -1; - int32_t src_missed_snap_count = -1; - int32_t dst_missed_snap_count = -1; - xlator_t *this = NULL; - int8_t soft_limit_flag = -1; - - this = THIS; - GF_ASSERT (this); - - if (!dst || !src) { - gf_log (this->name, GF_LOG_ERROR, "Source or Destination " - "dict is empty."); - goto out; - } - - ret = glusterd_merge_brick_status (dst, src); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to merge brick " - "status"); - goto out; - } - - ret = dict_get_str (src, "snapuuid", &buf); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to get snap UUID"); - goto out; - } - - ret = dict_set_dynstr_with_alloc (dst, "snapuuid", buf); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to set snap uuid in dict"); - goto out; - } - - /* set in dst dictionary soft-limit-reach only if soft-limit-reach - * is present src dictionary */ - ret = dict_get_int8 (src, "soft-limit-reach", &soft_limit_flag); - if (!ret) { - ret = dict_set_int8 (dst, "soft-limit-reach", soft_limit_flag); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to set " - "soft_limit_flag"); - goto out; - } - } - - ret = dict_get_int32 (src, "missed_snap_count", - &src_missed_snap_count); - if (ret) { - gf_log (this->name, GF_LOG_DEBUG, "No missed snaps"); - ret = 0; - goto out; - } - - ret = dict_get_int32 (dst, "missed_snap_count", - &dst_missed_snap_count); - if (ret) { - /* Initialize dst_missed_count for the first time */ - dst_missed_snap_count = 0; - } - - for (i = 0; i < src_missed_snap_count; i++) { - snprintf (name_buf, sizeof(name_buf), "missed_snaps_%d", - i); - ret = dict_get_str (src, name_buf, &buf); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to fetch %s", name_buf); - goto out; - } - - snprintf (name_buf, sizeof(name_buf), "missed_snaps_%d", - dst_missed_snap_count); - - tmp_str = gf_strdup (buf); - if (!tmp_str) { - ret = -1; - goto out; - } - - ret = dict_set_dynstr (dst, name_buf, tmp_str); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set %s", name_buf); - goto out; - } - - tmp_str = NULL; - dst_missed_snap_count++; - } - - ret = dict_set_int32 (dst, "missed_snap_count", dst_missed_snap_count); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Unable to set dst_missed_snap_count"); - goto out; - } - -out: - if (ret && tmp_str) - GF_FREE(tmp_str); - - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int -glusterd_snap_use_rsp_dict (dict_t *dst, dict_t *src) -{ - int ret = -1; - int32_t snap_command = 0; - - if (!dst || !src) { - gf_log ("", GF_LOG_ERROR, "Source or Destination " - "dict is empty."); - goto out; - } - - ret = dict_get_int32 (dst, "type", &snap_command); - if (ret) { - gf_log ("", GF_LOG_ERROR, "unable to get the type of " - "the snapshot command"); - goto out; - } - - switch (snap_command) { - case GF_SNAP_OPTION_TYPE_CREATE: - case GF_SNAP_OPTION_TYPE_DELETE: - ret = glusterd_snap_create_use_rsp_dict (dst, src); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to use rsp dict"); - goto out; - } - break; - case GF_SNAP_OPTION_TYPE_CONFIG: - ret = glusterd_snap_config_use_rsp_dict (dst, src); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to use rsp dict"); - goto out; - } - break; - default: - // copy the response dictinary's contents to the dict to be - // sent back to the cli - dict_copy (src, dst); - break; - } - - ret = 0; -out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - return ret; -} - -int glusterd_sys_exec_output_rsp_dict (dict_t *dst, dict_t *src) { char output_name[PATH_MAX] = ""; @@ -11692,100 +9554,6 @@ out: return is_status_tasks; } -int -glusterd_compare_snap_time(struct list_head *list1, struct list_head *list2) -{ - glusterd_snap_t *snap1 = NULL; - glusterd_snap_t *snap2 = NULL; - double diff_time = 0; - - GF_ASSERT (list1); - GF_ASSERT (list2); - - snap1 = list_entry(list1, glusterd_snap_t, snap_list); - snap2 = list_entry(list2, glusterd_snap_t, snap_list); - diff_time = difftime(snap1->time_stamp, snap2->time_stamp); - - return ((int)diff_time); -} - -int -glusterd_compare_snap_vol_time(struct list_head *list1, struct list_head *list2) -{ - glusterd_volinfo_t *snapvol1 = NULL; - glusterd_volinfo_t *snapvol2 = NULL; - double diff_time = 0; - - GF_ASSERT (list1); - GF_ASSERT (list2); - - snapvol1 = list_entry(list1, glusterd_volinfo_t, snapvol_list); - snapvol2 = list_entry(list2, glusterd_volinfo_t, snapvol_list); - diff_time = difftime(snapvol1->snapshot->time_stamp, - snapvol2->snapshot->time_stamp); - - return ((int)diff_time); -} - -int32_t -glusterd_missed_snapinfo_new (glusterd_missed_snap_info **missed_snapinfo) -{ - glusterd_missed_snap_info *new_missed_snapinfo = NULL; - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (missed_snapinfo); - - new_missed_snapinfo = GF_CALLOC (1, sizeof(*new_missed_snapinfo), - gf_gld_mt_missed_snapinfo_t); - - if (!new_missed_snapinfo) - goto out; - - INIT_LIST_HEAD (&new_missed_snapinfo->missed_snaps); - INIT_LIST_HEAD (&new_missed_snapinfo->snap_ops); - - *missed_snapinfo = new_missed_snapinfo; - - ret = 0; - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - -int32_t -glusterd_missed_snap_op_new (glusterd_snap_op_t **snap_op) -{ - glusterd_snap_op_t *new_snap_op = NULL; - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (snap_op); - - new_snap_op = GF_CALLOC (1, sizeof(*new_snap_op), - gf_gld_mt_missed_snapinfo_t); - - if (!new_snap_op) - goto out; - - new_snap_op->brick_num = -1; - new_snap_op->op = -1; - new_snap_op->status = -1; - INIT_LIST_HEAD (&new_snap_op->snap_ops_list); - - *snap_op = new_snap_op; - - ret = 0; -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - /* Tells if rebalance needs to be started for the given volume on the peer * * Rebalance should be started on a peer only if an involved brick is present on @@ -12116,468 +9884,6 @@ glusterd_compare_volume_name(struct list_head *list1, struct list_head *list2) return strcmp(volinfo1->volname, volinfo2->volname); } -int32_t -glusterd_mount_lvm_snapshot (glusterd_brickinfo_t *brickinfo, - char *brick_mount_path) -{ - char msg[NAME_MAX] = ""; - char mnt_opts[1024] = ""; - int32_t ret = -1; - runner_t runner = {0, }; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (brick_mount_path); - GF_ASSERT (brickinfo); - - - runinit (&runner); - snprintf (msg, sizeof (msg), "mount %s %s", - brickinfo->device_path, brick_mount_path); - - strcpy (mnt_opts, brickinfo->mnt_opts); - - /* XFS file-system does not allow to mount file-system with duplicate - * UUID. File-system UUID of snapshot and its origin volume is same. - * Therefore to mount such a snapshot in XFS we need to pass nouuid - * option - */ - if (!strcmp (brickinfo->fstype, "xfs") && - !mntopts_exists (mnt_opts, "nouuid")) { - if ( strlen (mnt_opts) > 0 ) - strcat (mnt_opts, ","); - strcat (mnt_opts, "nouuid"); - } - - - if ( strlen (mnt_opts) > 0 ) { - runner_add_args (&runner, "mount", "-o", mnt_opts, - brickinfo->device_path, brick_mount_path, NULL); - } else { - runner_add_args (&runner, "mount", brickinfo->device_path, - brick_mount_path, NULL); - } - - runner_log (&runner, this->name, GF_LOG_DEBUG, msg); - ret = runner_run (&runner); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "mounting the snapshot " - "logical device %s failed (error: %s)", - brickinfo->device_path, strerror (errno)); - goto out; - } else - gf_log (this->name, GF_LOG_DEBUG, "mounting the snapshot " - "logical device %s successful", brickinfo->device_path); - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning with %d", ret); - return ret; -} - -int32_t -glusterd_umount (const char *path) -{ - char msg[NAME_MAX] = ""; - int32_t ret = -1; - runner_t runner = {0, }; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (path); - - runinit (&runner); - snprintf (msg, sizeof (msg), "umount path %s", path); - runner_add_args (&runner, _PATH_UMOUNT, "-f", path, NULL); - runner_log (&runner, this->name, GF_LOG_DEBUG, msg); - ret = runner_run (&runner); - if (ret) - gf_log (this->name, GF_LOG_ERROR, "umounting %s failed (%s)", - path, strerror (errno)); - - gf_log (this->name, GF_LOG_TRACE, "Returning with %d", ret); - return ret; -} - -int32_t -glusterd_copy_file (const char *source, const char *destination) -{ - int32_t ret = -1; - xlator_t *this = NULL; - char buffer[1024] = ""; - int src_fd = -1; - int dest_fd = -1; - int read_len = -1; - struct stat stbuf = {0,}; - mode_t dest_mode = 0; - - this = THIS; - GF_ASSERT (this); - - GF_ASSERT (source); - GF_ASSERT (destination); - - /* Here is stat is made to get the file permission of source file*/ - ret = lstat (source, &stbuf); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "%s not found", source); - goto out; - } - - dest_mode = stbuf.st_mode & 0777; - - src_fd = open (source, O_RDONLY); - if (src_fd < 0) { - ret = -1; - gf_log (this->name, GF_LOG_ERROR, "Unable to open file %s", - source); - goto out; - } - - dest_fd = open (destination, O_CREAT | O_RDWR, dest_mode); - if (dest_fd < 0) { - ret = -1; - gf_log (this->name, GF_LOG_ERROR, - "Unble to open a file %s", destination); - goto out; - } - - do { - ret = read (src_fd, buffer, sizeof (buffer)); - if (ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "Error reading file " - "%s", source); - goto out; - } - read_len = ret; - if (read_len == 0) - break; - - ret = write (dest_fd, buffer, read_len); - if (ret != read_len) { - gf_log (this->name, GF_LOG_ERROR, "Error writing in " - "file %s", destination); - goto out; - } - } while (ret > 0); -out : - if (src_fd > 0) - close (src_fd); - - if (dest_fd > 0) - close (dest_fd); - return ret; -} - -int32_t -glusterd_copy_folder (const char *source, const char *destination) -{ - DIR *dir_ptr = NULL; - struct dirent *direntp = NULL; - int32_t ret = -1; - char src_path[PATH_MAX] = ""; - char dest_path[PATH_MAX] = ""; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - - GF_ASSERT (source); - GF_ASSERT (destination); - - dir_ptr = opendir (source); - if (!dir_ptr) { - gf_log (this->name, GF_LOG_ERROR, "Unable to open %s", source); - goto out; - } - - while ((direntp = readdir (dir_ptr)) != NULL) { - if (strcmp (direntp->d_name, ".") == 0 || - strcmp (direntp->d_name, "..") == 0) - continue; - ret = snprintf (src_path, sizeof (src_path), "%s/%s", - source, direntp->d_name); - if (ret < 0) - goto out; - - ret = snprintf (dest_path, sizeof (dest_path), "%s/%s", - destination, direntp->d_name); - if (ret < 0) - goto out; - - ret = glusterd_copy_file (src_path, dest_path); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Could not copy " - "%s to %s", src_path, dest_path); - goto out; - } - } -out: - if (dir_ptr) - closedir (dir_ptr); - - return ret; -} - -int32_t -glusterd_get_geo_rep_session (char *slave_key, char *origin_volname, - dict_t *gsync_slaves_dict, char *session, - char *slave) -{ - int32_t ret = -1; - char *token = NULL; - char *temp = NULL; - char *ip = NULL; - char *buffer = NULL; - xlator_t *this = NULL; - char *slave_temp = NULL; - char *save_ptr = NULL; - - this = THIS; - GF_ASSERT (this); - - GF_ASSERT (slave_key); - GF_ASSERT (origin_volname); - GF_ASSERT (gsync_slaves_dict); - - ret = dict_get_str (gsync_slaves_dict, slave_key, &buffer); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to " - "get value for key %s", slave_key); - goto out; - } - - temp = gf_strdup (buffer); - if (!temp) { - ret = -1; - goto out; - } - - token = strtok_r (temp, "/", &save_ptr); - - token = strtok_r (NULL, ":", &save_ptr); - if (!token) { - ret = -1; - goto out; - } - token++; - - ip = gf_strdup (token); - if (!ip) { - ret = -1; - goto out; - } - - token = strtok_r (NULL, "\0", &save_ptr); - if (!token) { - ret = -1; - goto out; - } - token++; - - slave_temp = gf_strdup (token); - if (!slave) { - ret = -1; - goto out; - } - - ret = snprintf (session, PATH_MAX, "%s_%s_%s", - origin_volname, ip, slave_temp); - if (ret < 0) /* Negative value is an error */ - goto out; - - ret = snprintf (slave, PATH_MAX, "%s::%s", ip, slave_temp); - if (ret < 0) { - goto out; - } - - ret = 0; /* Success */ - -out: - if (temp) - GF_FREE (temp); - - if (ip) - GF_FREE (ip); - - if (slave_temp) - GF_FREE (slave_temp); - - return ret; -} - -int32_t -glusterd_copy_quota_files (glusterd_volinfo_t *src_vol, - glusterd_volinfo_t *dest_vol) { - - int32_t ret = -1; - char src_dir[PATH_MAX] = ""; - char dest_dir[PATH_MAX] = ""; - char src_path[PATH_MAX] = ""; - char dest_path[PATH_MAX] = ""; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - struct stat stbuf = {0,}; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - GF_ASSERT (src_vol); - GF_ASSERT (dest_vol); - - GLUSTERD_GET_VOLUME_DIR (src_dir, src_vol, priv); - - GLUSTERD_GET_VOLUME_DIR (dest_dir, dest_vol, priv); - - ret = snprintf (src_path, sizeof (src_path), "%s/quota.conf", - src_dir); - if (ret < 0) - goto out; - - /* quota.conf is not present if quota is not enabled, Hence ignoring - * the absence of this file - */ - ret = lstat (src_path, &stbuf); - if (ret) { - ret = 0; - gf_log (this->name, GF_LOG_DEBUG, "%s not found", src_path); - goto out; - } - - ret = snprintf (dest_path, sizeof (dest_path), "%s/quota.conf", - dest_dir); - if (ret < 0) - goto out; - - ret = glusterd_copy_file (src_path, dest_path); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to copy %s in %s", - src_path, dest_path); - goto out; - } - - ret = snprintf (src_path, sizeof (src_path), "%s/quota.cksum", - src_dir); - if (ret < 0) - goto out; - - /* If quota.conf is present and quota.cksum is not present, then - * that scenario is considered as invalid, hence error out. - */ - ret = lstat (src_path, &stbuf); - if (ret) { - ret = -1; - gf_log (this->name, GF_LOG_ERROR, "%s not found", src_path); - goto out; - } - - ret = snprintf (dest_path, sizeof (dest_path), "%s/quota.cksum", - dest_dir); - if (ret < 0) - goto out; - - ret = glusterd_copy_file (src_path, dest_path); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to copy %s in %s", - src_path, dest_path); - goto out; - } - -out: - return ret; - -} - -int32_t -glusterd_restore_geo_rep_files (glusterd_volinfo_t *snap_vol) -{ - int32_t ret = -1; - char src_path[PATH_MAX] = ""; - char dest_path[PATH_MAX] = ""; - xlator_t *this = NULL; - char *origin_volname = NULL; - glusterd_volinfo_t *origin_vol = NULL; - int i = 0; - char key[PATH_MAX] = ""; - char session[PATH_MAX] = ""; - char slave[PATH_MAX] = ""; - char snapgeo_dir[PATH_MAX] = ""; - glusterd_conf_t *priv = NULL; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - GF_ASSERT (snap_vol); - - origin_volname = gf_strdup (snap_vol->parent_volname); - if (!origin_volname) { - ret = -1; - goto out; - } - - ret = glusterd_volinfo_find (origin_volname, &origin_vol); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Unable to fetch " - "volinfo for volname %s", origin_volname); - goto out; - } - - for (i = 1 ; i <= snap_vol->gsync_slaves->count; i++) { - ret = snprintf (key, sizeof (key), "slave%d", i); - if (ret < 0) { - goto out; - } - - /* "origin_vol" is used here because geo-replication saves - * the session in the form of master_ip_slave. - * As we need the master volume to be same even after - * restore, we are passing the origin volume name. - * - * "snap_vol->gsync_slaves" contain the slave information - * when the snapshot was taken, hence we have to restore all - * those slaves information when we do snapshot restore. - */ - ret = glusterd_get_geo_rep_session (key, origin_vol->volname, - snap_vol->gsync_slaves, - session, slave); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to get geo-rep session"); - goto out; - } - - GLUSTERD_GET_SNAP_GEO_REP_DIR(snapgeo_dir, snap_vol->snapshot, - priv); - ret = snprintf (src_path, sizeof (src_path), - "%s/%s", snapgeo_dir, session); - if (ret < 0) - goto out; - - ret = snprintf (dest_path, sizeof (dest_path), - "%s/%s/%s", priv->workdir, GEOREP, - session); - if (ret < 0) - goto out; - - ret = glusterd_copy_folder (src_path, dest_path); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Could not copy " - "%s to %s", src_path, dest_path); - goto out; - } - } -out: - if (origin_volname) - GF_ASSERT (origin_volname); - - return ret; -} - /* This is an utility function which will recursively delete * a folder and its contents. * @@ -12650,428 +9956,6 @@ out: return ret; } -gf_boolean_t -glusterd_volume_quorum_calculate (glusterd_volinfo_t *volinfo, dict_t *dict, - int down_count, gf_boolean_t first_brick_on, - int8_t snap_force, int quorum_count, - char *quorum_type, char **op_errstr) -{ - gf_boolean_t quorum_met = _gf_false; - char err_str[PATH_MAX] = {0, }; - xlator_t *this = NULL; - int up_count = 0; - - this = THIS; - GF_ASSERT (this); - - if (!volinfo || !dict) { - gf_log (this->name, GF_LOG_WARNING, "input parameters NULL"); - goto out; - } - - if (!snap_force && down_count) { - snprintf (err_str, sizeof (err_str), "One or more bricks may " - "be down. Use the force option "); - gf_log (this->name, GF_LOG_ERROR, "%s", err_str); - *op_errstr = gf_strdup (err_str); - goto out; - } - - up_count = volinfo->dist_leaf_count - down_count; - - if (quorum_type && !strcmp (quorum_type, "fixed")) { - if (up_count >= quorum_count) { - quorum_met = _gf_true; - goto out; - } - } else { - if ((GF_CLUSTER_TYPE_DISPERSE != volinfo->type) && - (volinfo->dist_leaf_count % 2 == 0)) { - if ((up_count > quorum_count) || - ((up_count == quorum_count) && first_brick_on)) { - quorum_met = _gf_true; - goto out; - } - } else { - if (up_count >= quorum_count) { - quorum_met = _gf_true; - goto out; - } - } - } - - if (!quorum_met) { - snprintf (err_str, sizeof (err_str), "quorum is not met"); - gf_log (this->name, GF_LOG_WARNING, "%s", err_str); - *op_errstr = gf_strdup (err_str); - } - -out: - return quorum_met; -} - -int32_t -glusterd_volume_quorum_check (glusterd_volinfo_t *volinfo, int64_t index, - dict_t *dict, char *key_prefix, - int8_t snap_force, int quorum_count, - char *quorum_type, char **op_errstr) -{ - int ret = 0; - xlator_t *this = NULL; - int64_t i = 0; - int64_t j = 0; - char key[1024] = {0, }; - int down_count = 0; - gf_boolean_t first_brick_on = _gf_true; - glusterd_conf_t *priv = NULL; - gf_boolean_t quorum_met = _gf_false; - int distribute_subvols = 0; - int32_t brick_online = 0; - char err_str[PATH_MAX] = {0, }; - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - if (!volinfo || !dict) { - gf_log (this->name, GF_LOG_WARNING, "input parameters NULL"); - goto out; - } - - if ((!glusterd_is_volume_replicate (volinfo) || - volinfo->replica_count < 3) && - (GF_CLUSTER_TYPE_DISPERSE != volinfo->type)) { - for (i = 0; i < volinfo->brick_count ; i++) { - /* for a pure distribute volume, and replica volume - with replica count 2, quorum is not met if even - one of its subvolumes is down - */ - snprintf (key, sizeof (key), "%s%"PRId64".brick%"PRId64".status", - key_prefix, index, i); - ret = dict_get_int32 (dict, key, &brick_online); - if (ret || !brick_online) { - ret = 1; - snprintf (err_str, sizeof (err_str), "quorum " - "is not met"); - gf_log (this->name, GF_LOG_ERROR, "%s", - err_str); - *op_errstr = gf_strdup (err_str); - goto out; - } - } - ret = 0; - quorum_met = _gf_true; - } else { - distribute_subvols = volinfo->brick_count / - volinfo->dist_leaf_count; - for (j = 0; j < distribute_subvols; j++) { - // by default assume quorum is not met - /* TODO: Handle distributed striped replicate volumes - Currently only distributed replicate volumes are - handled. - */ - ret = 1; - quorum_met = _gf_false; - for (i = 0; i < volinfo->dist_leaf_count; i++) { - snprintf (key, sizeof (key), - "%s%"PRId64".brick%"PRId64".status", key_prefix, - index, - (j * volinfo->dist_leaf_count) + i); - ret = dict_get_int32 (dict, key, &brick_online); - if (ret || !brick_online) { - if (i == 0) - first_brick_on = _gf_false; - down_count++; - } - } - - quorum_met = glusterd_volume_quorum_calculate (volinfo, - dict, - down_count, - first_brick_on, - snap_force, - quorum_count, - quorum_type, - op_errstr); - // goto out if quorum is not met - if (!quorum_met) { - ret = -1; - goto out; - } - - down_count = 0; - first_brick_on = _gf_true; - } - } - - if (quorum_met) { - gf_log (this->name, GF_LOG_DEBUG, "volume %s is in quorum", - volinfo->volname); - ret = 0; - } - -out: - return ret; -} - -int32_t -glusterd_snap_quorum_check_for_create (dict_t *dict, gf_boolean_t snap_volume, - char **op_errstr, - struct list_head *peers_list) -{ - int8_t snap_force = 0; - int32_t force = 0; - char err_str[PATH_MAX] = {0, }; - int quorum_count = 0; - char *quorum_type = NULL; - int32_t tmp = 0; - char key_prefix[PATH_MAX] = {0, }; - char *snapname = NULL; - glusterd_snap_t *snap = NULL; - glusterd_volinfo_t *volinfo = NULL; - char *volname = NULL; - int64_t volcount = 0; - char key[PATH_MAX] = {0, }; - int64_t i = 0; - int32_t ret = -1; - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - - if (!dict) { - gf_log (this->name, GF_LOG_ERROR, "dict is NULL"); - goto out; - } - - if (snap_volume) { - ret = dict_get_str (dict, "snapname", &snapname); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "get snapname"); - goto out; - } - - snap = glusterd_find_snap_by_name (snapname); - if (!snap) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "get the snapshot %s", snapname); - ret = -1; - goto out; - } - } - - ret = dict_get_int32 (dict, "flags", &force); - if (!ret && (force & GF_CLI_FLAG_OP_FORCE)) - snap_force = 1; - if (!snap_force) { - /* Do a quorum check of glusterds also. Because, - the missed snapshot information will be saved - by glusterd and if glusterds are not in - quorum, then better fail the snapshot - */ - if (!does_gd_meet_server_quorum (this, peers_list, _gf_true)) { - snprintf (err_str, sizeof (err_str), - "glusterds are not in quorum"); - gf_log (this->name, GF_LOG_WARNING, "%s", - err_str); - *op_errstr = gf_strdup (err_str); - ret = -1; - goto out; - } - - gf_log (this->name, GF_LOG_DEBUG, "glusterds are in " - "quorum"); - } - - ret = dict_get_int64 (dict, "volcount", &volcount); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to get " - "volcount"); - goto out; - } - - for (i = 1; i <= volcount; i++) { - snprintf (key, sizeof (key), "%s%"PRId64, - snap_volume?"snap-volname":"volname", i); - ret = dict_get_str (dict, key, &volname); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "failed to " - "get volname"); - goto out; - } - - if (snap_volume) { - ret = glusterd_snap_volinfo_find (volname, snap, - &volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "failed to get snap volume %s " - "for snap %s", volname, - snapname); - goto out; - } - } else { - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "failed to find the volume %s", - volname); - goto out; - } - } - - /* for replicate volumes with replica count equal to or - greater than 3, do quorum check by getting what type - of quorum rule has been set by getting the volume - option set. If getting the option fails, then assume - default. - AFR does this: - if quorum type is "auto": - - for odd numner of bricks (n), n/2 + 1 - bricks should be present - - for even number of bricks n, n/2 bricks - should be present along with the 1st - subvolume - if quorum type is not "auto": - - get the quorum count from dict with the - help of the option "cluster.quorum-count" - if the option is not there in the dict, - then assume quorum type is auto and follow - the above method. - For non replicate volumes quorum is met only if all - the bricks of the volume are online - */ - - if (GF_CLUSTER_TYPE_REPLICATE == volinfo->type) { - if (volinfo->replica_count %2 == 0) - quorum_count = volinfo->replica_count/2; - else - quorum_count = - volinfo->replica_count/2 + 1; - } else if (GF_CLUSTER_TYPE_DISPERSE == volinfo->type) { - quorum_count = volinfo->disperse_count - - volinfo->redundancy_count; - } else { - quorum_count = volinfo->brick_count; - } - - ret = dict_get_str (volinfo->dict, - "cluster.quorum-type", - &quorum_type); - if (!ret && !strcmp (quorum_type, "fixed")) { - ret = dict_get_int32 (volinfo->dict, - "cluster.quorum-count", - &tmp); - /* if quorum-type option is not found in the - dict assume auto quorum type. i.e n/2 + 1. - The same assumption is made when quorum-count - option cannot be obtained from the dict (even - if the quorum-type option is not set to auto, - the behavior is set to the default behavior) - */ - if (!ret) { - /* for dispersed volumes, only allow quorums - equal or larger than minimum functional - value. - */ - if ((GF_CLUSTER_TYPE_DISPERSE != - volinfo->type) || - (tmp >= quorum_count)) { - quorum_count = tmp; - } else { - gf_log(this->name, GF_LOG_INFO, - "Ignoring small quorum-count " - "(%d) on dispersed volume", tmp); - quorum_type = NULL; - } - } - else - quorum_type = NULL; - } - - snprintf (key_prefix, sizeof (key_prefix), - "%s", snap_volume?"snap-vol":"vol"); - - ret = glusterd_volume_quorum_check (volinfo, i, dict, - key_prefix, - snap_force, - quorum_count, - quorum_type, - op_errstr); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, "volume %s " - "is not in quorum", volinfo->volname); - goto out; - } - } -out: - return ret; -} - -int32_t -glusterd_snap_quorum_check (dict_t *dict, gf_boolean_t snap_volume, - char **op_errstr, - struct list_head *peers_list) -{ - int32_t ret = -1; - xlator_t *this = NULL; - int32_t snap_command = 0; - char err_str[PATH_MAX] = {0, }; - - this = THIS; - GF_ASSERT (this); - - if (!dict) { - gf_log (this->name, GF_LOG_ERROR, "dict is NULL"); - goto out; - } - - - ret = dict_get_int32 (dict, "type", &snap_command); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "unable to get the type of " - "the snapshot command"); - goto out; - } - - switch (snap_command) { - case GF_SNAP_OPTION_TYPE_CREATE: - ret = glusterd_snap_quorum_check_for_create (dict, snap_volume, - op_errstr, - peers_list); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, "Quorum check" - "failed during snapshot create command"); - goto out; - } - break; - case GF_SNAP_OPTION_TYPE_DELETE: - case GF_SNAP_OPTION_TYPE_RESTORE: - if (!does_gd_meet_server_quorum (this, peers_list, _gf_true)) { - ret = -1; - snprintf (err_str, sizeof (err_str), - "glusterds are not in quorum"); - gf_log (this->name, GF_LOG_WARNING, "%s", - err_str); - *op_errstr = gf_strdup (err_str); - goto out; - } - - gf_log (this->name, GF_LOG_DEBUG, "glusterds are in " - "quorum"); - break; - default: - break; - } - - ret = 0; - -out: - return ret; -} - static int gd_default_synctask_cbk (int ret, call_frame_t *frame, void *opaque) { @@ -13160,531 +10044,6 @@ glusterd_get_rebalance_volfile (glusterd_volinfo_t *volinfo, volinfo->volname); } -/* Snapd functions */ -int -glusterd_is_snapd_enabled (glusterd_volinfo_t *volinfo) -{ - int ret = 0; - xlator_t *this = THIS; - - ret = dict_get_str_boolean (volinfo->dict, "features.uss", -2); - if (ret == -2) { - gf_log (this->name, GF_LOG_DEBUG, "Key features.uss not " - "present in the dict for volume %s", volinfo->volname); - ret = 0; - - } else if (ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "Failed to get 'features.uss'" - " from dict for volume %s", volinfo->volname); - } - - return ret; -} - -void -glusterd_get_snapd_rundir (glusterd_volinfo_t *volinfo, - char *path, int path_len) -{ - char workdir [PATH_MAX] = {0,}; - glusterd_conf_t *priv = THIS->private; - - GLUSTERD_GET_VOLUME_DIR (workdir, volinfo, priv); - - snprintf (path, path_len, "%s/run", workdir); -} - -void -glusterd_get_snapd_volfile (glusterd_volinfo_t *volinfo, - char *path, int path_len) -{ - char workdir [PATH_MAX] = {0,}; - glusterd_conf_t *priv = THIS->private; - - GLUSTERD_GET_VOLUME_DIR (workdir, volinfo, priv); - - snprintf (path, path_len, "%s/%s-snapd.vol", workdir, - volinfo->volname); -} - -void -glusterd_get_snapd_pidfile (glusterd_volinfo_t *volinfo, - char *path, int path_len) -{ - char rundir [PATH_MAX] = {0,}; - - glusterd_get_snapd_rundir (volinfo, rundir, sizeof (rundir)); - - snprintf (path, path_len, "%s/%s-snapd.pid", rundir, volinfo->volname); -} - -void -glusterd_set_snapd_socket_filepath (glusterd_volinfo_t *volinfo, - char *path, int path_len) -{ - char sockfilepath[PATH_MAX] = {0,}; - char rundir[PATH_MAX] = {0,}; - - glusterd_get_snapd_rundir (volinfo, rundir, sizeof (rundir)); - snprintf (sockfilepath, sizeof (sockfilepath), "%s/run-%s", - rundir, uuid_utoa (MY_UUID)); - - glusterd_set_socket_filepath (sockfilepath, path, path_len); -} - -gf_boolean_t -glusterd_is_snapd_running (glusterd_volinfo_t *volinfo) -{ - char pidfile [PATH_MAX] = {0,}; - int pid = -1; - glusterd_conf_t *priv = THIS->private; - - glusterd_get_snapd_pidfile (volinfo, pidfile, - sizeof (pidfile)); - - return gf_is_service_running (pidfile, &pid); -} - -int -glusterd_restart_snapds (glusterd_conf_t *priv) -{ - glusterd_volinfo_t *volinfo = NULL; - int ret = 0; - xlator_t *this = THIS; - - list_for_each_entry (volinfo, &priv->volumes, vol_list) { - if (volinfo->status == GLUSTERD_STATUS_STARTED && - glusterd_is_snapd_enabled (volinfo)) { - ret = glusterd_snapd_start (volinfo, - _gf_false); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Couldn't start snapd for " - "vol: %s", volinfo->volname); - goto out; - } - } - } -out: - return ret; -} - -gf_boolean_t -glusterd_is_snapd_online (glusterd_volinfo_t *volinfo) -{ - return volinfo->snapd.online; -} - -void -glusterd_snapd_set_online_status (glusterd_volinfo_t *volinfo, - gf_boolean_t status) -{ - volinfo->snapd.online = status; -} - -static inline void -glusterd_snapd_set_rpc (glusterd_volinfo_t *volinfo, struct rpc_clnt *rpc) -{ - volinfo->snapd.rpc = rpc; -} - -int32_t -glusterd_snapd_connect (glusterd_volinfo_t *volinfo, char *socketpath) -{ - int ret = 0; - dict_t *options = NULL; - struct rpc_clnt *rpc = NULL; - glusterd_conf_t *priv = THIS->private; - - rpc = glusterd_snapd_get_rpc (volinfo); - - if (rpc == NULL) { - /* Setting frame-timeout to 10mins (600seconds). - * Unix domain sockets ensures that the connection is reliable. - * The default timeout of 30mins used for unreliable network - * connections is too long for unix domain socket connections. - */ - ret = rpc_transport_unix_options_build (&options, socketpath, - 600); - if (ret) - goto out; - - ret = dict_set_str(options, - "transport.socket.ignore-enoent", "on"); - if (ret) - goto out; - - glusterd_volinfo_ref (volinfo); - - synclock_unlock (&priv->big_lock); - ret = glusterd_rpc_create (&rpc, options, - glusterd_snapd_rpc_notify, - volinfo); - synclock_lock (&priv->big_lock); - if (ret) - goto out; - - (void) glusterd_snapd_set_rpc (volinfo, rpc); - } -out: - return ret; -} - -int32_t -glusterd_snapd_disconnect (glusterd_volinfo_t *volinfo) -{ - struct rpc_clnt *rpc = NULL; - glusterd_conf_t *priv = THIS->private; - - rpc = glusterd_snapd_get_rpc (volinfo); - - (void) glusterd_snapd_set_rpc (volinfo, NULL); - - if (rpc) - glusterd_rpc_clnt_unref (priv, rpc); - - return 0; -} - -int32_t -glusterd_snapd_start (glusterd_volinfo_t *volinfo, gf_boolean_t wait) -{ - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - runner_t runner = {0,}; - char pidfile[PATH_MAX] = {0,}; - char logfile[PATH_MAX] = {0,}; - char logdir[PATH_MAX] = {0,}; - char volfile[PATH_MAX] = {0,}; - char glusterd_uuid [1024] = {0,}; - char rundir[PATH_MAX] = {0,}; - char sockfpath[PATH_MAX] = {0,}; - char volfileid[256] = {0}; - char *volfileserver = NULL; - char valgrind_logfile[PATH_MAX] = {0}; - int snapd_port = 0; - char *volname = volinfo->volname; - char snapd_id [PATH_MAX] = {0,}; - char msg [1024] = {0,}; - - this = THIS; - GF_ASSERT(this); - - if (glusterd_is_snapd_running (volinfo)) { - ret = 0; - goto connect; - } - - priv = this->private; - - glusterd_get_snapd_rundir (volinfo, rundir, sizeof (rundir)); - ret = mkdir (rundir, 0777); - - if ((ret == -1) && (EEXIST != errno)) { - gf_log (this->name, GF_LOG_ERROR, "Unable to create rundir %s", - rundir); - goto out; - } - - glusterd_get_snapd_pidfile (volinfo, pidfile, sizeof (pidfile)); - glusterd_get_snapd_volfile (volinfo, volfile, sizeof (volfile)); - - ret = sys_access (volfile, F_OK); - if (ret) { - gf_log (this->name, GF_LOG_DEBUG, - "snapd Volfile %s is not present", volfile); - - /* If glusterd is down on one of the nodes and during - * that time "USS is enabled" for the first time. After some - * time when the glusterd which was down comes back it tries - * to look for the snapd volfile and it does not find snapd - * volfile and because of this starting of snapd fails. - * Therefore, if volfile is not present then create a fresh - * volfile. - */ - ret = glusterd_create_snapd_volfile (volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Couldn't create " - "snapd volfile for volume: %s", - volinfo->volname); - goto out; - } - } - - snprintf (logdir, PATH_MAX, "%s/snaps/%s", - DEFAULT_LOG_FILE_DIRECTORY, volname); - ret = mkdir_p (logdir, 0755, _gf_true); - if ((ret == -1) && (EEXIST != errno)) { - gf_log (this->name, GF_LOG_ERROR, "Unable to create logdir %s", - logdir); - goto out; - } - - snprintf (logfile, PATH_MAX, "%s/snapd.log", logdir); - - snprintf (volfileid, sizeof (volfileid), "snapd/%s", volname); - glusterd_set_snapd_socket_filepath (volinfo, sockfpath, - sizeof (sockfpath)); - - if (dict_get_str (this->options, "transport.socket.bind-address", - &volfileserver) != 0) { - volfileserver = "localhost"; - } - - runinit (&runner); - - if (priv->valgrind) { - snprintf (valgrind_logfile, PATH_MAX, "%s/valgrind-snapd.log", - logdir); - - runner_add_args (&runner, "valgrind", "--leak-check=full", - "--trace-children=yes", "--track-origins=yes", - NULL); - runner_argprintf (&runner, "--log-file=%s", valgrind_logfile); - } - - snprintf (snapd_id, sizeof (snapd_id), "snapd-%s", volname); - runner_add_args (&runner, SBIN_DIR"/glusterfsd", - "-s", volfileserver, - "--volfile-id", volfileid, - "-p", pidfile, - "-l", logfile, - "--brick-name", snapd_id, - "-S", sockfpath, NULL); - - snapd_port = volinfo->snapd.port; - if (!snapd_port) { - snapd_port = pmap_registry_alloc (THIS); - if (!snapd_port) { - snprintf (msg, sizeof (msg), "Could not allocate port " - "for snapd service for volume %s", volname); - - runner_log (&runner, this->name, GF_LOG_DEBUG, msg); - ret = -1; - goto out; - } - } - - runner_add_arg (&runner, "--brick-port"); - runner_argprintf (&runner, "%d", snapd_port); - runner_add_arg (&runner, "--xlator-option"); - runner_argprintf (&runner, "%s-server.listen-port=%d", - volname, snapd_port); - - snprintf (msg, sizeof (msg), - "Starting the snapd service for volume %s", volname); - runner_log (&runner, this->name, GF_LOG_DEBUG, msg); - - if (!wait) { - ret = runner_run_nowait (&runner); - } else { - synclock_unlock (&priv->big_lock); - { - ret = runner_run (&runner); - } - synclock_lock (&priv->big_lock); - } - - volinfo->snapd.port = snapd_port; - -connect: - if (ret == 0) - glusterd_snapd_connect (volinfo, sockfpath); - -out: - return ret; -} - -int -glusterd_snapd_stop (glusterd_volinfo_t *volinfo) -{ - char pidfile [PATH_MAX] = {0,}; - char sockfpath [PATH_MAX] = {0,}; - glusterd_conf_t *priv = THIS->private; - int ret = 0; - - (void)glusterd_snapd_disconnect (volinfo); - - if (!glusterd_is_snapd_running (volinfo)) - goto out; - - glusterd_get_snapd_pidfile (volinfo, pidfile, sizeof (pidfile)); - ret = glusterd_service_stop ("snapd", pidfile, SIGTERM, _gf_true); - - if (ret == 0) { - glusterd_set_snapd_socket_filepath (volinfo, sockfpath, - sizeof (sockfpath)); - (void)glusterd_unlink_file (sockfpath); - } -out: - return ret; -} - -int -glusterd_handle_snapd_option (glusterd_volinfo_t *volinfo) -{ - int ret = 0; - xlator_t *this = THIS; - - if (volinfo->is_snap_volume) - return 0; - - ret = glusterd_is_snapd_enabled (volinfo); - if (ret == -1) { - gf_log (this->name, GF_LOG_ERROR, "Failed to read volume " - "options"); - goto out; - } - - if (ret) { - if (!glusterd_is_volume_started (volinfo)) { - if (glusterd_is_snapd_running (volinfo)) { - ret = glusterd_snapd_stop (volinfo); - if (ret) - gf_log (this->name, GF_LOG_ERROR, - "Couldn't stop snapd for " - "volume: %s", - volinfo->volname); - } else { - /* Since snapd is not running set ret to 0 */ - ret = 0; - } - goto out; - } - - ret = glusterd_create_snapd_volfile (volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Couldn't create " - "snapd volfile for volume: %s", - volinfo->volname); - goto out; - } - - ret = glusterd_snapd_start (volinfo, _gf_false); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Couldn't start " - "snapd for volume: %s", volinfo->volname); - goto out; - } - - } else if (glusterd_is_snapd_running (volinfo)) { - ret = glusterd_snapd_stop (volinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Couldn't stop snapd for volume: %s", - volinfo->volname); - goto out; - } - volinfo->snapd.port = 0; - } - -out: - return ret; -} - -int32_t -glusterd_is_snap_soft_limit_reached (glusterd_volinfo_t *volinfo, dict_t *dict) -{ - int32_t ret = -1; - uint64_t opt_max_hard = GLUSTERD_SNAPS_MAX_HARD_LIMIT; - uint64_t opt_max_soft = GLUSTERD_SNAPS_DEF_SOFT_LIMIT_PERCENT; - uint64_t limit = 0; - int auto_delete = 0; - uint64_t effective_max_limit = 0; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - - GF_ASSERT (volinfo); - GF_ASSERT (dict); - - this = THIS; - GF_ASSERT (this); - priv = this->private; - GF_ASSERT (priv); - - /* config values snap-max-hard-limit and snap-max-soft-limit are - * optional and hence we are not erroring out if values are not - * present - */ - gd_get_snap_conf_values_if_present (priv->opts, &opt_max_hard, - &opt_max_soft); - - /* "auto-delete" might not be set by user explicitly, - * in that case it's better to consider the default value. - * Hence not erroring out if Key is not found. - */ - auto_delete = dict_get_str_boolean (priv->opts, - GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE, - _gf_false); - - if (volinfo->snap_max_hard_limit < opt_max_hard) - effective_max_limit = volinfo->snap_max_hard_limit; - else - effective_max_limit = opt_max_hard; - - limit = (opt_max_soft * effective_max_limit)/100; - - if (volinfo->snap_count >= limit && auto_delete != _gf_true) { - gf_log (this->name, GF_LOG_WARNING, "Soft-limit " - "(value = %"PRIu64") of volume %s is reached. " - "Snapshot creation is not possible once effective " - "hard-limit (value = %"PRIu64") is reached.", - limit, volinfo->volname, effective_max_limit); - - ret = dict_set_int8 (dict, "soft-limit-reach", - _gf_true); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to " - "set soft limit exceed flag in " - "response dictionary"); - } - goto out; - } - ret = 0; -out : - return ret; -} - -/* This function initializes the parameter sys_hard_limit, - * sys_soft_limit and auto_delete value to the value set - * in dictionary, If value is not present then it is - * initialized to default values. Hence this function does not - * return any values. - */ -void -gd_get_snap_conf_values_if_present (dict_t *dict, uint64_t *sys_hard_limit, - uint64_t *sys_soft_limit) -{ - xlator_t *this = NULL; - - this = THIS; - GF_ASSERT (this); - - GF_ASSERT (dict); - - /* "snap-max-hard-limit" might not be set by user explicitly, - * in that case it's better to consider the default value. - * Hence not erroring out if Key is not found. - */ - if (dict_get_uint64 (dict, GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT, - sys_hard_limit)) { - gf_log (this->name, GF_LOG_DEBUG, "%s is not present in" - "dictionary", - GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT); - } - - /* "snap-max-soft-limit" might not be set by user explicitly, - * in that case it's better to consider the default value. - * Hence not erroring out if Key is not found. - */ - if (dict_get_uint64 (dict, GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT, - sys_soft_limit)) { - gf_log (this->name, GF_LOG_DEBUG, "%s is not present in" - "dictionary", - GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT); - } -} - /* This function will update the backend file-system * type and the mount options in origin and snap brickinfo. * This will be later used to perform file-system specific operation @@ -13699,8 +10058,8 @@ glusterd_update_mntopts (char *brick_path, glusterd_brickinfo_t *brickinfo) { int32_t ret = -1; char *mnt_pt = NULL; - char buff [PATH_MAX] = ""; - char msg [PATH_MAX] = ""; + char buff[PATH_MAX] = ""; + char msg[PATH_MAX] = ""; char *cmd = NULL; struct mntent *entry = NULL; struct mntent save_entry = {0,}; @@ -14081,35 +10440,3 @@ glusterd_op_clear_xaction_peers () } } - -gf_boolean_t -mntopts_exists (const char *str, const char *opts) -{ - char *dup_val = NULL; - char *savetok = NULL; - char *token = NULL; - gf_boolean_t exists = _gf_false; - - GF_ASSERT (opts); - - if (!str || !strlen(str)) - goto out; - - dup_val = gf_strdup (str); - if (!dup_val) - goto out; - - token = strtok_r (dup_val, ",", &savetok); - while (token) { - if (!strcmp (token, opts)) { - exists = _gf_true; - goto out; - } - token = strtok_r (NULL, ",", &savetok); - } - -out: - GF_FREE (dup_val); - return exists; -} - |