From 727a63c3a5f9cab5af6089826d81df2035e1c0b6 Mon Sep 17 00:00:00 2001 From: Rajesh Joseph Date: Fri, 13 Dec 2013 11:53:21 +0530 Subject: Snapshot: Gluster snapshot restore feature Implemented gluster snapshot restore feature. The restore is done by replacing the origin volume with the snap volume. TODO: After the restore the snapshot volume should be deleted. As of now the deletion work is pending. Change-Id: Ib137fb6bb84a74030607ffa47f89cd705dc7e1ff Signed-off-by: Rajesh Joseph --- xlators/mgmt/glusterd/src/glusterd-snapshot.c | 171 ++------- xlators/mgmt/glusterd/src/glusterd-store.c | 150 ++++++-- xlators/mgmt/glusterd/src/glusterd-store.h | 95 ++--- xlators/mgmt/glusterd/src/glusterd-utils.c | 31 +- xlators/mgmt/glusterd/src/glusterd-volgen.c | 514 +++++++++++++++++++++++++- xlators/mgmt/glusterd/src/glusterd-volgen.h | 5 +- xlators/mgmt/glusterd/src/glusterd.h | 18 +- 7 files changed, 737 insertions(+), 247 deletions(-) (limited to 'xlators') diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index acc8bef16..8419cfb25 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -48,139 +48,6 @@ char * generate_snapname (char *volname, char *name, gf_boolean_t volume_from_cg); -/* This function will do the actual snapshot restore on the brick. - * - * @param brickinfo brickinfo structure - * @param snapname name of the snap which will be restored - * - * @return Negative value on Failure and 0 in success - */ -int -glusterd_snapshot_restore_brick_snap (glusterd_brickinfo_t *brickinfo, - char *snapname) -{ - int ret = -1; - char *device = NULL; - xlator_t *this = NULL; - runner_t runner = {0,}; - glusterd_conf_t *conf = NULL; - char msg[PATH_MAX] = {0,}; - - this = THIS; - GF_ASSERT (this); - conf = this->private; - - GF_ASSERT (conf); - GF_ASSERT (brickinfo); - GF_ASSERT (snapname); - - /* Using the brickinfo get the actual device name */ - device = glusterd_get_brick_mount_details (brickinfo); - - runinit (&runner); - snprintf (msg, sizeof (msg), "Restoring snapshot of the brick %s:%s " - "to %s snap", brickinfo->hostname, brickinfo->path, snapname); - - /* Command for restoring the snapshot */ - runner_add_args (&runner, "/sbin/lvconvert", "--merge", device, NULL); - runner_log (&runner, "", GF_LOG_DEBUG, msg); - - synclock_unlock (&conf->big_lock); - /* Run the actual command */ - ret = runner_run (&runner); - synclock_lock (&conf->big_lock); - - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "snapshot restore of the " - "brick (%s:%s) of device %s failed", - brickinfo->hostname, brickinfo->path, device); - goto out; - } - -out: - return ret; -} - -/* This function will restore the snapshot for the entire volume. - * - * @param snap snap object which needs to be restored - * @param op_errstr In case of any failure error message will be returned - * in this variable - * @return Negative value on Failure and 0 in success - */ -int -glusterd_snapshot_restore_snap (glusterd_snap_t *snap, char **op_errstr) -{ - int ret = -1; - xlator_t *this = NULL; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - - this = THIS; - - GF_ASSERT (this); - GF_ASSERT (snap); - GF_ASSERT (snap->snap_volume); - GF_ASSERT (op_errstr); - - /* For restore always take volinfo stored in snap. Do not use - * volinfo of the original volume*/ - volinfo = snap->snap_volume; - - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - /* This code is executed on each node of the volume. We need - * to run the restore only on those bricks which are present - * in this node. Therefore check if node belongs to this node - * or not. - */ - if (uuid_compare (brickinfo->uuid, MY_UUID)) { - continue; /* Bricks not present in this node */ - } - - /* This case should never occur as volume is already stopped. - * Just to avoid a case where the brick is explicitly started - * by the user we have this check here. - */ - if (glusterd_is_brick_started (brickinfo)) { - ret = gf_asprintf (op_errstr, "Brick (%s: %s) is " - "running therefore snapshot cannot " - "be restored", brickinfo->hostname, - brickinfo->path); - if (ret < 0) { - goto out; - } - - gf_log (this->name, GF_LOG_ERROR, "%s", *op_errstr); - ret = -1; - goto out; - } - - /* Do the actual snapshot restore */ - ret = glusterd_snapshot_restore_brick_snap (brickinfo, - snap->snap_name); - if (ret) { - ret = gf_asprintf (op_errstr, "Snapshot restore failed" - " for %s:%s", brickinfo->hostname, - brickinfo->path); - if (ret < 0) { - goto out; - } - - gf_log (this->name, GF_LOG_ERROR, "%s", *op_errstr); - ret = -1; - goto out; - } - - } - - /* TODO: Move this code to postvalidate */ - snap->snap_restored = _gf_true; - /* TODO: persist the change in store */ - -out: - return ret; -} - /* This function will restore a snapshot for the entire * volume or the entire CG (Consistency Group) * @@ -260,7 +127,7 @@ glusterd_snapshot_restore (dict_t *dict, char **op_errstr) } /* Restore the snap for the entire volume */ - ret = glusterd_snapshot_restore_snap (snap, op_errstr); + ret = gd_restore_snap_volume (volinfo, snap->snap_volume); if (ret) { /* No need to update op_errstr because it is assumed * that the called function will do that in case of @@ -289,10 +156,12 @@ out: * @param dict dictionary containing snapshot restore request * @param op_errstr In case of any failure error message will be returned * in this variable + * @param rsp_dict response dictionary * @return Negative value on Failure and 0 in success */ int -glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr) +glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) { int ret = -1; int64_t i = 0; @@ -300,6 +169,7 @@ glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr) gf_boolean_t snap_restored = _gf_false; char *volname = NULL; char *snapname = NULL; + char *cgname = NULL; glusterd_volinfo_t *volinfo = NULL; glusterd_snap_t *snap = NULL; xlator_t *this = NULL; @@ -310,6 +180,30 @@ glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr) GF_ASSERT (this); GF_ASSERT (dict); GF_ASSERT (op_errstr); + GF_ASSERT (rsp_dict); + + ret = dict_get_str (dict, "cgname", &cgname); + if (ret) { + ret = dict_get_str (dict, "snapname", &snapname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get " + "neither snapname nor cgname"); + goto out; + } + ret = dict_set_str (rsp_dict, "snapname", snapname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to set " + "snap name"); + goto out; + } + } else { + ret = dict_set_str (rsp_dict, "cgname", cgname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to set " + "CG name"); + goto out; + } + } ret = dict_get_int64 (dict, "volcount", &volcount); @@ -3234,7 +3128,7 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict, } ret = generate_snap_client_volfiles (volinfo, snap_volume, - GF_CLIENT_TRUSTED); + GF_CLIENT_TRUSTED, _gf_false); if (ret) { gf_log (this->name, GF_LOG_ERROR, "generating the trusted " "client volfiles for the snap %s (volume: %s) failed", @@ -3243,7 +3137,7 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *snapname, dict_t *dict, } ret = generate_snap_client_volfiles (volinfo, snap_volume, - GF_CLIENT_OTHER); + GF_CLIENT_OTHER, _gf_false); if (ret) { gf_log (this->name, GF_LOG_ERROR, "generating the client " "volfiles for the snap %s (volume: %s) failed", @@ -4657,7 +4551,8 @@ glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, break; case GF_SNAP_OPTION_TYPE_RESTORE: - ret = glusterd_snapshot_restore_prevalidate (dict, op_errstr); + ret = glusterd_snapshot_restore_prevalidate (dict, op_errstr, + rsp_dict); if (ret) { gf_log (this->name, GF_LOG_WARNING, "Snapshot restore " "validation failed"); diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c index d6e071b74..41633ebd8 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.c +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -607,14 +607,13 @@ int _storeopts (dict_t *this, char *key, data_t *value, void *data) int32_t glusterd_volume_exclude_options_write (int fd, glusterd_volinfo_t *volinfo) { - char *str = NULL; + char *str = NULL; + char buf[PATH_MAX] = {0,}; + int32_t ret = -1; GF_ASSERT (fd > 0); GF_ASSERT (volinfo); - char buf[PATH_MAX] = {0,}; - int32_t ret = -1; - snprintf (buf, sizeof (buf), "%d", volinfo->type); ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_VOL_TYPE, buf); if (ret) @@ -703,6 +702,14 @@ glusterd_volume_exclude_options_write (int fd, glusterd_volinfo_t *volinfo) goto out; } + snprintf (buf, sizeof (buf), "%d", volinfo->is_volume_restored); + ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_VOL_IS_RESTORED, buf); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "Unable to write is_volume_restored"); + goto out; + } + snprintf (buf, sizeof (buf), "%"PRIu64, volinfo->snap_max_hard_limit); ret = gf_store_save_value (fd, GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT, buf); @@ -1519,11 +1526,17 @@ glusterd_store_perform_snap_store (glusterd_volinfo_t *volinfo) list_for_each_entry_safe (entry, tmp, &volinfo->snaps, snap_list) { ret = glusterd_store_snap_list_write (fd, entry, count); - if (ret) + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to " + "write snap list to store"); goto unlock; + } ret = glusterd_store_snap_volume (volinfo, entry); - if (ret) + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to " + "store snap volume"); goto unlock; + } count++; } snprintf (buf, sizeof(buf), "%"PRIu64, count); @@ -2680,53 +2693,66 @@ out: return ret; } -int32_t -glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap) -{ - int32_t ret = -1; - glusterd_volinfo_t *volinfo = NULL; - gf_store_iter_t *iter = NULL; - char *key = NULL; - char *value = NULL; - char volpath[PATH_MAX] = {0,}; - glusterd_conf_t *priv = NULL; - char path[PATH_MAX] = {0,}; - int exists = 0; - gf_store_op_errno_t op_errno = GD_STORE_SUCCESS; - glusterd_volinfo_t *parent_vol = NULL; - - GF_ASSERT (volname); - ret = glusterd_volinfo_new (&volinfo); - if (ret) - goto out; +int +glusterd_store_update_volinfo (glusterd_volinfo_t *volinfo, + glusterd_snap_t *snap) +{ + int ret = -1; + int exists = 0; + uint64_t count = 0; + char *key = NULL; + char *value = NULL; + char volpath[PATH_MAX] = {0,}; + char path[PATH_MAX] = {0,}; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + gf_store_iter_t *iter = NULL; + gf_store_op_errno_t op_errno = GD_STORE_SUCCESS; + glusterd_volinfo_t *parent_vol = NULL; - priv = THIS->private; + this = THIS; + GF_ASSERT (this); + conf = THIS->private; + GF_ASSERT (volinfo); if (snap) { - ret = glusterd_volinfo_find (volname, &parent_vol); - if (ret) + ret = glusterd_volinfo_find (volinfo->parent_volname, + &parent_vol); + if (ret) { + gf_log (this->name, GF_LOG_DEBUG, "Failed to get parent" + " volume for %s snap volume", volinfo->volname); goto out; - strncpy (volinfo->volname, snap->snap_name, GLUSTERD_MAX_VOLUME_NAME); - GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, snap->snap_name, priv); + } + + GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, snap->snap_name, + conf); } else { - strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); - GLUSTERD_GET_VOLUME_DIR(volpath, volinfo, priv); + GLUSTERD_GET_VOLUME_DIR(volpath, volinfo, conf); } + snprintf (path, sizeof (path), "%s/%s", volpath, GLUSTERD_VOLUME_INFO_FILE); ret = gf_store_handle_retrieve (path, &volinfo->shandle); - if (ret) + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "snap handle is NULL"); goto out; + } ret = gf_store_iter_new (volinfo->shandle, &iter); - if (ret) + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get new store " + "iter"); goto out; + } ret = gf_store_iter_get_next (iter, &key, &value, &op_errno); - if (ret) + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get next store " + "iter"); goto out; + } while (!ret) { gf_log ("", GF_LOG_DEBUG, "key = %s value = %s", key, value); @@ -2801,6 +2827,9 @@ glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap) } else if (!strncmp (key, GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT, strlen (GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT))) { volinfo->snap_max_hard_limit = (uint64_t) atoll (value); + } else if (!strncmp (key, GLUSTERD_STORE_KEY_VOL_IS_RESTORED, + strlen (GLUSTERD_STORE_KEY_VOL_IS_RESTORED))) { + volinfo->is_volume_restored = atoi (value); } else if (!strncmp (key, GLUSTERD_STORE_KEY_PARENT_VOLNAME, strlen (GLUSTERD_STORE_KEY_PARENT_VOLNAME))) { strncpy (volinfo->parent_volname, value, sizeof(volinfo->parent_volname) - 1); @@ -2891,10 +2920,57 @@ glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap) goto out; ret = gf_store_iter_destroy (iter); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to destroy store " + "iter"); + goto out; + } + ret = 0; +out: + return ret; +} + +int32_t +glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap) +{ + int32_t ret = -1; + char volpath[PATH_MAX] = {0,}; + glusterd_volinfo_t *volinfo = NULL; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *parent_vol = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + GF_ASSERT (volname); + + ret = glusterd_volinfo_new (&volinfo); if (ret) goto out; + priv = THIS->private; + + if (snap) { + ret = glusterd_volinfo_find (volname, &parent_vol); + if (ret) + goto out; + strncpy (volinfo->volname, snap->snap_name, GLUSTERD_MAX_VOLUME_NAME); + GLUSTERD_GET_SNAP_DIR (volpath, parent_vol, snap->snap_name, priv); + } else { + strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); + GLUSTERD_GET_VOLUME_DIR(volpath, volinfo, priv); + } + + ret = glusterd_store_update_volinfo (volinfo, snap); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to update volinfo " + "for %s volume", volname); + goto out; + } + if (snap) ret = glusterd_store_retrieve_bricks (parent_vol, volinfo); else @@ -2916,12 +2992,12 @@ glusterd_store_retrieve_volume (char *volname, glusterd_snap_t *snap) // as of now snap volume are also added to the list of volume volinfo->is_snap_volume = _gf_true; snap->snap_volume = volinfo; - list_add_tail (&volinfo->vol_list, &priv->volumes); + list_add_tail (&volinfo->vol_list, &priv->volumes); } out: - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + gf_log ("", GF_LOG_TRACE, "Returning with %d", ret); return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h index 02e723fe2..d9192e396 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.h +++ b/xlators/mgmt/glusterd/src/glusterd-store.h @@ -35,55 +35,55 @@ typedef enum glusterd_store_ver_ac_{ } glusterd_volinfo_ver_ac_t; -#define GLUSTERD_STORE_UUID_KEY "UUID" - -#define GLUSTERD_STORE_KEY_VOL_TYPE "type" -#define GLUSTERD_STORE_KEY_VOL_COUNT "count" -#define GLUSTERD_STORE_KEY_VOL_STATUS "status" -#define GLUSTERD_STORE_KEY_VOL_PORT "port" -#define GLUSTERD_STORE_KEY_VOL_SUB_COUNT "sub_count" -#define GLUSTERD_STORE_KEY_VOL_STRIPE_CNT "stripe_count" -#define GLUSTERD_STORE_KEY_VOL_REPLICA_CNT "replica_count" -#define GLUSTERD_STORE_KEY_VOL_BRICK "brick" -#define GLUSTERD_STORE_KEY_VOL_VERSION "version" -#define GLUSTERD_STORE_KEY_VOL_TRANSPORT "transport-type" -#define GLUSTERD_STORE_KEY_VOL_ID "volume-id" -#define GLUSTERD_STORE_KEY_RB_STATUS "rb_status" -#define GLUSTERD_STORE_KEY_RB_SRC_BRICK "rb_src" -#define GLUSTERD_STORE_KEY_RB_DST_BRICK "rb_dst" -#define GLUSTERD_STORE_KEY_RB_DST_PORT "rb_port" -#define GLUSTERD_STORE_KEY_VOL_DEFRAG "rebalance_status" -#define GLUSTERD_STORE_KEY_DEFRAG_OP "rebalance_op" -#define GLUSTERD_STORE_KEY_USERNAME "username" -#define GLUSTERD_STORE_KEY_PASSWORD "password" -#define GLUSTERD_STORE_KEY_PARENT_VOLNAME "parent_volname" -#define GLUSTERD_STORE_KEY_VOL_OP_VERSION "op-version" +#define GLUSTERD_STORE_UUID_KEY "UUID" + +#define GLUSTERD_STORE_KEY_VOL_TYPE "type" +#define GLUSTERD_STORE_KEY_VOL_COUNT "count" +#define GLUSTERD_STORE_KEY_VOL_STATUS "status" +#define GLUSTERD_STORE_KEY_VOL_PORT "port" +#define GLUSTERD_STORE_KEY_VOL_SUB_COUNT "sub_count" +#define GLUSTERD_STORE_KEY_VOL_STRIPE_CNT "stripe_count" +#define GLUSTERD_STORE_KEY_VOL_REPLICA_CNT "replica_count" +#define GLUSTERD_STORE_KEY_VOL_BRICK "brick" +#define GLUSTERD_STORE_KEY_VOL_VERSION "version" +#define GLUSTERD_STORE_KEY_VOL_TRANSPORT "transport-type" +#define GLUSTERD_STORE_KEY_VOL_ID "volume-id" +#define GLUSTERD_STORE_KEY_VOL_IS_RESTORED "is-volume-restored" +#define GLUSTERD_STORE_KEY_RB_STATUS "rb_status" +#define GLUSTERD_STORE_KEY_RB_SRC_BRICK "rb_src" +#define GLUSTERD_STORE_KEY_RB_DST_BRICK "rb_dst" +#define GLUSTERD_STORE_KEY_RB_DST_PORT "rb_port" +#define GLUSTERD_STORE_KEY_VOL_DEFRAG "rebalance_status" +#define GLUSTERD_STORE_KEY_DEFRAG_OP "rebalance_op" +#define GLUSTERD_STORE_KEY_USERNAME "username" +#define GLUSTERD_STORE_KEY_PASSWORD "password" +#define GLUSTERD_STORE_KEY_PARENT_VOLNAME "parent_volname" +#define GLUSTERD_STORE_KEY_VOL_OP_VERSION "op-version" #define GLUSTERD_STORE_KEY_VOL_CLIENT_OP_VERSION "client-op-version" -#define GLUSTERD_STORE_KEY_SNAP_NAME "name" -#define GLUSTERD_STORE_KEY_SNAP_ID "snap-id" -#define GLUSTERD_STORE_KEY_SNAP_CG_ID "cg-id" -#define GLUSTERD_STORE_KEY_SNAP_CG_NAME "cg-name" -#define GLUSTERD_STORE_KEY_SNAP_DESC "desc" -#define GLUSTERD_STORE_KEY_SNAP_TIMESTAMP "time-stamp" -#define GLUSTERD_STORE_KEY_SNAP_STATUS "status" -#define GLUSTERD_STORE_KEY_SNAP_COUNT "count" -#define GLUSTERD_STORE_KEY_CG_VOL_COUNT "count" -#define GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT "snap-max-hard-limit" -#define GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT "snap-max-soft-limit" - -#define GLUSTERD_STORE_KEY_BRICK_HOSTNAME "hostname" -#define GLUSTERD_STORE_KEY_BRICK_PATH "path" -#define GLUSTERD_STORE_KEY_BRICK_PORT "listen-port" -#define GLUSTERD_STORE_KEY_BRICK_RDMA_PORT "rdma.listen-port" +#define GLUSTERD_STORE_KEY_SNAP_NAME "name" +#define GLUSTERD_STORE_KEY_SNAP_ID "snap-id" +#define GLUSTERD_STORE_KEY_SNAP_CG_ID "cg-id" +#define GLUSTERD_STORE_KEY_SNAP_DESC "desc" +#define GLUSTERD_STORE_KEY_SNAP_TIMESTAMP "time-stamp" +#define GLUSTERD_STORE_KEY_SNAP_STATUS "status" +#define GLUSTERD_STORE_KEY_SNAP_COUNT "count" +#define GLUSTERD_STORE_KEY_CG_VOL_COUNT "count" +#define GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT "snap-max-hard-limit" +#define GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT "snap-max-soft-limit" + +#define GLUSTERD_STORE_KEY_BRICK_HOSTNAME "hostname" +#define GLUSTERD_STORE_KEY_BRICK_PATH "path" +#define GLUSTERD_STORE_KEY_BRICK_PORT "listen-port" +#define GLUSTERD_STORE_KEY_BRICK_RDMA_PORT "rdma.listen-port" #define GLUSTERD_STORE_KEY_BRICK_DECOMMISSIONED "decommissioned" -#define GLUSTERD_STORE_KEY_BRICK_VGNAME "vg" +#define GLUSTERD_STORE_KEY_BRICK_VGNAME "vg" -#define GLUSTERD_STORE_KEY_PEER_UUID "uuid" -#define GLUSTERD_STORE_KEY_PEER_HOSTNAME "hostname" -#define GLUSTERD_STORE_KEY_PEER_STATE "state" +#define GLUSTERD_STORE_KEY_PEER_UUID "uuid" +#define GLUSTERD_STORE_KEY_PEER_HOSTNAME "hostname" +#define GLUSTERD_STORE_KEY_PEER_STATE "state" -#define GLUSTERD_STORE_KEY_VOL_CAPS "caps" +#define GLUSTERD_STORE_KEY_VOL_CAPS "caps" #define glusterd_for_each_entry(entry, dir) \ do {\ @@ -140,6 +140,13 @@ glusterd_store_global_info (xlator_t *this); int32_t glusterd_store_retrieve_options (xlator_t *this); +int +glusterd_store_update_volinfo (glusterd_volinfo_t *volinfo, + glusterd_snap_t *snap); +int32_t +glusterd_store_retrieve_bricks (glusterd_volinfo_t *volinfo, + glusterd_volinfo_t *snap_volinfo); + int32_t glusterd_store_options (xlator_t *this, dict_t *opts); diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 6cba5b467..dedfd890f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -1542,7 +1542,7 @@ glusterd_snap_volume_start_glusterfs (glusterd_volinfo_t *volinfo, glusterd_set_socket_filepath (sock_filepath, socketpath, sizeof (socketpath)); - GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo, + GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo->volname, snap_volinfo->volname, brickinfo, priv); if (glusterd_is_service_running (pidfile, NULL)) @@ -1760,10 +1760,10 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, gf_boolean_t del_brick) { - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - char pidfile[PATH_MAX] = {0,}; - int ret = 0; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + char pidfile[PATH_MAX] = {0,}; + int ret = 0; GF_ASSERT (volinfo); GF_ASSERT (brickinfo); @@ -1816,7 +1816,7 @@ glusterd_snap_volume_stop_glusterfs (glusterd_volinfo_t *volinfo, if (GLUSTERD_STATUS_STARTED == volinfo->status) { (void) glusterd_brick_disconnect (brickinfo); - GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo, + GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, volinfo->volname, snap_volinfo->volname, brickinfo, priv); ret = glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_false); @@ -2159,6 +2159,15 @@ glusterd_add_volume_to_dict (glusterd_volinfo_t *volinfo, if (ret) goto out; + snprintf (key, sizeof (key), "volume%d.is_volume_restored", count); + ret = dict_set_int32 (dict, key, volinfo->is_volume_restored); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to set " + "is_volume_restored option for %s volume", + volinfo->volname); + goto out; + } + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "volume%d.brick_count", count); ret = dict_set_int32 (dict, key, volinfo->brick_count); @@ -5191,7 +5200,6 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, char key[1024] = {0}; char base_key[1024] = {0}; char pidfile[PATH_MAX] = {0}; - char exp_path[PATH_MAX] = {0}; xlator_t *this = NULL; glusterd_conf_t *priv = NULL; @@ -5226,11 +5234,10 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, if (volinfo->is_snap_volume == _gf_true) { /* Fetching the snap pidfile using parent volname */ - GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); - snprintf (pidfile, sizeof(pidfile) - 1, - "%s/vols/%s/snaps/%s/run/%s-%s.pid", priv->workdir, - volinfo->parent_volname, volinfo->volname, - brickinfo->hostname, exp_path); + GLUSTERD_GET_SNAP_BRICK_PIDFILE (pidfile, + volinfo->parent_volname, + volinfo->volname, + brickinfo, priv); } else GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, brickinfo, priv); diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 1bc0db6ce..3b8e7648c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -28,6 +28,8 @@ #include "logging.h" #include "dict.h" #include "graph-utils.h" +#include "glusterd-store.h" +#include "glusterd-hooks.h" #include "trie.h" #include "glusterd-mem-types.h" #include "cli1-xdr.h" @@ -3175,7 +3177,8 @@ glusterd_generate_brick_volfile (glusterd_volinfo_t *volinfo, static int glusterd_generate_snap_brick_volfile (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, - glusterd_volinfo_t *snap_volinfo) + glusterd_volinfo_t *snap_volinfo, + gf_boolean_t vol_restore) { volgen_graph_t graph = {0,}; char filename[PATH_MAX] = {0,}; @@ -3189,7 +3192,16 @@ glusterd_generate_snap_brick_volfile (glusterd_volinfo_t *volinfo, GF_ASSERT (brickinfo); GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, brick); - GLUSTERD_GET_SNAP_DIR (path, volinfo, snap_volinfo->volname, priv); + /* If the brick volfile is generated as part of a restore + * operation then we should be generating the brick volfile + * in the origin volume folder instead of snap volume folder. + */ + if (vol_restore) { + GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); + } else { + GLUSTERD_GET_SNAP_DIR (path, volinfo, + snap_volinfo->volname, priv); + } snprintf (filename, PATH_MAX, "%s/%s.%s.%s.vol", path, snap_volinfo->volname, @@ -3285,8 +3297,10 @@ generate_snap_brick_volfiles (glusterd_volinfo_t *volinfo, "Found a brick - %s:%s", brickinfo->hostname, brickinfo->path); - ret = glusterd_generate_snap_brick_volfile (volinfo, brickinfo, - snap_volinfo); + ret = glusterd_generate_snap_brick_volfile (volinfo, + brickinfo, + snap_volinfo, + _gf_false); if (ret) goto out; } @@ -3382,7 +3396,8 @@ out: int generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo, glusterd_volinfo_t *snap_volinfo, - glusterd_client_type_t client_type) + glusterd_client_type_t client_type, + gf_boolean_t vol_restore) { char filepath[PATH_MAX] = {0,}; int ret = -1; @@ -3416,6 +3431,18 @@ generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo, dict = dict_new (); if (!dict) goto out; + + /* If the brick volfile is generated as part of a restore + * operation then we should be generating the brick volfile + * in the origin volume folder instead of snap volume folder. + */ + if (vol_restore) { + GLUSTERD_GET_VOLUME_DIR (path, actual_volinfo, conf); + } else { + GLUSTERD_GET_SNAP_DIR (path, actual_volinfo, + snap_volinfo->volname, conf); + } + for (i = 0; types[i]; i++) { memset (filepath, 0, sizeof (filepath)); ret = dict_set_str (dict, "client-transport-type", types[i]); @@ -3427,8 +3454,6 @@ generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo, if (ret) goto out; - GLUSTERD_GET_SNAP_DIR (path, actual_volinfo, - snap_volinfo->volname,conf); if (client_type == GF_CLIENT_TRUSTED) { if ((actual_volinfo->transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) && @@ -4115,3 +4140,478 @@ gd_is_boolean_option (char *key) return _gf_false; } + +/* This is a utility function which will create backup of + * origin volume file and then replace the origin volume + * file with a sym-link to snap volume file. + * + * @param orig_vol volinfo of origin volume + * @param orig_file file belonging to origin volume + * @param snap_file corresponding file in snap volume + * + * @return 0 on success and negative value on failure. + */ +static int +gd_backup_and_restore_snap_files (glusterd_volinfo_t *orig_vol, + const char *orig_file, + const char *snap_file) +{ + int ret = -1; + char tmppath[PATH_MAX] = {0,}; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + GF_ASSERT (orig_vol); + GF_ASSERT (orig_file); + GF_ASSERT (snap_file); + + /* If the volume is already a restored volume then we + * need not create a backup of files belonging to origin + * volume. + * We can simply delete the sym-link created by previous + * restore. + */ + if (orig_vol->is_volume_restored) { + ret = remove (orig_file); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + "remove %s file", orig_file); + goto out; + } + } else { + snprintf (tmppath, sizeof (tmppath), "%s.origin", + orig_file); + /* TODO: These temp files need to be deleted once the restored + * operation is successful + */ + + /* Create backup of origin volume file */ + ret = rename (orig_file, tmppath); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to rename " + "file from %s to %s", orig_file, tmppath); + goto out; + } + } + + /* Create sym-link to snap file */ + ret = symlink (snap_file, orig_file); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to create sym-link " + "to %s file", snap_file); + goto out; + } + + ret = 0; +out: + + return ret; +} + +/* This is a utility function which will create a backup copy + * of origin volume. + * + * @param origvol volinfo of origin volume + * @param fileformat This string provides formatting information + * for the file to be backed up. The format + * string should be of %s format. + * Where can be any string and this + * function will replace %s with origin volume + * name. e.g. "trusted-%s-fuse.vol". + * @param volpath volume path + * + * @return 0 on success and negative value on failure. + */ +static inline int +gd_format_path_and_backup_snap_files (glusterd_volinfo_t *origvol, + const char *fileformat, + const char *volpath) +{ + int ret = -1; + char origfile[PATH_MAX] = {0,}; + char formatstr[PATH_MAX] = {0,}; + char tmppath[PATH_MAX] = {0,}; + + snprintf (formatstr, sizeof (formatstr), "%s/%s", volpath, fileformat); + snprintf (origfile, sizeof (origfile), formatstr, origvol->volname); + + /* If the volume is already a restored volume then we + * need not create a backup of files belonging to origin + * volume. + * We can simply delete the sym-link created by previous + * restore. + */ + if (origvol->is_volume_restored) { + ret = remove (origfile); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to " + "remove %s file", origfile); + } + goto out; + } + + snprintf (tmppath, sizeof (tmppath), "%s.origin", origfile); + + /* Create a backup of this file */ + ret = rename (origfile, tmppath); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "failed to restore %s file", + origfile); + } + +out: + return ret; +} + +/* This is a utility function which will backup the origin volume + * brick folder and then create sym link to the snap_vol brick + * folder. + * + * @param orig_vol volinfo of origin volume + * @param snap_vol volinfo of snap volume + * + * @return 0 on success and negative value on failure. + */ +static int +gd_restore_snap_brick_vol_files (glusterd_volinfo_t *orig_vol, + glusterd_volinfo_t *snap_vol) +{ + int ret = -1; + char path[PATH_MAX] = {0,}; + char brick[PATH_MAX] = {0,}; + char oldfilename[PATH_MAX] = {0,}; + char newfilename[PATH_MAX] = {0,}; + glusterd_brickinfo_t *brickinfo = NULL; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + + this = THIS; + GF_ASSERT (this); + conf = this->private; + GF_ASSERT (conf); + + GLUSTERD_GET_VOLUME_DIR (path, orig_vol, conf); + + /* brick count of origin volume and snapshot volume might be + * different. Therefore we need to run two different loop to + * restore snap brick vol files. + */ + list_for_each_entry (brickinfo, &orig_vol->bricks, brick_list) { + GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, brick); + + snprintf (oldfilename, sizeof (oldfilename), "%s/%s.%s.%s.vol", + path, orig_vol->volname, brickinfo->hostname, + brick); + + /* If the volume is already a restored volume then we + * need not create a backup of files belonging to origin + * volume. + * We can simply delete the sym-link created by previous + * restore. + */ + if (orig_vol->is_volume_restored) { + ret = remove (oldfilename); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + "remove %s file", oldfilename); + goto out; + } + continue; + } + + snprintf (newfilename, sizeof (newfilename), "%s.origin", + oldfilename); + + /* Create a backup of origin volume file */ + ret = rename (oldfilename, newfilename); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to rename " + "file from %s to %s", oldfilename, + newfilename); + goto out; + } + } + + /* Recreate brick files for origin volume */ + list_for_each_entry (brickinfo, &snap_vol->bricks, brick_list) { + ret = glusterd_generate_snap_brick_volfile (orig_vol, + brickinfo, + snap_vol, + _gf_true); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to generate " + "brick volfile"); + goto out; + } + } + + ret = 0; +out: + return ret; +} + + +/* This function will update the in-memory representation + * of the origin volume with the snap volume details. + * + * @param orig_vol origin volume volinfo + * @param snap_vol snap volume volinfo + * + * @return 0 on success and negative value on failure. + */ +static int +gd_update_origin_volume (glusterd_volinfo_t *orig_vol, + glusterd_volinfo_t *snap_vol) +{ + int ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + + this = THIS; + GF_ASSERT (this); + conf = this->private; + GF_ASSERT (conf); + GF_ASSERT (orig_vol); + GF_ASSERT (snap_vol); + + /* Update the in-memory volinfo from the store */ + ret = glusterd_store_update_volinfo (orig_vol, NULL); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to update " + "volinfo for %s volume", orig_vol->volname); + goto out; + } + + /* Reset the port number to 0 */ + orig_vol->port = 0; + /* Reset the volume status to stopped */ + glusterd_set_volume_status (orig_vol, GLUSTERD_STATUS_STOPPED); + + /* Stop the snap volume */ + list_for_each_entry (brickinfo, &snap_vol->bricks, brick_list) { + ret = glusterd_snap_brick_stop (orig_vol, snap_vol, + brickinfo, _gf_false); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to stop " + " %s brick", brickinfo->path); + goto out; + } + } + + /* Set the volume status to stopped for the snap volume */ + glusterd_set_volume_status (snap_vol, GLUSTERD_STATUS_STOPPED); + + /* The in-memory brick list for the origin volume should be + * replaced with the brick list of snap volume. Therefore + * first delete all the bricks from the origin volume and + * then read the brick list from the store which is already + * updated + */ + + /* Delete previous brick infos */ + ret = glusterd_volume_brickinfos_delete (orig_vol); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to delete " + "brickinfos for %s volume", orig_vol->volname); + goto out; + } + + /* Retrieve brick list */ + ret = glusterd_store_retrieve_bricks (orig_vol, NULL); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to retrieve " + "bricks info from store for %s volume", + orig_vol->volname); + goto out; + } + +out: + return ret; +} + +/* This function will restore origin volume to it it's snap. + * The restore operation will simply replace the Gluster origin + * volume with the snap volume. + * + * @param orig_vol volinfo of origin volume + * @param snap_vol volinfo of snapshot volume + * + * @return 0 on success and negative value on error + */ +int +gd_restore_snap_volume (glusterd_volinfo_t *orig_vol, + glusterd_volinfo_t *snap_vol) +{ + int ret = -1; + unsigned int i = 0; + char snappath[PATH_MAX] = {0,}; + char volpath[PATH_MAX] = {0,}; + char oldfilename[PATH_MAX] = {0,}; + char newfilename[PATH_MAX] = {0,}; + char *types[] = {NULL, NULL, NULL}; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + gf_transport_type type = GF_TRANSPORT_TCP; + char tmpname[GLUSTERD_MAX_VOLUME_NAME] = {0,}; + + this = THIS; + GF_ASSERT (this); + conf = this->private; + GF_ASSERT (conf); + + GF_VALIDATE_OR_GOTO (this->name, orig_vol, out); + GF_VALIDATE_OR_GOTO (this->name, snap_vol, out); + + GLUSTERD_GET_SNAP_DIR (snappath, orig_vol, snap_vol->volname, conf); + GLUSTERD_GET_VOLUME_DIR (volpath, orig_vol, conf); + + /* As mentioned earlier the snapshot restore is done by replacing + * the origin volume with the snapshot volume. To do so we have to + * replace all backend files belonging to origin volume with the + * snapshot volume. And once all the backend files are updated + * update the in-memory structure of the origin volume. Also delete + * the snapshot volume. + * TODO: deleting of snapshot volume can be controlled by user + * controllable option. + */ + + /* Backup and restore info file */ + ret = gd_backup_and_restore_snap_files (orig_vol, + orig_vol->shandle->path, + snap_vol->shandle->path); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to restore info " + "file for %s volume", orig_vol->volname); + goto out; + } + + GLUSTERD_GET_BRICK_DIR (oldfilename, orig_vol, conf); + GLUSTERD_GET_SNAP_BRICK_DIR (newfilename, orig_vol, + snap_vol->volname, conf); + + /* Backup and restore bricks folder and it's contents */ + ret = gd_backup_and_restore_snap_files (orig_vol, oldfilename, + newfilename); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to restore bricks " + "folder for %s volume", orig_vol->volname); + goto out; + } + + enumerate_transport_reqs (orig_vol->transport_type, types); + + + for (i = 0; NULL != types[i]; i++) { + type = transport_str_to_type (types[i]); + + if ((orig_vol->transport_type == GF_TRANSPORT_BOTH_TCP_RDMA) && + type == GF_TRANSPORT_RDMA) { + /* Backup trusted rdma-fuse.vol file */ + ret = gd_format_path_and_backup_snap_files (orig_vol, + "trusted-%s.rdma-fuse.vol", + volpath); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + " backup trusted*.rdma-fuse.vol file"); + goto out; + } + + /* Backup rdma-fuse.vol file */ + ret = gd_format_path_and_backup_snap_files (orig_vol, + "%s.rdma-fuse.vol", volpath); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + " backup rdma-fuse.vol file"); + goto out; + } + } else { + /* Backup trusted fuse.vol file */ + ret = gd_format_path_and_backup_snap_files (orig_vol, + "trusted-%s-fuse.vol", volpath); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + " backup trusted*-fuse.vol file"); + goto out; + } + + /* Backup fuse.vol file */ + ret = gd_format_path_and_backup_snap_files (orig_vol, + "%s-fuse.vol", volpath); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to " + " backup fuse.vol file"); + goto out; + } + } + } + + /* The restored client and brick vol files should have all + * the entries present in snap vol files but the volume name + * for all these entries should still be the origin volume + * name. + * As of now these volfile generation takes volume name + * directly from the volinfo. Therefore instead of changing + * all the generate function simply replace the snap volume + * name with the origin volume name. And once the vol files + * are generated restore the volume name. + */ + strncpy (tmpname, snap_vol->volname, sizeof(tmpname)); + strncpy (snap_vol->volname, orig_vol->volname, + sizeof(snap_vol->volname)); + + /* Generate trusted client vol file */ + ret = generate_snap_client_volfiles (orig_vol, snap_vol, + GF_CLIENT_TRUSTED, _gf_true); + if (ret) { + /* Restore the snap volume name */ + strncpy (snap_vol->volname, tmpname, sizeof(snap_vol->volname)); + gf_log (this->name, GF_LOG_ERROR, "Failed to generated " + " trusted client vol file for %s volume", + orig_vol->volname); + goto out; + } + + ret = generate_snap_client_volfiles (orig_vol, snap_vol, + GF_CLIENT_OTHER, _gf_true); + if (ret) { + /* Restore the snap volume name */ + strncpy (snap_vol->volname, tmpname, sizeof(snap_vol->volname)); + gf_log (this->name, GF_LOG_ERROR, "Failed to generated " + " client vol file for %s volume", orig_vol->volname); + goto out; + } + + ret = gd_restore_snap_brick_vol_files (orig_vol, snap_vol); + if (ret) { + /* Restore the snap volume name */ + strncpy (snap_vol->volname, tmpname, sizeof(snap_vol->volname)); + gf_log (this->name, GF_LOG_ERROR, "Failed to generated " + " brick vol files for %s volume", orig_vol->volname); + goto out; + } + + /* Restore the snap volume name */ + strncpy (snap_vol->volname, tmpname, sizeof(snap_vol->volname)); + + /* Update the in-memory structure of origin volume */ + ret = gd_update_origin_volume (orig_vol, snap_vol); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to update " + "origin volume %s", orig_vol->volname); + goto out; + } + + /* Update status to restored */ + orig_vol->is_volume_restored = _gf_true; + + ret = glusterd_store_volinfo (orig_vol, GLUSTERD_VOLINFO_VER_AC_NONE); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to store volume " + "info of %s volume", orig_vol->volname); + goto out; + } +out: + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h index 2b22f5226..f5163b477 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.h +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h @@ -148,7 +148,8 @@ int generate_client_volfiles (glusterd_volinfo_t *volinfo, int generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo, glusterd_volinfo_t *snap_volinfo, - glusterd_client_type_t client_type); + glusterd_client_type_t client_type, + gf_boolean_t vol_restore); int glusterd_get_volopt_content (dict_t *dict, gf_boolean_t xml_out); char* glusterd_get_trans_type_rb (gf_transport_type ttype); @@ -169,4 +170,6 @@ gd_is_xlator_option (char *key); gf_boolean_t gd_is_boolean_option (char *key); +int gd_restore_snap_volume (glusterd_volinfo_t *orig_vol, + glusterd_volinfo_t *snap_vol); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index f14b6737b..40ae611fa 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -278,6 +278,7 @@ struct glusterd_volinfo_ { gf_lock_t lock; char volname[GLUSTERD_MAX_VOLUME_NAME]; gf_boolean_t is_snap_volume; + gf_boolean_t is_volume_restored; char parent_volname[GLUSTERD_MAX_VOLUME_NAME]; /* In case of a snap volume i.e (is_snap_volume == TRUE) this @@ -485,14 +486,15 @@ typedef ssize_t (*gd_serialize_t) (struct iovec outmsg, void *args); volpath, brickinfo->hostname, exp_path); \ } while (0) -#define GLUSTERD_GET_SNAP_BRICK_PIDFILE(pidfile,volinfo,snapname,brickinfo, \ - priv) do { \ - char exp_path[PATH_MAX] = {0,}; \ - char volpath[PATH_MAX] = {0,}; \ - GLUSTERD_GET_SNAP_DIR(volpath, volinfo, snapname, priv); \ - GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); \ - snprintf (pidfile, PATH_MAX, "%s/run/%s-%s.pid", \ - volpath, brickinfo->hostname, exp_path); \ +#define GLUSTERD_GET_SNAP_BRICK_PIDFILE(pidfile,vol_name,snap_name, \ + brickinfo, priv) do { \ + char exp_path[PATH_MAX] = {0,}; \ + char volpath[PATH_MAX] = {0,}; \ + snprintf (volpath, sizeof (volpath), "%s/vols/%s/snaps/%s", \ + priv->workdir, vol_name, snap_name); \ + GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path);\ + snprintf (pidfile, sizeof (pidfile), "%s/run/%s-%s.pid", \ + volpath, brickinfo->hostname, exp_path); \ } while (0) #define GLUSTERD_GET_NFS_PIDFILE(pidfile,nfspath) { \ -- cgit