summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd/src/glusterd-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-utils.c')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c1056
1 files changed, 935 insertions, 121 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index 20a3d08..8968272 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -2239,12 +2239,17 @@ 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
+ */
int32_t
glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
- dict_t *dict, int32_t count)
+ dict_t *dict, int32_t count,
+ char *prefix)
{
int32_t ret = -1;
- char prefix[512] = {0,};
+ char pfx[512] = {0,};
char key[512] = {0,};
glusterd_brickinfo_t *brickinfo = NULL;
int32_t i = 1;
@@ -2261,14 +2266,15 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
GF_ASSERT (this);
GF_ASSERT (dict);
GF_ASSERT (volinfo);
+ GF_ASSERT (prefix);
- snprintf (key, sizeof (key), "volume%d.name", count);
+ snprintf (key, sizeof (key), "%s%d.name", prefix, count);
ret = dict_set_str (dict, key, volinfo->volname);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.type", count);
+ snprintf (key, sizeof (key), "%s%d.type", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->type);
if (ret)
goto out;
@@ -2280,68 +2286,81 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
if (ret)
goto out;
+ if (strlen (volinfo->parent_volname) > 0) {
+ snprintf (key, sizeof (key), "%s%d.parent_volname",
+ prefix, count);
+ ret = dict_set_dynstr_with_alloc (dict, key,
+ volinfo->parent_volname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to set parent_volname for %s",
+ volinfo->volname);
+ goto out;
+ }
+ }
+
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick_count", count);
+ snprintf (key, sizeof (key), "%s%d.brick_count", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->brick_count);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.version", count);
+ snprintf (key, sizeof (key), "%s%d.version", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->version);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.status", count);
+ snprintf (key, sizeof (key), "%s%d.status", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->status);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.sub_count", count);
+ snprintf (key, sizeof (key), "%s%d.sub_count", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->sub_count);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.stripe_count", count);
+ snprintf (key, sizeof (key), "%s%d.stripe_count", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->stripe_count);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.replica_count", count);
+ snprintf (key, sizeof (key), "%s%d.replica_count", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->replica_count);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.dist_count", count);
+ snprintf (key, sizeof (key), "%s%d.dist_count", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->dist_leaf_count);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.ckusm", count);
+ snprintf (key, sizeof (key), "%s%d.ckusm", prefix, count);
ret = dict_set_int64 (dict, key, volinfo->cksum);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.transport_type", count);
+ snprintf (key, sizeof (key), "%s%d.transport_type", prefix, count);
ret = dict_set_uint32 (dict, key, volinfo->transport_type);
if (ret)
goto out;
- snprintf (key, sizeof (key), "volume%d.is_snap_volume", count);
+ snprintf (key, sizeof (key), "%s%d.is_snap_volume", prefix, count);
ret = dict_set_uint32 (dict, key, volinfo->is_snap_volume);
if (ret) {
gf_log (THIS->name, GF_LOG_ERROR, "Unable to set %s", key);
goto out;
}
- snprintf (key, sizeof (key), "volume%d.snap-max-hard-limit", count);
+ snprintf (key, sizeof (key), "%s%d.snap-max-hard-limit", prefix, count);
ret = dict_set_uint64 (dict, key, volinfo->snap_max_hard_limit);
if (ret) {
gf_log (THIS->name, GF_LOG_ERROR, "Unable to set %s", key);
@@ -2354,14 +2373,14 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
goto out;
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.volume_id", count);
+ snprintf (key, sizeof (key), "%s%d.volume_id", prefix, count);
ret = dict_set_dynstr (dict, key, volume_id_str);
if (ret)
goto out;
volume_id_str = NULL;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.username", count);
+ snprintf (key, sizeof (key), "%s%d.username", prefix, count);
str = glusterd_auth_get_username (volinfo);
if (str) {
ret = dict_set_dynstr (dict, key, gf_strdup (str));
@@ -2370,7 +2389,7 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.password", count);
+ snprintf (key, sizeof (key), "%s%d.password", prefix, count);
str = glusterd_auth_get_password (volinfo);
if (str) {
ret = dict_set_dynstr (dict, key, gf_strdup (str));
@@ -2379,7 +2398,7 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
}
memset (key, 0, sizeof (key));
- snprintf (key, 256, "volume%d.rebalance", count);
+ snprintf (key, 256, "%s%d.rebalance", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->rebal.defrag_cmd);
if (ret)
goto out;
@@ -2391,22 +2410,22 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
goto out;
}
memset (key, 0, sizeof (key));
- snprintf (key, 256, "volume%d.rebalance-id", count);
+ snprintf (key, 256, "%s%d.rebalance-id", prefix, count);
ret = dict_set_dynstr (dict, key, rebalance_id_str);
if (ret)
goto out;
rebalance_id_str = NULL;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.rebalance-op", count);
+ snprintf (key, sizeof (key), "%s%d.rebalance-op", prefix, count);
ret = dict_set_uint32 (dict, key, volinfo->rebal.op);
if (ret)
goto out;
if (volinfo->rebal.dict) {
- snprintf (prefix, sizeof (prefix), "volume%d", count);
+ snprintf (pfx, sizeof (pfx), "%s%d", prefix, count);
ctx.dict = dict;
- ctx.prefix = prefix;
+ ctx.prefix = pfx;
ctx.opt_count = 1;
ctx.key_name = "rebal-dict-key";
ctx.val_name = "rebal-dict-value";
@@ -2421,7 +2440,7 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
}
memset (key, 0, sizeof (key));
- snprintf (key, 256, "volume%d."GLUSTERD_STORE_KEY_RB_STATUS, count);
+ snprintf (key, 256, "%s%d."GLUSTERD_STORE_KEY_RB_STATUS, prefix, count);
ret = dict_set_int32 (dict, key, volinfo->rep_brick.rb_status);
if (ret)
goto out;
@@ -2429,8 +2448,8 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
if (volinfo->rep_brick.rb_status > GF_RB_STATUS_NONE) {
memset (key, 0, sizeof (key));
- snprintf (key, 256, "volume%d."GLUSTERD_STORE_KEY_RB_SRC_BRICK,
- count);
+ snprintf (key, 256, "%s%d."GLUSTERD_STORE_KEY_RB_SRC_BRICK,
+ prefix, count);
gf_asprintf (&src_brick, "%s:%s",
volinfo->rep_brick.src_brick->hostname,
volinfo->rep_brick.src_brick->path);
@@ -2439,8 +2458,8 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, 256, "volume%d."GLUSTERD_STORE_KEY_RB_DST_BRICK,
- count);
+ snprintf (key, 256, "%s%d."GLUSTERD_STORE_KEY_RB_DST_BRICK,
+ prefix, count);
gf_asprintf (&dst_brick, "%s:%s",
volinfo->rep_brick.dst_brick->hostname,
volinfo->rep_brick.dst_brick->path);
@@ -2455,16 +2474,16 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.rb_id", count);
+ snprintf (key, sizeof (key), "%s%d.rb_id", prefix, count);
ret = dict_set_dynstr (dict, key, rb_id_str);
if (ret)
goto out;
rb_id_str = NULL;
}
- snprintf (prefix, sizeof (prefix), "volume%d", count);
+ snprintf (pfx, sizeof (pfx), "%s%d", prefix, count);
ctx.dict = dict;
- ctx.prefix = prefix;
+ ctx.prefix = pfx;
ctx.opt_count = 1;
ctx.key_name = "key";
ctx.val_name = "value";
@@ -2473,13 +2492,13 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
dict_foreach (volinfo->dict, _add_dict_to_prdict, &ctx);
ctx.opt_count--;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.opt-count", count);
+ snprintf (key, sizeof (key), "%s%d.opt-count", prefix, count);
ret = dict_set_int32 (dict, key, ctx.opt_count);
if (ret)
goto out;
ctx.dict = dict;
- ctx.prefix = prefix;
+ ctx.prefix = pfx;
ctx.opt_count = 1;
ctx.key_name = "slave-num";
ctx.val_name = "slave-val";
@@ -2489,42 +2508,42 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
ctx.opt_count--;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.gsync-count", count);
+ snprintf (key, sizeof (key), "%s%d.gsync-count", prefix, count);
ret = dict_set_int32 (dict, key, ctx.opt_count);
if (ret)
goto out;
list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick%d.hostname",
- count, i);
+ snprintf (key, sizeof (key), "%s%d.brick%d.hostname",
+ prefix, count, i);
ret = dict_set_str (dict, key, brickinfo->hostname);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick%d.path",
- count, i);
+ snprintf (key, sizeof (key), "%s%d.brick%d.path",
+ prefix, count, i);
ret = dict_set_str (dict, key, brickinfo->path);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick%d.decommissioned",
- count, i);
+ snprintf (key, sizeof (key), "%s%d.brick%d.decommissioned",
+ prefix, count, i);
ret = dict_set_int32 (dict, key, brickinfo->decommissioned);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick%d.brick_id",
- count, i);
+ snprintf (key, sizeof (key), "%s%d.brick%d.brick_id",
+ prefix, count, i);
ret = dict_set_str (dict, key, brickinfo->brick_id);
if (ret)
goto out;
- snprintf (key, sizeof (key), "volume%d.brick%d.snap_status",
- count, i);
+ snprintf (key, sizeof (key), "%s%d.brick%d.snap_status",
+ prefix, count, i);
ret = dict_set_int32 (dict, key, brickinfo->snap_status);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
@@ -2534,8 +2553,8 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
goto out;
}
- snprintf (key, sizeof (key), "volume%d.brick%d.device_path",
- count, i);
+ snprintf (key, sizeof (key), "%s%d.brick%d.device_path",
+ prefix, count, i);
ret = dict_set_str (dict, key, brickinfo->device_path);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
@@ -2552,19 +2571,19 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo,
* in the cluster
*/
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.op-version", count);
+ snprintf (key, sizeof (key), "%s%d.op-version", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->op_version);
if (ret)
goto out;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.client-op-version", count);
+ snprintf (key, sizeof (key), "%s%d.client-op-version", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->client_op_version);
if (ret)
goto out;
/*Add volume Capability (BD Xlator) to dict*/
memset (key, 0 ,sizeof (key));
- snprintf (key, sizeof (key), "volume%d.caps", count);
+ snprintf (key, sizeof (key), "%s%d.caps", prefix, count);
ret = dict_set_int32 (dict, key, volinfo->caps);
out:
@@ -2572,14 +2591,17 @@ out:
GF_FREE (rebalance_id_str);
GF_FREE (rb_id_str);
- gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);
-
+ gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret);
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
+ */
int
glusterd_vol_add_quota_conf_to_dict (glusterd_volinfo_t *volinfo, dict_t* load,
- int vol_idx)
+ int vol_idx, char *prefix)
{
int fd = -1;
char *gfid_str = NULL;
@@ -2591,6 +2613,7 @@ glusterd_vol_add_quota_conf_to_dict (glusterd_volinfo_t *volinfo, dict_t* load,
this = THIS;
GF_ASSERT (this);
+ GF_ASSERT (prefix);
ret = glusterd_store_create_quota_conf_sh_on_absence (volinfo);
if (ret)
@@ -2627,8 +2650,8 @@ glusterd_vol_add_quota_conf_to_dict (glusterd_volinfo_t *volinfo, dict_t* load,
goto out;
}
- snprintf (key, sizeof(key)-1, "volume%d.gfid%d", vol_idx,
- gfid_idx);
+ snprintf (key, sizeof(key)-1, "%s%d.gfid%d", prefix,
+ vol_idx, gfid_idx);
key[sizeof(key)-1] = '\0';
ret = dict_set_dynstr (load, key, gfid_str);
if (ret) {
@@ -2638,19 +2661,19 @@ glusterd_vol_add_quota_conf_to_dict (glusterd_volinfo_t *volinfo, dict_t* load,
gfid_str = NULL;
}
- snprintf (key, sizeof(key)-1, "volume%d.gfid-count", vol_idx);
+ snprintf (key, sizeof(key)-1, "%s%d.gfid-count", prefix, vol_idx);
key[sizeof(key)-1] = '\0';
ret = dict_set_int32 (load, key, gfid_idx);
if (ret)
goto out;
- snprintf (key, sizeof(key)-1, "volume%d.quota-cksum", vol_idx);
+ snprintf (key, sizeof(key)-1, "%s%d.quota-cksum", prefix, vol_idx);
key[sizeof(key)-1] = '\0';
ret = dict_set_uint32 (load, key, volinfo->quota_conf_cksum);
if (ret)
goto out;
- snprintf (key, sizeof(key)-1, "volume%d.quota-version", vol_idx);
+ snprintf (key, sizeof(key)-1, "%s%d.quota-version", prefix, vol_idx);
key[sizeof(key)-1] = '\0';
ret = dict_set_uint32 (load, key, volinfo->quota_conf_version);
if (ret)
@@ -2726,6 +2749,175 @@ out:
}
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;
+ }
+
+ 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;
@@ -2747,12 +2939,14 @@ glusterd_add_volumes_to_export_dict (dict_t **peer_data)
list_for_each_entry (volinfo, &priv->volumes, vol_list) {
count++;
- ret = glusterd_add_volume_to_dict (volinfo, dict, count);
+ ret = glusterd_add_volume_to_dict (volinfo, dict, count,
+ "volume");
if (ret)
goto out;
if (!glusterd_is_volume_quota_enabled (volinfo))
continue;
- ret = glusterd_vol_add_quota_conf_to_dict (volinfo, dict, count);
+ ret = glusterd_vol_add_quota_conf_to_dict (volinfo, dict,
+ count, "volume");
if (ret)
goto out;
}
@@ -3276,10 +3470,15 @@ 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
+ */
int32_t
glusterd_import_new_brick (dict_t *peer_data, int32_t vol_count,
int32_t brick_count,
- glusterd_brickinfo_t **brickinfo)
+ glusterd_brickinfo_t **brickinfo,
+ char *prefix)
{
char key[512] = {0,};
int ret = -1;
@@ -3295,10 +3494,11 @@ glusterd_import_new_brick (dict_t *peer_data, int32_t vol_count,
GF_ASSERT (peer_data);
GF_ASSERT (vol_count >= 0);
GF_ASSERT (brickinfo);
+ GF_ASSERT (prefix);
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick%d.hostname",
- vol_count, brick_count);
+ snprintf (key, sizeof (key), "%s%d.brick%d.hostname",
+ prefix, vol_count, brick_count);
ret = dict_get_str (peer_data, key, &hostname);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload", key);
@@ -3306,8 +3506,8 @@ glusterd_import_new_brick (dict_t *peer_data, int32_t vol_count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick%d.path",
- vol_count, brick_count);
+ snprintf (key, sizeof (key), "%s%d.brick%d.path",
+ prefix, vol_count, brick_count);
ret = dict_get_str (peer_data, key, &path);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload", key);
@@ -3315,29 +3515,29 @@ glusterd_import_new_brick (dict_t *peer_data, int32_t vol_count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick%d.brick_id",
- vol_count, brick_count);
+ snprintf (key, sizeof (key), "%s%d.brick%d.brick_id",
+ prefix, vol_count, brick_count);
ret = dict_get_str (peer_data, key, &brick_id);
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick%d.decommissioned",
- vol_count, brick_count);
+ snprintf (key, sizeof (key), "%s%d.brick%d.decommissioned",
+ prefix, vol_count, brick_count);
ret = dict_get_int32 (peer_data, key, &decommissioned);
if (ret) {
/* For backward compatibility */
ret = 0;
}
- snprintf (key, sizeof (key), "volume%d.brick%d.snap_status",
- vol_count, brick_count);
+ snprintf (key, sizeof (key), "%s%d.brick%d.snap_status",
+ prefix, vol_count, brick_count);
ret = dict_get_int32 (peer_data, key, &snap_status);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload", key);
goto out;
}
- snprintf (key, sizeof (key), "volume%d.brick%d.device_path",
- vol_count, brick_count);
+ snprintf (key, sizeof (key), "%s%d.brick%d.device_path",
+ prefix, vol_count, brick_count);
ret = dict_get_str (peer_data, key, &snap_device);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload", key);
@@ -3366,9 +3566,13 @@ 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
+ */
int32_t
glusterd_import_bricks (dict_t *peer_data, int32_t vol_count,
- glusterd_volinfo_t *new_volinfo)
+ glusterd_volinfo_t *new_volinfo, char *prefix)
{
int ret = -1;
int brick_count = 1;
@@ -3378,11 +3582,12 @@ glusterd_import_bricks (dict_t *peer_data, int32_t vol_count,
GF_ASSERT (peer_data);
GF_ASSERT (vol_count >= 0);
GF_ASSERT (new_volinfo);
+ GF_ASSERT (prefix);
while (brick_count <= new_volinfo->brick_count) {
ret = glusterd_import_new_brick (peer_data, vol_count,
brick_count,
- &new_brickinfo);
+ &new_brickinfo, prefix);
if (ret)
goto out;
if (new_brickinfo->brick_id[0] == '\0')
@@ -3400,9 +3605,14 @@ 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
+ */
static int
glusterd_import_quota_conf (dict_t *peer_data, int vol_idx,
- glusterd_volinfo_t *new_volinfo)
+ glusterd_volinfo_t *new_volinfo,
+ char *prefix)
{
int gfid_idx = 0;
int gfid_count = 0;
@@ -3416,6 +3626,7 @@ glusterd_import_quota_conf (dict_t *peer_data, int vol_idx,
this = THIS;
GF_ASSERT (this);
GF_ASSERT (peer_data);
+ GF_ASSERT (prefix);
if (!glusterd_is_volume_quota_enabled (new_volinfo)) {
(void) glusterd_clean_up_quota_store (new_volinfo);
@@ -3432,13 +3643,13 @@ glusterd_import_quota_conf (dict_t *peer_data, int vol_idx,
goto out;
}
- snprintf (key, sizeof (key)-1, "volume%d.quota-cksum", vol_idx);
+ snprintf (key, sizeof (key)-1, "%s%d.quota-cksum", prefix, vol_idx);
key[sizeof(key)-1] = '\0';
ret = dict_get_uint32 (peer_data, key, &new_volinfo->quota_conf_cksum);
if (ret)
gf_log (this->name, GF_LOG_DEBUG, "Failed to get quota cksum");
- snprintf (key, sizeof (key)-1, "volume%d.quota-version", vol_idx);
+ snprintf (key, sizeof (key)-1, "%s%d.quota-version", prefix, vol_idx);
key[sizeof(key)-1] = '\0';
ret = dict_get_uint32 (peer_data, key,
&new_volinfo->quota_conf_version);
@@ -3446,7 +3657,7 @@ glusterd_import_quota_conf (dict_t *peer_data, int vol_idx,
gf_log (this->name, GF_LOG_DEBUG, "Failed to get quota "
"version");
- snprintf (key, sizeof (key)-1, "volume%d.gfid-count", vol_idx);
+ snprintf (key, sizeof (key)-1, "%s%d.gfid-count", prefix, vol_idx);
key[sizeof(key)-1] = '\0';
ret = dict_get_int32 (peer_data, key, &gfid_count);
if (ret)
@@ -3462,8 +3673,8 @@ glusterd_import_quota_conf (dict_t *peer_data, int vol_idx,
gfid_idx = 0;
for (gfid_idx = 0; gfid_idx < gfid_count; gfid_idx++) {
- snprintf (key, sizeof (key)-1, "volume%d.gfid%d",
- vol_idx, gfid_idx);
+ snprintf (key, sizeof (key)-1, "%s%d.gfid%d",
+ prefix, vol_idx, gfid_idx);
key[sizeof(key)-1] = '\0';
ret = dict_get_str (peer_data, key, &gfid_str);
if (ret)
@@ -3546,12 +3757,18 @@ 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
+ */
int32_t
glusterd_import_volinfo (dict_t *peer_data, int count,
- glusterd_volinfo_t **volinfo)
+ glusterd_volinfo_t **volinfo,
+ char *prefix)
{
int ret = -1;
char key[256] = {0};
+ char *parent_volname = NULL;
char *volname = NULL;
glusterd_volinfo_t *new_volinfo = NULL;
char *volume_id_str = NULL;
@@ -3569,8 +3786,9 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
GF_ASSERT (peer_data);
GF_ASSERT (volinfo);
+ GF_ASSERT (prefix);
- snprintf (key, sizeof (key), "volume%d.name", count);
+ snprintf (key, sizeof (key), "%s%d.name", prefix, count);
ret = dict_get_str (peer_data, key, &volname);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload", key);
@@ -3578,7 +3796,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.is_snap_volume", count);
+ snprintf (key, sizeof (key), "%s%d.is_snap_volume", prefix, count);
ret = dict_get_uint32 (peer_data, key, &is_snap_volume);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3586,21 +3804,13 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
goto out;
}
- if (is_snap_volume == _gf_true) {
- gf_log (THIS->name, GF_LOG_DEBUG,
- "Not syncing snap volume %s", volname);
- ret = 0;
- goto out;
- }
-
ret = glusterd_volinfo_new (&new_volinfo);
if (ret)
goto out;
strncpy (new_volinfo->volname, volname, sizeof (new_volinfo->volname));
-
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.type", count);
+ snprintf (key, sizeof (key), "%s%d.type", prefix, count);
ret = dict_get_int32 (peer_data, key, &new_volinfo->type);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3608,8 +3818,14 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
goto out;
}
+ snprintf (key, sizeof (key), "%s%d.parent_volname", prefix, count);
+ ret = dict_get_str (peer_data, key, &parent_volname);
+ if (!ret)
+ strncpy (new_volinfo->parent_volname, parent_volname,
+ sizeof(new_volinfo->parent_volname));
+
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.brick_count", count);
+ snprintf (key, sizeof (key), "%s%d.brick_count", prefix, count);
ret = dict_get_int32 (peer_data, key, &new_volinfo->brick_count);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3618,7 +3834,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.version", count);
+ snprintf (key, sizeof (key), "%s%d.version", prefix, count);
ret = dict_get_int32 (peer_data, key, &new_volinfo->version);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3627,7 +3843,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.status", count);
+ snprintf (key, sizeof (key), "%s%d.status", prefix, count);
ret = dict_get_int32 (peer_data, key, (int32_t *)&new_volinfo->status);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3636,7 +3852,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.sub_count", count);
+ snprintf (key, sizeof (key), "%s%d.sub_count", prefix, count);
ret = dict_get_int32 (peer_data, key, &new_volinfo->sub_count);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3647,7 +3863,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
/* not having a 'stripe_count' key is not a error
(as peer may be of old version) */
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.stripe_count", count);
+ snprintf (key, sizeof (key), "%s%d.stripe_count", prefix, count);
ret = dict_get_int32 (peer_data, key, &new_volinfo->stripe_count);
if (ret)
gf_log (THIS->name, GF_LOG_INFO,
@@ -3656,7 +3872,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
/* not having a 'replica_count' key is not a error
(as peer may be of old version) */
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.replica_count", count);
+ snprintf (key, sizeof (key), "%s%d.replica_count", prefix, count);
ret = dict_get_int32 (peer_data, key, &new_volinfo->replica_count);
if (ret)
gf_log (THIS->name, GF_LOG_INFO,
@@ -3665,7 +3881,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
/* not having a 'dist_count' key is not a error
(as peer may be of old version) */
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.dist_count", count);
+ snprintf (key, sizeof (key), "%s%d.dist_count", prefix, count);
ret = dict_get_int32 (peer_data, key, &new_volinfo->dist_leaf_count);
if (ret)
gf_log (THIS->name, GF_LOG_INFO,
@@ -3673,7 +3889,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
new_volinfo->subvol_count = new_volinfo->brick_count/
glusterd_get_dist_leaf_count (new_volinfo);
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.ckusm", count);
+ snprintf (key, sizeof (key), "%s%d.ckusm", prefix, count);
ret = dict_get_uint32 (peer_data, key, &new_volinfo->cksum);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3682,7 +3898,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.volume_id", count);
+ snprintf (key, sizeof (key), "%s%d.volume_id", prefix, count);
ret = dict_get_str (peer_data, key, &volume_id_str);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3693,7 +3909,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
uuid_parse (volume_id_str, new_volinfo->volume_id);
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.username", count);
+ snprintf (key, sizeof (key), "%s%d.username", prefix, count);
ret = dict_get_str (peer_data, key, &str);
if (!ret) {
ret = glusterd_auth_set_username (new_volinfo, str);
@@ -3702,7 +3918,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.password", count);
+ snprintf (key, sizeof (key), "%s%d.password", prefix, count);
ret = dict_get_str (peer_data, key, &str);
if (!ret) {
ret = glusterd_auth_set_password (new_volinfo, str);
@@ -3711,7 +3927,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.transport_type", count);
+ snprintf (key, sizeof (key), "%s%d.transport_type", prefix, count);
ret = dict_get_uint32 (peer_data, key, &new_volinfo->transport_type);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3721,7 +3937,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
new_volinfo->is_snap_volume = is_snap_volume;
- snprintf (key, sizeof (key), "volume%d.restored_from_snap", count);
+ snprintf (key, sizeof (key), "%s%d.restored_from_snap", prefix, count);
ret = dict_get_str (peer_data, key, &restored_snap);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3731,7 +3947,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
uuid_parse (restored_snap, new_volinfo->restored_from_snap);
- snprintf (key, sizeof (key), "volume%d.snap-max-hard-limit", count);
+ snprintf (key, sizeof (key), "%s%d.snap-max-hard-limit", prefix, count);
ret = dict_get_uint64 (peer_data, key,
&new_volinfo->snap_max_hard_limit);
if (ret) {
@@ -3741,7 +3957,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.rebalance", count);
+ snprintf (key, sizeof (key), "%s%d.rebalance", prefix, count);
ret = dict_get_uint32 (peer_data, key, &new_volinfo->rebal.defrag_cmd);
if (ret) {
snprintf (msg, sizeof (msg), "%s missing in payload for %s",
@@ -3750,7 +3966,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.rebalance-id", count);
+ snprintf (key, sizeof (key), "%s%d.rebalance-id", prefix, count);
ret = dict_get_str (peer_data, key, &rebalance_id_str);
if (ret) {
/* This is not present in older glusterfs versions,
@@ -3762,7 +3978,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.rebalance-op", count);
+ snprintf (key, sizeof (key), "%s%d.rebalance-op", prefix, count);
ret = dict_get_uint32 (peer_data, key,
(uint32_t *) &new_volinfo->rebal.op);
if (ret) {
@@ -3780,7 +3996,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, 256, "volume%d."GLUSTERD_STORE_KEY_RB_STATUS, count);
+ snprintf (key, 256, "%s%d."GLUSTERD_STORE_KEY_RB_STATUS, prefix, count);
ret = dict_get_int32 (peer_data, key, &rb_status);
if (ret)
goto out;
@@ -3789,8 +4005,8 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
if (new_volinfo->rep_brick.rb_status > GF_RB_STATUS_NONE) {
memset (key, 0, sizeof (key));
- snprintf (key, 256, "volume%d."GLUSTERD_STORE_KEY_RB_SRC_BRICK,
- count);
+ snprintf (key, 256, "%s%d."GLUSTERD_STORE_KEY_RB_SRC_BRICK,
+ prefix, count);
ret = dict_get_str (peer_data, key, &src_brick);
if (ret)
goto out;
@@ -3804,8 +4020,8 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, 256, "volume%d."GLUSTERD_STORE_KEY_RB_DST_BRICK,
- count);
+ snprintf (key, 256, "%s%d."GLUSTERD_STORE_KEY_RB_DST_BRICK,
+ prefix, count);
ret = dict_get_str (peer_data, key, &dst_brick);
if (ret)
goto out;
@@ -3819,7 +4035,7 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.rb_id", count);
+ snprintf (key, sizeof (key), "%s%d.rb_id", prefix, count);
ret = dict_get_str (peer_data, key, &rb_id_str);
if (ret) {
/* This is not present in older glusterfs versions,
@@ -3846,12 +4062,12 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
* present. Only one being present is a failure
*/
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.op-version", count);
+ snprintf (key, sizeof (key), "%s%d.op-version", prefix, count);
ret = dict_get_int32 (peer_data, key, &op_version);
if (ret)
ret = 0;
memset (key, 0, sizeof (key));
- snprintf (key, sizeof (key), "volume%d.client-op-version", count);
+ snprintf (key, sizeof (key), "%s%d.client-op-version", prefix, count);
ret = dict_get_int32 (peer_data, key, &client_op_version);
if (ret)
ret = 0;
@@ -3871,11 +4087,11 @@ glusterd_import_volinfo (dict_t *peer_data, int count,
}
memset (key, 0 ,sizeof (key));
- snprintf (key, sizeof (key), "volume%d.caps", count);
+ snprintf (key, sizeof (key), "%s%d.caps", prefix, count);
/*This is not present in older glusterfs versions, so ignore ret value*/
ret = dict_get_int32 (peer_data, key, &new_volinfo->caps);
- ret = glusterd_import_bricks (peer_data, count, new_volinfo);
+ ret = glusterd_import_bricks (peer_data, count, new_volinfo, prefix);
if (ret)
goto out;
@@ -4107,7 +4323,8 @@ glusterd_import_friend_volume (dict_t *peer_data, size_t count)
GF_ASSERT (this);
priv = this->private;
GF_ASSERT (priv);
- ret = glusterd_import_volinfo (peer_data, count, &new_volinfo);
+ ret = glusterd_import_volinfo (peer_data, count,
+ &new_volinfo, "volume");
if (ret)
goto out;
@@ -4133,7 +4350,8 @@ glusterd_import_friend_volume (dict_t *peer_data, size_t count)
if (ret)
goto out;
- ret = glusterd_import_quota_conf (peer_data, count, new_volinfo);
+ ret = glusterd_import_quota_conf (peer_data, count,
+ new_volinfo, "volume");
if (ret)
goto out;
@@ -4473,6 +4691,602 @@ out:
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 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->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);
+
+ list_for_each_entry (brickinfo, &snap_vol->bricks, brick_list) {
+ if (uuid_compare (brickinfo->uuid, MY_UUID))
+ continue;
+
+ if (brickinfo->snap_status == -1) {
+ gf_log (this->name, GF_LOG_INFO,
+ "not starting snap brick %s:%s for "
+ "for the snap %s (volume: %s)",
+ brickinfo->hostname, brickinfo->path,
+ peer_snap_name, parent_volinfo->volname);
+ continue;
+ }
+
+ ret = glusterd_brick_start (snap_vol, brickinfo, _gf_true);
+ if (ret) {
+ gf_log (this->name, GF_LOG_WARNING, "starting the "
+ "brick %s:%s for the snap %s (volume: %s) "
+ "failed", brickinfo->hostname, brickinfo->path,
+ peer_snap_name, parent_volinfo->volname);
+ goto out;
+ }
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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 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 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)