From 123db32a53f7e2f99c0d63b368ed8a8ee6b41f62 Mon Sep 17 00:00:00 2001 From: Raghavendra Bhat Date: Thu, 20 Mar 2014 14:46:02 +0530 Subject: mgmt/glusterd: do cleanup of snapshots in post-validate phase if half baked objects are there Change-Id: I372cac98ad054cdc1a6fbc7f6c77c25981063b2f Signed-off-by: Raghavendra Bhat Reviewed-on: http://review.gluster.org/7237 Reviewed-by: Rajesh Joseph Tested-by: Rajesh Joseph --- xlators/mgmt/glusterd/src/glusterd-snapshot.c | 147 +++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 1 deletion(-) (limited to 'xlators/mgmt/glusterd/src/glusterd-snapshot.c') diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index db2d88831..5759bded4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -2685,7 +2685,12 @@ glusterd_create_snap_object (dict_t *dict) strcpy (snap->snapname, snapname); uuid_copy (snap->snap_id, *snap_id); snap->time_stamp = (time_t)time_stamp; - snap->snap_status = GD_SNAP_STATUS_IN_USE; + /* Set the status as GD_SNAP_STATUS_INIT and once the backend snapshot + is taken and snap is really ready to use, set the status to + GD_SNAP_STATUS_IN_USE. This helps in identifying the incomplete + snapshots and cleaning them up. + */ + snap->snap_status = GD_SNAP_STATUS_INIT; if (description) { snap->description = gf_strdup (description); if (snap->description == NULL) { @@ -2705,8 +2710,10 @@ glusterd_create_snap_object (dict_t *dict) list_add_order (&snap->snap_list, &priv->snapshots, glusterd_compare_snap_time); + gf_log (this->name, GF_LOG_TRACE, "Snap %s added to the list", snap->snapname); + ret = 0; out: @@ -3557,6 +3564,61 @@ out: return ret; } +int32_t +glusterd_do_snap_cleanup (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ + int32_t ret = -1; + char *name = NULL; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_snap_t *snap = NULL; + + this = THIS; + GF_ASSERT (this); + conf = this->private; + GF_ASSERT (conf); + + if (!dict || !op_errstr) { + gf_log (this->name, GF_LOG_ERROR, "input parameters NULL"); + goto out; + } + + ret = dict_get_str (dict, "snapname", &name); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "getting the snap " + "name failed (volume: %s)", volinfo->volname); + goto out; + } + + /* + If the snapname is not found that means the failure happened at + staging, or in commit, before the snap object is created, in which + case there is nothing to cleanup. So set ret to 0. + */ + snap = glusterd_find_snap_by_name (name); + if (!snap) { + gf_log (this->name, GF_LOG_INFO, "snap %s is not found", name); + ret = 0; + goto out; + } + + ret = glusterd_snap_remove (snap, _gf_true, _gf_true); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "removing the snap %s failed", + name); + goto out; + } + + name = NULL; + + ret = 0; + +out: + + return ret; +} + int32_t glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, dict_t *rsp_dict) @@ -3643,6 +3705,14 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, } } + snap->snap_status = GD_SNAP_STATUS_IN_USE; + ret = glusterd_store_snap (snap); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Could not store snap" + "object %s", snap->snapname); + goto out; + } + ret = 0; out: @@ -4569,6 +4639,38 @@ out : return ret; } +int32_t +glusterd_snapshot_create_postvalidate (dict_t *dict, int32_t op_ret, + char **op_errstr, dict_t *rsp_dict) +{ + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + int ret = -1; + + this = THIS; + + GF_ASSERT (this); + GF_ASSERT (dict); + GF_ASSERT (rsp_dict); + + priv = this->private; + GF_ASSERT (priv); + + if (op_ret) { + ret = glusterd_do_snap_cleanup (dict, op_errstr, rsp_dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "cleanup operation " + "failed"); + goto out; + } + } + + ret = 0; + +out: + return ret; +} + int32_t glusterd_snapshot (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { @@ -4796,6 +4898,49 @@ out: return ret; } +int +glusterd_snapshot_postvalidate (dict_t *dict, int32_t op_ret, char **op_errstr, + dict_t *rsp_dict) +{ + int snap_command = 0; + xlator_t *this = NULL; + int ret = -1; + + this = THIS; + + GF_ASSERT (this); + GF_ASSERT (dict); + GF_ASSERT (rsp_dict); //not sure if this is needed, verify. + + 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_snapshot_create_postvalidate (dict, op_ret, + op_errstr, + rsp_dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Snapshot create " + "post-validation failed"); + goto out; + } + break; + + default: + gf_log (this->name, GF_LOG_WARNING, "invalid snap command"); + goto out; + } + + ret = 0; +out: + return ret; +} + int glusterd_handle_snapshot_fn (rpcsvc_request_t *req) { -- cgit