From ef02610d4b1b2165e2c076c1aa9584bd634b2b56 Mon Sep 17 00:00:00 2001 From: shishir gowda Date: Tue, 24 Sep 2013 16:44:24 +0530 Subject: mgmt/glusterd: Introduce snapshot infrastructure API's for creating, adding, finding, removing snapshots and consistency groups are provided. Signed-off-by: shishir gowda --- xlators/mgmt/glusterd/src/glusterd-mem-types.h | 4 +- xlators/mgmt/glusterd/src/glusterd-utils.c | 303 +++++++++++++++++++++++++ xlators/mgmt/glusterd/src/glusterd.c | 2 + xlators/mgmt/glusterd/src/glusterd.h | 78 +++++++ 4 files changed, 386 insertions(+), 1 deletion(-) diff --git a/xlators/mgmt/glusterd/src/glusterd-mem-types.h b/xlators/mgmt/glusterd/src/glusterd-mem-types.h index 51057c274..c1009d66f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mem-types.h +++ b/xlators/mgmt/glusterd/src/glusterd-mem-types.h @@ -67,7 +67,9 @@ typedef enum gf_gld_mem_types_ { gf_gld_mt_hooks_priv_t = gf_common_mt_end + 51, gf_gld_mt_mop_commit_req_t = gf_common_mt_end + 52, gf_gld_mt_int = gf_common_mt_end + 53, - gf_gld_mt_end = gf_common_mt_end + 54, + gf_gld_mt_snap_t = gf_common_mt_end + 54, + gf_gld_mt_snap_cg_t = gf_common_mt_end + 55, + gf_gld_mt_end = gf_common_mt_end + 56, } gf_gld_mem_types_t; #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index b0f9a210f..6eb508e89 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -430,8 +430,10 @@ glusterd_volinfo_new (glusterd_volinfo_t **volinfo) if (!new_volinfo) goto out; + LOCK_INIT (&new_volinfo->lock); INIT_LIST_HEAD (&new_volinfo->vol_list); INIT_LIST_HEAD (&new_volinfo->bricks); + INIT_LIST_HEAD (&new_volinfo->snaps); new_volinfo->dict = dict_new (); if (!new_volinfo->dict) { @@ -7695,3 +7697,304 @@ out: gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); return ret; } + +glusterd_snap_t* +glusterd_new_snap_object() +{ + glusterd_snap_t *snap = NULL; + + snap = GF_CALLOC (1, sizeof (*snap), gf_gld_mt_snap_t); + + if (snap) { + LOCK_INIT (&snap->lock); + INIT_LIST_HEAD (&snap->snap_list); + snap->snap_status = GD_SNAP_STATUS_INIT; + } + + return snap; + +}; + +glusterd_snap_cg_t* +glusterd_new_snap_cg_object(int64_t volume_count) +{ + glusterd_snap_cg_t *cg = NULL; + glusterd_volinfo_t *volinfo = NULL; + + if (volume_count < 0) { + gf_log (THIS->name, GF_LOG_ERROR, "Volume count < 0"); + return NULL; + } + + cg = GF_CALLOC (1, (sizeof (*cg) + + (volume_count * sizeof (*volinfo))), + gf_gld_mt_snap_cg_t); + + if (cg) { + LOCK_INIT (&cg->lock); + INIT_LIST_HEAD (&cg->cg_list); + cg->cg_status = GD_SNAP_STATUS_INIT; + cg->volume_count = volume_count; + } + + return cg; +} + +int32_t +glusterd_add_snap (glusterd_volinfo_t *volinfo, glusterd_snap_t *snap) +{ + int ret = -1; + uint64_t count = -1; + glusterd_snap_t *entry = NULL; + glusterd_snap_t *last = NULL; + glusterd_snap_t *tmp = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + GF_VALIDATE_OR_GOTO ("glusterd", snap, out); + + LOCK (&volinfo->lock); + { + list_for_each_entry_safe (entry, tmp, &volinfo->snaps, + snap_list) { + count++; + if (!strcmp (entry->snap_name, snap->snap_name) || + !uuid_compare (entry->snap_id, snap->snap_id)) { + gf_log (THIS->name, GF_LOG_ERROR, "Found " + "duplicate snap %s (%s)", + entry->snap_name, + uuid_utoa (entry->snap_id)); + goto unlock; + } + last = entry; + } + list_add (&snap->snap_list, &last->snap_list); + + gf_log (THIS->name, GF_LOG_DEBUG, "Snap %s added @ %"PRIu64, + snap->snap_name, count); + ret = 0; + } +unlock: + UNLOCK (&volinfo->lock); +out: + return ret; +} + +glusterd_snap_t* +glusterd_find_snap_by_name (glusterd_volinfo_t *volinfo, char *snap_name) +{ + uint64_t count = -1; + glusterd_snap_t *entry = NULL; + glusterd_snap_t *dup = NULL; + glusterd_snap_t *tmp = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + GF_VALIDATE_OR_GOTO ("glusterd", snap_name, out); + + LOCK (&volinfo->lock); + { + list_for_each_entry_safe (entry, tmp, &volinfo->snaps, + snap_list) { + count++; + if (!strcmp (entry->snap_name, snap_name)) { + gf_log (THIS->name, GF_LOG_DEBUG, "Found " + "snap %s (%s)", entry->snap_name, + uuid_utoa (entry->snap_id)); + dup = entry; + break; + } + } + } + UNLOCK (&volinfo->lock); +out: + return dup; +} + +glusterd_snap_t* +glusterd_find_snap_by_id (glusterd_volinfo_t *volinfo, uuid_t snap_id) +{ + uint64_t count = -1; + glusterd_snap_t *entry = NULL; + glusterd_snap_t *dup = NULL; + glusterd_snap_t *tmp = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + if (uuid_is_null(snap_id)) + goto out; + + LOCK (&volinfo->lock); + { + list_for_each_entry_safe (entry, tmp, &volinfo->snaps, + snap_list) { + count++; + if (!uuid_compare (entry->snap_id, snap_id)) { + gf_log (THIS->name, GF_LOG_DEBUG, "Found " + "snap %s (%s)", entry->snap_name, + uuid_utoa (entry->snap_id)); + dup = entry; + break; + } + } + } + UNLOCK (&volinfo->lock); +out: + return dup; +} + +glusterd_snap_t* +glusterd_remove_snap_by_id (glusterd_volinfo_t *volinfo, uuid_t snap_id) +{ + glusterd_snap_t *entry = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + if (uuid_is_null(snap_id)) + goto out; + + entry = glusterd_find_snap_by_id (volinfo, snap_id); + + if (entry) { + LOCK (&volinfo->lock); + { + entry->snap_status = GD_SNAP_STATUS_DECOMMISSION; + list_del_init (&entry->snap_list); + } + UNLOCK (&volinfo->lock); + } +out: + return entry; +} + +glusterd_snap_t* +glusterd_remove_snap_by_name (glusterd_volinfo_t *volinfo, char *snap_name) +{ + glusterd_snap_t *entry = NULL; + + GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); + GF_VALIDATE_OR_GOTO ("glusterd", snap_name, out); + + entry = glusterd_find_snap_by_name (volinfo, snap_name); + + if (entry) { + LOCK (&volinfo->lock); + { + entry->snap_status = GD_SNAP_STATUS_DECOMMISSION; + list_del_init (&entry->snap_list); + } + UNLOCK (&volinfo->lock); + } +out: + return entry; +} + +// Big lock should already acquired before this is called +int32_t +glusterd_add_snap_cg (glusterd_conf_t *conf, glusterd_snap_cg_t *cg) +{ + int ret = -1; + uint64_t count = -1; + glusterd_snap_cg_t *entry = NULL; + glusterd_snap_cg_t *last = NULL; + glusterd_snap_cg_t *tmp = NULL; + + GF_VALIDATE_OR_GOTO (THIS->name, conf, out); + GF_VALIDATE_OR_GOTO (THIS->name, cg, out); + + list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) { + count++; + if (!strcmp (entry->cg_name, cg->cg_name) || + !uuid_compare (entry->cg_id, cg->cg_id)) { + gf_log (THIS->name, GF_LOG_ERROR, "Found duplicate " + "CG %s(%s)", entry->cg_name, + uuid_utoa(entry->cg_id)); + goto out; + } + last = entry; + } + list_add (&cg->cg_list, &last->cg_list); + gf_log (THIS->name, GF_LOG_DEBUG, "Added CG %s (%s) @ %"PRIu64, + cg->cg_name, uuid_utoa(cg->cg_id), count); + ret = 0; +out: + return ret; + +} + + +glusterd_snap_cg_t* +glusterd_find_snap_cg_by_name (glusterd_conf_t *conf, char *cg_name) +{ + glusterd_snap_cg_t *entry = NULL; + glusterd_snap_cg_t *dup = NULL; + glusterd_snap_cg_t *tmp = NULL; + + GF_VALIDATE_OR_GOTO (THIS->name, conf, out); + GF_VALIDATE_OR_GOTO (THIS->name, cg_name, out); + + list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) { + if (!strcmp (entry->cg_name, cg_name)) { + gf_log (THIS->name, GF_LOG_DEBUG, "Found CG %s(%s)", + entry->cg_name, uuid_utoa(entry->cg_id)); + dup = entry; + break; + } + } +out: + return dup; +} + +glusterd_snap_cg_t* +glusterd_find_snap_cg_by_id (glusterd_conf_t *conf, uuid_t cg_id) +{ + glusterd_snap_cg_t *entry = NULL; + glusterd_snap_cg_t *dup = NULL; + glusterd_snap_cg_t *tmp = NULL; + + GF_VALIDATE_OR_GOTO (THIS->name, conf, out); + if (uuid_is_null (cg_id)) + goto out; + + list_for_each_entry_safe (entry, tmp, &conf->snap_cg, cg_list) { + if (!uuid_compare (entry->cg_id, cg_id)) { + gf_log (THIS->name, GF_LOG_DEBUG, "Found CG %s(%s)", + entry->cg_name, uuid_utoa(entry->cg_id)); + dup = entry; + break; + } + } +out: + return dup; +} + +glusterd_snap_cg_t* +glusterd_remove_snap_cg_by_name (glusterd_conf_t *conf, char *cg_name) +{ + glusterd_snap_cg_t *entry = NULL; + + GF_VALIDATE_OR_GOTO (THIS->name, conf, out); + GF_VALIDATE_OR_GOTO (THIS->name, cg_name, out); + + entry = glusterd_find_snap_cg_by_name(conf, cg_name); + if (entry) { + entry->cg_status = GD_SNAP_STATUS_DECOMMISSION; + list_del_init (&entry->cg_list); + } +out: + return entry; +} + +glusterd_snap_cg_t* +glusterd_remove_snap_cg_by_id (glusterd_conf_t *conf, uuid_t cg_id) +{ + glusterd_snap_cg_t *entry = NULL; + + GF_VALIDATE_OR_GOTO (THIS->name, conf, out); + if (uuid_is_null (cg_id)) + goto out; + + entry = glusterd_find_snap_cg_by_id (conf, cg_id); + if (entry) { + entry->cg_status = GD_SNAP_STATUS_DECOMMISSION; + list_del_init (&entry->cg_list); + } +out: + return entry; +} diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index dc35f8bf0..bb03e5ba0 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -1123,6 +1123,8 @@ init (xlator_t *this) INIT_LIST_HEAD (&conf->peers); INIT_LIST_HEAD (&conf->volumes); + INIT_LIST_HEAD (&conf->snap_cg); + pthread_mutex_init (&conf->mutex, NULL); conf->rpc = rpc; conf->gfs_mgmt = &gd_brick_prog; diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 26e9b0c0d..e804c9ce8 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -154,6 +154,7 @@ typedef struct { dict_t *opts; synclock_t big_lock; gf_boolean_t restart_done; + struct list_head snap_cg; } glusterd_conf_t; @@ -263,11 +264,13 @@ struct glusterd_replace_brick_ { typedef struct glusterd_replace_brick_ glusterd_replace_brick_t; struct glusterd_volinfo_ { + gf_lock_t lock; char volname[GLUSTERD_MAX_VOLUME_NAME]; int type; int brick_count; struct list_head vol_list; struct list_head bricks; + struct list_head snaps; glusterd_volume_status status; int sub_count; /* backward compatibility */ int stripe_count; @@ -310,6 +313,44 @@ struct glusterd_volinfo_ { int client_op_version; }; +typedef enum gd_snap_status_ { + GD_SNAP_STATUS_NONE, + GD_SNAP_STATUS_INIT, + GD_SNAP_STATUS_IN_USE, + GD_SNAP_STATUS_DECOMMISSION, + GD_SNAP_STATUS_RESTORED, +} gd_snap_status_t; + + +struct glusterd_snap_ { + gf_lock_t lock; + glusterd_volinfo_t *snap_volume; + struct list_head snap_list; + char snap_name[256]; + uuid_t snap_id; + uuid_t cg_id; + char *description; + time_t time_stamp; + gd_snap_status_t snap_status; +}; + +typedef struct glusterd_snap_ glusterd_snap_t; + +struct glusterd_snap_cg_ { + gf_lock_t lock; + uuid_t cg_id; + char cg_name[256]; + char *description; + gd_snap_status_t cg_status; + int64_t volume_count; + struct list_head cg_list; + glusterd_volinfo_t volumes[0]; +}; + +typedef struct glusterd_snap_cg_ glusterd_snap_cg_t; + + + typedef enum gd_node_type_ { GD_NODE_NONE, GD_NODE_BRICK, @@ -760,4 +801,41 @@ int32_t glusterd_op_begin_synctask (rpcsvc_request_t *req, glusterd_op_t op, void *dict); int32_t glusterd_defrag_event_notify_handle (dict_t *dict); + +/* snapshot */ +glusterd_snap_t* +glusterd_new_snap_object(); + +glusterd_snap_cg_t* +glusterd_new_snap_cg_object(int64_t volume_count); + +int32_t +glusterd_add_snap (glusterd_volinfo_t *volinfo, glusterd_snap_t *snap); + +glusterd_snap_t* +glusterd_remove_snap_by_id (glusterd_volinfo_t *volinfo, uuid_t snap_id); + +glusterd_snap_t* +glusterd_remove_snap_by_name (glusterd_volinfo_t *volinfo, char *snap_name); + +glusterd_snap_t* +glusterd_find_snap_by_name (glusterd_volinfo_t *volinfo, char *snap_name); + +glusterd_snap_t* +glusterd_find_snap_by_id (glusterd_volinfo_t *volinfo, uuid_t snap_id); + +int32_t +glusterd_add_snap_cg (glusterd_conf_t *conf, glusterd_snap_cg_t *cg); + +glusterd_snap_cg_t* +glusterd_remove_snap_cg_by_name (glusterd_conf_t *conf, char *cg_name); + +glusterd_snap_cg_t* +glusterd_remove_snap_cg_by_id (glusterd_conf_t *conf, uuid_t cg_id); + +glusterd_snap_cg_t* +glusterd_find_snap_cg_by_id (glusterd_conf_t *conf, uuid_t cg_id); + +glusterd_snap_cg_t* +glusterd_find_snap_cg_by_name (glusterd_conf_t *conf, char *cg_name); #endif -- cgit