summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Joseph <rjoseph@redhat.com>2014-03-05 18:26:37 +0530
committerRajesh Joseph <rjoseph@redhat.com>2014-03-10 05:24:09 -0700
commit8f87071658ae8d0799f752a9f7f951fbd46ceda7 (patch)
tree33bf64697b10cb3ea71780ba45a913e2358a87be
parent586e1cabf850211b9e6856fcb8c42c696de6d484 (diff)
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 <rjoseph@redhat.com> Reviewed-on: http://review.gluster.org/7209 Reviewed-by: Sachin Pandit <spandit@redhat.com> Reviewed-by: Vijaikumar Mallikarjuna <vmallika@redhat.com>
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c38
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c169
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h9
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c479
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-ops.c59
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h5
6 files changed, 282 insertions, 477 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
index 7960e84..2b2cc1a 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 7b4e454..90becf3 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 1ef5685..e3e2750 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 90886dc..24a70eb 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 <string>%s<string> format.
- * Where <string> 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 bbe0c8d..0d9fa56 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 296b219..b70709d 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