summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd/src/glusterd-volgen.c
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 /xlators/mgmt/glusterd/src/glusterd-volgen.c
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>
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-volgen.c')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c479
1 files changed, 60 insertions, 419 deletions
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 <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;
}