From 8f87071658ae8d0799f752a9f7f951fbd46ceda7 Mon Sep 17 00:00:00 2001 From: Rajesh Joseph Date: Wed, 5 Mar 2014 18:26:37 +0530 Subject: glusterd/snapshot: Modified restore backend Now instead of creating volume store files first we constructing the in-memory volinfo first and then generate the backend store files. This gives lot of flexibility in restore operation. This patch also fixes the read-only issue with restored snaps. Change-Id: I51032228a5212fc3b90dc6e93f3539af3eb36074 BUG: 1064688 Signed-off-by: Rajesh Joseph Reviewed-on: http://review.gluster.org/7209 Reviewed-by: Sachin Pandit Reviewed-by: Vijaikumar Mallikarjuna --- xlators/mgmt/glusterd/src/glusterd-snapshot.c | 38 +- xlators/mgmt/glusterd/src/glusterd-utils.c | 169 +++++++-- xlators/mgmt/glusterd/src/glusterd-utils.h | 9 +- xlators/mgmt/glusterd/src/glusterd-volgen.c | 479 +++--------------------- xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 59 ++- xlators/mgmt/glusterd/src/glusterd.h | 5 + 6 files changed, 282 insertions(+), 477 deletions(-) (limited to 'xlators/mgmt') diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index 7960e84ac..2b2cc1adc 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -1191,6 +1191,7 @@ out: int32_t glusterd_snap_volume_remove (glusterd_volinfo_t *snap_vol, + gf_boolean_t remove_lvm, gf_boolean_t force) { int ret = -1; @@ -1223,13 +1224,17 @@ glusterd_snap_volume_remove (glusterd_volinfo_t *snap_vol, goto out; } } - ret = glusterd_lvm_snapshot_remove (snap_vol); - if (ret) { - gf_log(this->name, GF_LOG_WARNING, "Failed to remove " - "lvm snapshot volume %s", snap_vol->volname); - ret_1 = ret; - if (!force) - goto out; + + /* Only remove the backend lvm when required */ + if (remove_lvm) { + ret = glusterd_lvm_snapshot_remove (snap_vol); + if (ret) { + gf_log(this->name, GF_LOG_WARNING, "Failed to remove " + "lvm snapshot volume %s", snap_vol->volname); + ret_1 = ret; + if (!force) + goto out; + } } ret = glusterd_store_delete_volume (snap_vol); @@ -1291,6 +1296,7 @@ glusterd_snapobject_delete (glusterd_snap_t *snap) int32_t glusterd_snap_remove (glusterd_snap_t *snap, + gf_boolean_t remove_lvm, gf_boolean_t force) { int ret = -1; @@ -1308,7 +1314,8 @@ glusterd_snap_remove (glusterd_snap_t *snap, } list_for_each_entry_safe (snap_vol, tmp, &snap->volumes, vol_list) { - ret = glusterd_snap_volume_remove (snap_vol, force); + ret = glusterd_snap_volume_remove (snap_vol, + remove_lvm, force); if (ret) { gf_log(this->name, GF_LOG_WARNING, "Failed to remove " "volinfo %s for snap %s", snap_vol->volname, @@ -2538,7 +2545,7 @@ glusterd_create_snap_object (dict_t *dict) out: if (ret) { if (snap) - glusterd_snap_remove (snap, _gf_true); + glusterd_snap_remove (snap, _gf_true,_gf_true); snap=NULL; } @@ -2906,7 +2913,11 @@ glusterd_do_snap_vol (glusterd_volinfo_t *origin_vol, glusterd_snap_t *snap, goto out; } - ret = glusterd_volinfo_dup (origin_vol, &snap_vol); + /* We are not setting the username and password here as + * we need to set the user name and password passed in + * the dictionary + */ + ret = glusterd_volinfo_dup (origin_vol, &snap_vol, _gf_false); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to duplicate volinfo " "for the snapshot %s", snap->snapname); @@ -3056,7 +3067,8 @@ glusterd_do_snap_vol (glusterd_volinfo_t *origin_vol, glusterd_snap_t *snap, out: if (ret) { if (snap_vol) - glusterd_snap_volume_remove (snap_vol, _gf_true); + glusterd_snap_volume_remove (snap_vol, + _gf_true, _gf_true); snap_vol = NULL; } @@ -3252,7 +3264,7 @@ glusterd_snapshot_remove_commit (dict_t *dict, char **op_errstr, goto out; } - ret = glusterd_snap_remove (snap, _gf_false); + ret = glusterd_snap_remove (snap, _gf_true, _gf_false); if (ret){ gf_log (this->name, GF_LOG_ERROR, "Failed to remove snap %s", snapname); @@ -3369,7 +3381,7 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, out: if (ret) { if (snap) - glusterd_snap_remove (snap, _gf_true); + glusterd_snap_remove (snap, _gf_true, _gf_true); snap=NULL; } diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 7b4e454cb..90becf346 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -477,20 +477,28 @@ out: return ret; } +/* This function will create a new volinfo and then + * dup the entries from volinfo to the new_volinfo. + * + * @param volinfo volinfo which will be duplicated + * @param dup_volinfo new volinfo which will be created + * @param set_userauth if this true then auth info is also set + * + * @return 0 on success else -1 + */ int32_t glusterd_volinfo_dup (glusterd_volinfo_t *volinfo, - glusterd_volinfo_t **dup_volinfo) + glusterd_volinfo_t **dup_volinfo, + gf_boolean_t set_userauth) { - int32_t ret = -1; - glusterd_volinfo_t *new_volinfo = NULL; - xlator_t *this = NULL; - uuid_t username_id = {0, }; - uuid_t password_id = {0, }; - char *username = NULL; - char *password = NULL; + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_volinfo_t *new_volinfo = NULL; this = THIS; GF_ASSERT (this); + GF_VALIDATE_OR_GOTO (this->name, volinfo, out); + GF_VALIDATE_OR_GOTO (this->name, dup_volinfo, out); ret = glusterd_volinfo_new (&new_volinfo); if (ret) { @@ -512,34 +520,134 @@ glusterd_volinfo_dup (glusterd_volinfo_t *volinfo, dict_copy (volinfo->dict, new_volinfo->dict); gd_update_volume_op_versions (new_volinfo); - /* For now, actual volume's username and password itself is used - for authentication of trusted clients. If its not working, - generate new username and passowd (uuid-generate) and use. - */ - uuid_generate (username_id); - username = uuid_utoa (username_id); - if (!username) { - ret = -1; - gf_log (this->name, GF_LOG_WARNING, "could not get the " - "username"); - goto out; + if (set_userauth) { + glusterd_auth_set_username (new_volinfo, + volinfo->auth.username); + glusterd_auth_set_password (new_volinfo, + volinfo->auth.password); } - uuid_generate (password_id); - password = uuid_utoa (password_id); - if (!password) { - ret = -1; - gf_log (this->name, GF_LOG_WARNING, "could not get the " - "password"); + + *dup_volinfo = new_volinfo; + ret = 0; +out: + if (ret && (NULL != new_volinfo)) { + (void) glusterd_volinfo_delete (new_volinfo); + } + return ret; +} + +/* This function will duplicate brickinfo + * + * @param brickinfo Source brickinfo + * @param dup_brickinfo Destination brickinfo + * + * @return 0 on success else -1 + */ +int +glusterd_brickinfo_dup (glusterd_brickinfo_t *brickinfo, + glusterd_brickinfo_t *dup_brickinfo) +{ + int ret = -1; + + GF_ASSERT (brickinfo); + GF_ASSERT (dup_brickinfo); + + strcpy (dup_brickinfo->hostname, brickinfo->hostname); + strcpy (dup_brickinfo->path, brickinfo->path); + ret = gf_canonicalize_path (dup_brickinfo->path); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to canonicalize " + "brick path"); goto out; } - glusterd_auth_set_username (new_volinfo, username); - glusterd_auth_set_password (new_volinfo, password); + uuid_copy (dup_brickinfo->uuid, brickinfo->uuid); - *dup_volinfo = new_volinfo; + dup_brickinfo->port = brickinfo->port; + dup_brickinfo->rdma_port = brickinfo->rdma_port; + if (NULL != brickinfo->logfile) { + dup_brickinfo->logfile = gf_strdup (brickinfo->logfile); + if (NULL == dup_brickinfo->logfile) { + ret = -1; + goto out; + } + } + dup_brickinfo->status = brickinfo->status; out: - if (ret) - GF_FREE (new_volinfo); + return ret; +} + +/* This function will copy snap volinfo to the new + * passed volinfo and regenerate backend store files + * for the restored snap. + * + * @param new_volinfo new volinfo + * @param snap_volinfo volinfo of snap volume + * + * @return 0 on success and -1 on failure + * + * TODO: Duplicate all members of volinfo, e.g. geo-rep sync slaves + */ +int32_t +glusterd_snap_volinfo_restore (glusterd_volinfo_t *new_volinfo, + glusterd_volinfo_t *snap_volinfo) +{ + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_brickinfo_t *new_brickinfo = NULL; + + this = THIS; + GF_ASSERT (this); + + GF_VALIDATE_OR_GOTO (this->name, new_volinfo, out); + GF_VALIDATE_OR_GOTO (this->name, snap_volinfo, out); + + list_for_each_entry (brickinfo, &snap_volinfo->bricks, brick_list) { + ret = glusterd_brickinfo_new (&new_brickinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to create " + "new brickinfo"); + goto out; + } + + /* Duplicate brickinfo */ + ret = glusterd_brickinfo_dup (brickinfo, new_brickinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to dup " + "brickinfo"); + goto out; + } + + /* We need to replace the volume id of all the bricks + * to the volume id of the origin volume. new_volinfo + * has the origin volume's volume id*/ + ret = sys_lsetxattr (new_brickinfo->path, + GF_XATTR_VOL_ID_KEY, + new_volinfo->volume_id, + sizeof (new_volinfo->volume_id), + XATTR_REPLACE); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to set " + "extended attribute %s on %s. Reason: " + "%s, snap: %s", GF_XATTR_VOL_ID_KEY, + new_brickinfo->path, strerror (errno), + new_volinfo->volname); + goto out; + } + + list_add_tail (&new_brickinfo->brick_list, &new_volinfo->bricks); + /* ownership of new_brickinfo is passed to new_volinfo */ + new_brickinfo = NULL; + } + + /* Regenerate all volfiles */ + ret = glusterd_create_volfiles_and_notify_services (new_volinfo); + +out: + if (ret && (NULL != new_brickinfo)) { + (void) glusterd_brickinfo_delete (new_brickinfo); + } return ret; } @@ -657,7 +765,6 @@ out: return ret; } - int32_t glusterd_brickinfo_new (glusterd_brickinfo_t **brickinfo) { diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 1ef5685eb..e3e275095 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -83,7 +83,8 @@ glusterd_volinfo_new (glusterd_volinfo_t **volinfo); int32_t glusterd_volinfo_dup (glusterd_volinfo_t *volinfo, - glusterd_volinfo_t **dup_volinfo); + glusterd_volinfo_t **dup_volinfo, + gf_boolean_t set_userauth); char * glusterd_auth_get_username (glusterd_volinfo_t *volinfo); @@ -604,4 +605,10 @@ glusterd_get_brick_root (char *path, char **mount_point); int glusterd_compare_snap_time(struct list_head *, struct list_head *); + +int32_t +glusterd_snap_volinfo_restore (glusterd_volinfo_t *new_volinfo, + glusterd_volinfo_t *snap_volinfo); +int32_t +glusterd_lvm_snapshot_remove (glusterd_volinfo_t *snap_vol); #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 90886dcf3..24a70eb41 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -4107,298 +4107,11 @@ 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_brick_stop (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); - 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. + * TODO: Multi-volume delete to be done. + * Cleanup in case of restore failure is pending. * * @param orig_vol volinfo of origin volume * @param snap_vol volinfo of snapshot volume @@ -4409,17 +4122,11 @@ 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,}; + int ret = -1; + glusterd_volinfo_t *new_volinfo = NULL; + glusterd_snap_t *snap = NULL; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; this = THIS; GF_ASSERT (this); @@ -4428,154 +4135,88 @@ gd_restore_snap_volume (glusterd_volinfo_t *orig_vol, GF_VALIDATE_OR_GOTO (this->name, orig_vol, out); GF_VALIDATE_OR_GOTO (this->name, snap_vol, out); + snap = snap_vol->snapshot; + GF_VALIDATE_OR_GOTO (this->name, snap, out); - GLUSTERD_GET_VOLUME_DIR (snappath, snap_vol, 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. + /* Snap volume must be stoped before performing the + * restore operation. */ - - /* Backup and restore info file */ - ret = gd_backup_and_restore_snap_files (orig_vol, - orig_vol->shandle->path, - snap_vol->shandle->path); + ret = glusterd_stop_volume (snap_vol); if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to restore info " - "file for %s volume", orig_vol->volname); + gf_log (this->name, GF_LOG_ERROR, "Failed to stop " + "snap volume"); goto out; } - GLUSTERD_GET_BRICK_DIR (oldfilename, orig_vol, conf); - GLUSTERD_GET_BRICK_DIR (newfilename, snap_vol, conf); - - /* Backup and restore bricks folder and it's contents */ - ret = gd_backup_and_restore_snap_files (orig_vol, oldfilename, - newfilename); + /* Create a new volinfo for the restored volume */ + ret = glusterd_volinfo_dup (snap_vol, &new_volinfo, _gf_true); if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to restore bricks " - "folder for %s volume", orig_vol->volname); + gf_log (this->name, GF_LOG_ERROR, "Failed to create volinfo"); goto out; } - enumerate_transport_reqs (orig_vol->transport_type, types); - + /* Following entries need to be derived from origin volume. */ + strcpy (new_volinfo->volname, orig_vol->volname); + uuid_copy (new_volinfo->volume_id, orig_vol->volume_id); + new_volinfo->snap_count = orig_vol->snap_count; + new_volinfo->snap_max_hard_limit = orig_vol->snap_max_hard_limit; + new_volinfo->is_volume_restored = _gf_true; - 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; - } + /* Copy the snap vol info to the new_volinfo.*/ + ret = glusterd_snap_volinfo_restore (new_volinfo, snap_vol); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to restore snap"); + (void)glusterd_volinfo_delete (new_volinfo); + 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; - } + /* If the orig_vol is already restored then we should delete + * the backend LVMs */ + if (orig_vol->is_volume_restored) { + ret = glusterd_lvm_snapshot_remove (orig_vol); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to remove " + "LVM backend"); + (void)glusterd_volinfo_delete (new_volinfo); + 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. + /* Once the new_volinfo is completely constructed then delete + * the orinal volinfo */ - 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); + ret = glusterd_volinfo_delete (orig_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 " - " trusted client vol file for %s volume", - orig_vol->volname); + gf_log (this->name, GF_LOG_ERROR, "Failed to delete volinfo"); + (void)glusterd_volinfo_delete (new_volinfo); 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; - } + /* New volinfo always shows the status as created. Therefore + * set the status to stop. */ + glusterd_set_volume_status (new_volinfo, GLUSTERD_STATUS_STOPPED); + + list_add_tail (&new_volinfo->vol_list, &conf->volumes); - ret = gd_restore_snap_brick_vol_files (orig_vol, snap_vol); + /* Now delete the snap entry. As a first step delete the snap + * volume information stored in store. */ + ret = glusterd_snap_remove (snap, _gf_false, _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 " - " brick vol files for %s volume", orig_vol->volname); + gf_log (this->name, GF_LOG_WARNING, "Failed to delete " + "snap %s", snap->snapname); 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); + ret = glusterd_store_volinfo (new_volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); if (ret) { - gf_log (this->name, GF_LOG_ERROR, "Failed to update " - "origin volume %s", orig_vol->volname); + gf_log (this->name, GF_LOG_ERROR, "Failed to store volinfo"); 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; - } + ret = 0; out: - return ret; + + return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index bbe0c8d96..0d9fa5617 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -1717,6 +1717,47 @@ out: return ret; } +int +glusterd_stop_volume (glusterd_volinfo_t *volinfo) +{ + int ret = -1; + glusterd_brickinfo_t *brickinfo = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + GF_VALIDATE_OR_GOTO (this->name, volinfo, out); + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + ret = glusterd_brick_stop (volinfo, brickinfo, _gf_false); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to stop " + "brick (%s)", brickinfo->path); + goto out; + } + } + + glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STOPPED); + + ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to store volinfo of " + "%s volume", volinfo->volname); + goto out; + } + + ret = glusterd_nodesvcs_handle_graph_change (volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to notify graph " + "change for %s volume", volinfo->volname); + goto out; + } + +out: + return ret; +} + int glusterd_op_stop_volume (dict_t *dict) @@ -1725,7 +1766,6 @@ glusterd_op_stop_volume (dict_t *dict) int flags = 0; char *volname = NULL; glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; xlator_t *this = NULL; this = THIS; @@ -1742,19 +1782,12 @@ glusterd_op_stop_volume (dict_t *dict) goto out; } - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - ret = glusterd_brick_stop (volinfo, brickinfo, _gf_false); - if (ret) - goto out; - } - - glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STOPPED); - - ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - if (ret) + ret = glusterd_stop_volume (volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to stop %s volume", + volname); goto out; - - ret = glusterd_nodesvcs_handle_graph_change (volinfo); + } out: return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 296b2196d..b70709d51 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -884,6 +884,8 @@ int glusterd_op_statedump_volume_args_get (dict_t *dict, char **volname, int glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, char **master, char **slave, char **host_uuid); +int glusterd_stop_volume (glusterd_volinfo_t *volinfo); + /* Synctask part */ int32_t glusterd_op_begin_synctask (rpcsvc_request_t *req, glusterd_op_t op, void *dict); @@ -945,4 +947,7 @@ int glusterd_snapshot (dict_t *dict, char **op_errstr, dict_t *rsp_dict); char * glusterd_build_snap_device_path (char *device, char *snapname); +int32_t +glusterd_snap_remove (glusterd_snap_t *snap, gf_boolean_t remove_lvm, + gf_boolean_t force); #endif -- cgit