diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-snapshot.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 565 |
1 files changed, 379 insertions, 186 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index d11abee70..0e824a022 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -18,6 +18,14 @@ #include <sys/resource.h> #include <sys/statvfs.h> #include <sys/mount.h> +#include <signal.h> + + +#if !defined(__NetBSD__) && !defined(GF_DARWIN_HOST_OS) +#include <mntent.h> +#else +#include "mntent_compat.h" +#endif #include "globals.h" #include "compat.h" @@ -40,16 +48,70 @@ #include "cli1-xdr.h" #include "xdr-generic.h" -#ifdef GF_LINUX_HOST_OS -#include <mntent.h> -#endif +#include "lvm-defaults.h" char snap_mount_folder[PATH_MAX]; +/* Look for disconnected peers, for missed snap creates or deletes */ static int32_t glusterd_find_missed_snap (dict_t *rsp_dict, glusterd_volinfo_t *vol, - char *snap_uuid, struct list_head *peers, - int32_t op); + struct list_head *peers, int32_t op) +{ + int32_t brick_count = -1; + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + + this = THIS; + GF_ASSERT (this); + GF_ASSERT (rsp_dict); + GF_ASSERT (peers); + GF_ASSERT (vol); + + brick_count = 0; + list_for_each_entry (brickinfo, &vol->bricks, brick_list) { + if (!uuid_compare (brickinfo->uuid, MY_UUID)) { + /* If the brick belongs to the same node */ + brick_count++; + continue; + } + + list_for_each_entry (peerinfo, peers, uuid_list) { + if (uuid_compare (peerinfo->uuid, brickinfo->uuid)) { + /* If the brick doesnt belong to this peer */ + continue; + } + + /* Found peer who owns the brick, * + * if peer is not connected or not * + * friend add it to missed snap list */ + if (!(peerinfo->connected) || + (peerinfo->state.state != + GD_FRIEND_STATE_BEFRIENDED)) { + ret = glusterd_add_missed_snaps_to_dict + (rsp_dict, + vol, brickinfo, + brick_count + 1, + op); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add missed snapshot " + "info for %s:%s in the " + "rsp_dict", brickinfo->hostname, + brickinfo->path); + goto out; + } + } + } + brick_count++; + } + + ret = 0; +out: + gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); + return ret; +} /* This function will restore a snapshot volumes * @@ -62,7 +124,6 @@ int glusterd_snapshot_restore (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { int ret = -1; - char *volname = NULL; char *snapname = NULL; xlator_t *this = NULL; glusterd_volinfo_t *snap_volinfo = NULL; @@ -90,7 +151,7 @@ glusterd_snapshot_restore (dict_t *dict, char **op_errstr, dict_t *rsp_dict) snap = glusterd_find_snap_by_name (snapname); if (NULL == snap) { ret = gf_asprintf (op_errstr, "Snap (%s) not found", - snapname); + snapname); if (ret < 0) { goto out; } @@ -99,6 +160,7 @@ glusterd_snapshot_restore (dict_t *dict, char **op_errstr, dict_t *rsp_dict) goto out; } + /* TODO : As of now there is only volume in snapshot. * Change this when multiple volume snapshot is introduced */ @@ -116,7 +178,6 @@ glusterd_snapshot_restore (dict_t *dict, char **op_errstr, dict_t *rsp_dict) /* From origin glusterd check if * * any peers with snap bricks is down */ ret = glusterd_find_missed_snap (rsp_dict, snap_volinfo, - snap_volinfo->volname, &priv->peers, GF_SNAP_OPTION_TYPE_RESTORE); if (ret) { @@ -133,7 +194,7 @@ glusterd_snapshot_restore (dict_t *dict, char **op_errstr, dict_t *rsp_dict) * failure. */ gf_log (this->name, GF_LOG_ERROR, "Failed to restore " - "snap for %s volume", volname); + "snap for %s", snapname); goto out; } @@ -156,7 +217,7 @@ out: * @param rsp_dict response dictionary * @return Negative value on Failure and 0 in success */ -int +int32_t glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { @@ -267,7 +328,7 @@ out: int snap_max_hard_limits_validate (dict_t *dict, char *volname, - uint64_t value, char **op_errstr) + uint64_t value, char **op_errstr) { char err_str[PATH_MAX] = ""; glusterd_conf_t *conf = NULL; @@ -449,7 +510,7 @@ glusterd_snap_create_pre_val_use_rsp_dict (dict_t *dst, dict_t *src) for (i = 0; i < volume_count; i++) { memset (snapbrckcnt, '\0', sizeof(snapbrckcnt)); ret = snprintf (snapbrckcnt, sizeof(snapbrckcnt) - 1, - "vol%ld_brickcount", i+1); + "vol%"PRId64"_brickcount", i+1); ret = dict_get_int64 (src, snapbrckcnt, &brick_count); if (ret) { gf_log (this->name, GF_LOG_TRACE, @@ -460,7 +521,7 @@ glusterd_snap_create_pre_val_use_rsp_dict (dict_t *dst, dict_t *src) for (j = 0; j < brick_count; j++) { /* Fetching data from source dict */ snprintf (key, sizeof(key) - 1, - "vol%ld.brickdir%ld", i+1, j); + "vol%"PRId64".brickdir%"PRId64, i+1, j); ret = dict_get_ptr (src, key, (void **)&snap_brick_dir); @@ -471,7 +532,7 @@ glusterd_snap_create_pre_val_use_rsp_dict (dict_t *dst, dict_t *src) } snprintf (key, sizeof(key) - 1, - "vol%ld.brick_snapdevice%ld", i+1, j); + "vol%"PRId64".brick_snapdevice%"PRId64, i+1, j); ret = dict_get_ptr (src, key, (void **)&snap_device); @@ -482,7 +543,7 @@ glusterd_snap_create_pre_val_use_rsp_dict (dict_t *dst, dict_t *src) } snprintf (snapbrckord, sizeof(snapbrckord) - 1, - "vol%ld.brick%ld.order", i+1, j); + "vol%"PRId64".brick%"PRId64".order", i+1, j); ret = dict_get_int64 (src, snapbrckord, &brick_order); if (ret) { @@ -493,7 +554,7 @@ glusterd_snap_create_pre_val_use_rsp_dict (dict_t *dst, dict_t *src) /* Adding the data in the dst dict */ snprintf (key, sizeof(key) - 1, - "vol%ld.brickdir%ld", i+1, brick_order); + "vol%"PRId64".brickdir%"PRId64, i+1, brick_order); tmpstr = gf_strdup (snap_brick_dir); if (!tmpstr) { @@ -511,7 +572,7 @@ glusterd_snap_create_pre_val_use_rsp_dict (dict_t *dst, dict_t *src) } snprintf (key, sizeof(key) - 1, - "vol%ld.brick_snapdevice%ld", + "vol%"PRId64".brick_snapdevice%"PRId64, i+1, brick_order); tmpstr = gf_strdup (snap_device); @@ -618,8 +679,8 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, goto out; } if (volcount <= 0) { - snprintf (err_str, sizeof (err_str), "Invalid volume count %ld " - "supplied", volcount); + snprintf (err_str, sizeof (err_str), "Invalid volume count %"PRId64 + " supplied", volcount); ret = -1; goto out; } @@ -638,7 +699,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, } for (i = 1; i <= volcount; i++) { - snprintf (key, sizeof (key), "volname%ld", i); + snprintf (key, sizeof (key), "volname%"PRId64, i); ret = dict_get_str (dict, key, &volname); if (ret) { snprintf (err_str, sizeof (err_str), @@ -690,7 +751,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, goto out; } - snprintf (key, sizeof(key) - 1, "vol%ld_volid", i); + snprintf (key, sizeof(key) - 1, "vol%"PRId64"_volid", i); ret = dict_get_bin (dict, key, (void **)&snap_volid); if (ret) { gf_log (this->name, GF_LOG_ERROR, @@ -745,7 +806,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, } snprintf (key, sizeof(key), - "vol%ld.brick_snapdevice%ld", i, + "vol%"PRId64".brick_snapdevice%"PRId64, i, brick_count); ret = dict_set_dynstr (rsp_dict, key, device); if (ret) { @@ -783,7 +844,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, ret = -1; goto out; } - snprintf (key, sizeof(key), "vol%ld.brickdir%ld", i, + snprintf (key, sizeof(key), "vol%"PRId64".brickdir%"PRId64, i, brick_count); ret = dict_set_dynstr (rsp_dict, key, tmpstr); if (ret) { @@ -793,7 +854,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, } tmpstr = NULL; - snprintf (key, sizeof(key) - 1, "vol%ld.brick%ld.order", + snprintf (key, sizeof(key) - 1, "vol%"PRId64".brick%"PRId64".order", i, brick_count); ret = dict_set_int64 (rsp_dict, key, brick_order); if (ret) { @@ -805,7 +866,7 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, brick_count++; brick_order++; } - snprintf (key, sizeof(key) - 1, "vol%ld_brickcount", i); + snprintf (key, sizeof(key) - 1, "vol%"PRId64"_brickcount", i); ret = dict_set_int64 (rsp_dict, key, brick_count); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to set %s", @@ -1002,7 +1063,7 @@ glusterd_do_lvm_snapshot_remove (glusterd_volinfo_t *snap_vol, snprintf (msg, sizeof(msg), "remove snapshot of the brick %s:%s, " "device: %s", brickinfo->hostname, brickinfo->path, snap_device); - runner_add_args (&runner, "/sbin/lvremove", "-f", snap_device, NULL); + runner_add_args (&runner, LVM_REMOVE, "-f", snap_device, NULL); runner_log (&runner, "", GF_LOG_DEBUG, msg); ret = runner_run (&runner); @@ -1030,19 +1091,25 @@ glusterd_lvm_snapshot_remove (dict_t *rsp_dict, glusterd_volinfo_t *snap_vol) this = THIS; GF_ASSERT (this); - GF_ASSERT (rsp_dict); GF_ASSERT (snap_vol); - if (!snap_vol) { - gf_log (this->name, GF_LOG_ERROR, "snap volinfo is NULL"); + if ((snap_vol->is_snap_volume == _gf_false) && + (uuid_is_null (snap_vol->restored_from_snap))) { + gf_log (this->name, GF_LOG_DEBUG, + "Not a snap volume, or a restored snap volume."); + ret = 0; goto out; } brick_count = -1; list_for_each_entry (brickinfo, &snap_vol->bricks, brick_list) { brick_count++; - if (uuid_compare (brickinfo->uuid, MY_UUID)) + if (uuid_compare (brickinfo->uuid, MY_UUID)) { + gf_log (this->name, GF_LOG_DEBUG, + "%s:%s belongs to a different node", + brickinfo->hostname, brickinfo->path); continue; + } if (brickinfo->snap_status == -1) { gf_log (this->name, GF_LOG_INFO, @@ -1051,20 +1118,23 @@ glusterd_lvm_snapshot_remove (dict_t *rsp_dict, glusterd_volinfo_t *snap_vol) brickinfo->hostname, brickinfo->path, snap_vol->snapshot->snapname); - /* Adding missed delete to the dict */ - ret = glusterd_add_missed_snaps_to_dict + if (rsp_dict && + (snap_vol->is_snap_volume == _gf_true)) { + /* Adding missed delete to the dict */ + ret = glusterd_add_missed_snaps_to_dict (rsp_dict, - snap_vol->volname, + snap_vol, brickinfo, brick_count + 1, GF_SNAP_OPTION_TYPE_DELETE); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to add missed snapshot info " - "for %s:%s in the rsp_dict", - brickinfo->hostname, - brickinfo->path); - goto out; + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add missed snapshot " + "info for %s:%s in the " + "rsp_dict", brickinfo->hostname, + brickinfo->path); + goto out; + } } continue; @@ -1104,6 +1174,7 @@ glusterd_lvm_snapshot_remove (dict_t *rsp_dict, glusterd_volinfo_t *snap_vol) ret = 0; out: + gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); return ret; } @@ -2047,8 +2118,8 @@ glusterd_handle_snapshot_create (rpcsvc_request_t *req, glusterd_op_t op, goto out; } if (volcount <= 0) { - gf_log (this->name, GF_LOG_ERROR, "Invalid volume count %ld " - "supplied", volcount); + gf_log (this->name, GF_LOG_ERROR, "Invalid volume count %"PRId64 + " supplied", volcount); ret = -1; goto out; } @@ -2476,7 +2547,7 @@ glusterd_create_snap_object (dict_t *dict, dict_t *rsp_dict) } if (time_stamp <= 0) { ret = -1; - gf_log (this->name, GF_LOG_ERROR, "Invalid time-stamp: %ld", + gf_log (this->name, GF_LOG_ERROR, "Invalid time-stamp: %"PRId64, time_stamp); goto out; } @@ -2550,11 +2621,12 @@ out: /* Added missed_snap_entry to rsp_dict */ int32_t -glusterd_add_missed_snaps_to_dict (dict_t *rsp_dict, char *snap_uuid, +glusterd_add_missed_snaps_to_dict (dict_t *rsp_dict, + glusterd_volinfo_t *snap_vol, glusterd_brickinfo_t *brickinfo, int32_t brick_number, int32_t op) { - char *buf = NULL; + char *snap_uuid = NULL; char missed_snap_entry[PATH_MAX] = ""; char name_buf[PATH_MAX] = ""; int32_t missed_snap_count = -1; @@ -2564,20 +2636,20 @@ glusterd_add_missed_snaps_to_dict (dict_t *rsp_dict, char *snap_uuid, this = THIS; GF_ASSERT (this); GF_ASSERT (rsp_dict); - GF_ASSERT (snap_uuid); + GF_ASSERT (snap_vol); GF_ASSERT (brickinfo); - snprintf (missed_snap_entry, sizeof(missed_snap_entry), - "%s:%s=%d:%s:%d:%d", uuid_utoa(brickinfo->uuid), - snap_uuid, brick_number, brickinfo->path, op, - GD_MISSED_SNAP_PENDING); - - buf = gf_strdup (missed_snap_entry); - if (!buf) { + snap_uuid = gf_strdup (uuid_utoa (snap_vol->snapshot->snap_id)); + if (!snap_uuid) { ret = -1; goto out; } + snprintf (missed_snap_entry, sizeof(missed_snap_entry), + "%s:%s=%s:%d:%s:%d:%d", uuid_utoa(brickinfo->uuid), + snap_uuid, snap_vol->volname, brick_number, brickinfo->path, + op, GD_MISSED_SNAP_PENDING); + /* Fetch the missed_snap_count from the dict */ ret = dict_get_int32 (rsp_dict, "missed_snap_count", &missed_snap_count); @@ -2589,12 +2661,12 @@ glusterd_add_missed_snaps_to_dict (dict_t *rsp_dict, char *snap_uuid, /* Setting the missed_snap_entry in the rsp_dict */ snprintf (name_buf, sizeof(name_buf), "missed_snaps_%d", missed_snap_count); - ret = dict_set_dynstr (rsp_dict, name_buf, buf); + ret = dict_set_dynstr_with_alloc (rsp_dict, name_buf, + missed_snap_entry); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to set missed_snap_entry (%s) " - "in the rsp_dict.", buf); - GF_FREE (buf); + "in the rsp_dict.", missed_snap_entry); goto out; } missed_snap_count++; @@ -2610,6 +2682,9 @@ glusterd_add_missed_snaps_to_dict (dict_t *rsp_dict, char *snap_uuid, } out: + if (snap_uuid) + GF_FREE (snap_uuid); + gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); return ret; } @@ -2715,7 +2790,7 @@ glusterd_take_lvm_snapshot (glusterd_volinfo_t *snap_vol, /* Figuring out if setactivationskip flag is supported or not */ runinit (&runner); snprintf (msg, sizeof (msg), "running lvcreate help"); - runner_add_args (&runner, "/sbin/lvcreate", "--help", NULL); + runner_add_args (&runner, LVM_CREATE, "--help", NULL); runner_log (&runner, "", GF_LOG_DEBUG, msg); runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); ret = runner_start (&runner); @@ -2744,11 +2819,11 @@ glusterd_take_lvm_snapshot (glusterd_volinfo_t *snap_vol, snprintf (msg, sizeof (msg), "taking snapshot of the brick %s:%s", brickinfo->hostname, brickinfo->path); if (match == _gf_true) - runner_add_args (&runner, "/sbin/lvcreate", "-s", device, + runner_add_args (&runner, LVM_CREATE, "-s", device, "--setactivationskip", "n", "--name", snap_vol->volname, NULL); else - runner_add_args (&runner, "/sbin/lvcreate", "-s", device, + runner_add_args (&runner, LVM_CREATE, "-s", device, "--name", snap_vol->volname, NULL); runner_log (&runner, "", GF_LOG_DEBUG, msg); ret = runner_start (&runner); @@ -2785,9 +2860,7 @@ glusterd_snap_brick_create (char *device, glusterd_volinfo_t *snap_volinfo, glusterd_conf_t *priv = NULL; char snap_brick_mount_path[PATH_MAX] = ""; char snap_brick_path[PATH_MAX] = ""; - char msg[1024] = ""; struct stat statbuf = {0, }; - runner_t runner = {0, }; this = THIS; priv = this->private; @@ -2818,25 +2891,12 @@ glusterd_snap_brick_create (char *device, glusterd_volinfo_t *snap_volinfo, MS_MGC_VAL, "nouuid"); But for now, mounting using runner apis. */ - runinit (&runner); - snprintf (msg, sizeof (msg), "mounting snapshot of the brick %s:%s", - original_brickinfo->hostname, original_brickinfo->path); - runner_add_args (&runner, "mount", "-o", "nouuid", device, - snap_brick_mount_path, NULL); - runner_log (&runner, "", GF_LOG_DEBUG, msg); - - /* let glusterd get blocked till snapshot is over */ - synclock_unlock (&priv->big_lock); - ret = runner_run (&runner); - synclock_lock (&priv->big_lock); + ret = glusterd_mount_lvm_snapshot (device, snap_brick_mount_path); if (ret) { - gf_log (this->name, GF_LOG_ERROR, "mounting the snapshot " - "logical device %s failed (error: %s)", device, - strerror (errno)); + gf_log (this->name, GF_LOG_ERROR, + "Failed to mount lvm snapshot."); goto out; - } else - gf_log (this->name, GF_LOG_DEBUG, "mounting the snapshot " - "logical device %s successful", device); + } ret = stat (snap_brick_path, &statbuf); if (ret) { @@ -2862,7 +2922,11 @@ out: if (ret) { gf_log (this->name, GF_LOG_WARNING, "unmounting the snap brick" " mount %s", snap_brick_mount_path); +#if !defined(GF_DARWIN_HOST_OS) umount (snap_brick_mount_path); +#else + unmount (snap_brick_mount_path, 0); +#endif } gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); @@ -2893,7 +2957,7 @@ glusterd_add_bricks_to_snap_volume (dict_t *dict, dict_t *rsp_dict, GF_ASSERT (snap_brickinfo); GF_ASSERT (snap_brick_dir); - snprintf (key, sizeof(key) - 1, "vol%ld.brickdir%d", volcount, + snprintf (key, sizeof(key) - 1, "vol%"PRId64".brickdir%d", volcount, brick_count); ret = dict_get_ptr (dict, key, (void **)snap_brick_dir); if (ret) { @@ -2938,7 +3002,7 @@ glusterd_add_bricks_to_snap_volume (dict_t *dict, dict_t *rsp_dict, if (add_missed_snap) { ret = glusterd_add_missed_snaps_to_dict (rsp_dict, - snap_vol->volname, + snap_vol, original_brickinfo, brick_count + 1, GF_SNAP_OPTION_TYPE_CREATE); @@ -2951,7 +3015,7 @@ glusterd_add_bricks_to_snap_volume (dict_t *dict, dict_t *rsp_dict, } } - snprintf (key, sizeof(key), "vol%ld.brick_snapdevice%d", + snprintf (key, sizeof(key), "vol%"PRId64".brick_snapdevice%d", volcount, brick_count); ret = dict_get_ptr (dict, key, (void **)&snap_device); if (ret) { @@ -3038,70 +3102,6 @@ out: return ret; } -/* Look for disconnected peers, for missed snap creates or deletes */ -static int32_t -glusterd_find_missed_snap (dict_t *rsp_dict, glusterd_volinfo_t *vol, - char *snap_uuid, struct list_head *peers, - int32_t op) -{ - int32_t brick_count = -1; - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_peerinfo_t *peerinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - - this = THIS; - GF_ASSERT (this); - GF_ASSERT (rsp_dict); - GF_ASSERT (peers); - GF_ASSERT (vol); - GF_ASSERT (snap_uuid); - - brick_count = 0; - list_for_each_entry (brickinfo, &vol->bricks, brick_list) { - if (!uuid_compare (brickinfo->uuid, MY_UUID)) { - /* If the brick belongs to the same node */ - brick_count++; - continue; - } - - list_for_each_entry (peerinfo, peers, uuid_list) { - if (uuid_compare (peerinfo->uuid, brickinfo->uuid)) { - /* If the brick doesnt belong to this peer */ - continue; - } - - /* Found peer who owns the brick, * - * if peer is not connected or not * - * friend add it to missed snap list */ - if (!(peerinfo->connected) || - (peerinfo->state.state != - GD_FRIEND_STATE_BEFRIENDED)) { - ret = glusterd_add_missed_snaps_to_dict - (rsp_dict, - snap_uuid, - brickinfo, - brick_count + 1, - op); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "Failed to add missed snapshot " - "info for %s:%s in the " - "rsp_dict", brickinfo->hostname, - brickinfo->path); - goto out; - } - } - } - brick_count++; - } - - ret = 0; -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - glusterd_volinfo_t * glusterd_do_snap_vol (glusterd_volinfo_t *origin_vol, glusterd_snap_t *snap, dict_t *dict, dict_t *rsp_dict, int64_t volcount) @@ -3129,7 +3129,7 @@ glusterd_do_snap_vol (glusterd_volinfo_t *origin_vol, glusterd_snap_t *snap, GF_ASSERT (rsp_dict); /* fetch username, password and vol_id from dict*/ - snprintf (key, sizeof(key), "volume%ld_username", volcount); + snprintf (key, sizeof(key), "volume%"PRId64"_username", volcount); ret = dict_get_str (dict, key, &username); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to get %s for " @@ -3137,7 +3137,7 @@ glusterd_do_snap_vol (glusterd_volinfo_t *origin_vol, glusterd_snap_t *snap, goto out; } - snprintf (key, sizeof(key), "volume%ld_password", volcount); + snprintf (key, sizeof(key), "volume%"PRId64"_password", volcount); ret = dict_get_str (dict, key, &password); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to get %s for " @@ -3145,7 +3145,7 @@ glusterd_do_snap_vol (glusterd_volinfo_t *origin_vol, glusterd_snap_t *snap, goto out; } - snprintf (key, sizeof(key) - 1, "vol%ld_volid", volcount); + snprintf (key, sizeof(key) - 1, "vol%"PRId64"_volid", volcount); ret = dict_get_bin (dict, key, (void **)&snap_volid); if (ret) { gf_log (this->name, GF_LOG_ERROR, @@ -3367,7 +3367,7 @@ glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op, goto out; } - snprintf (key, sizeof (key), "volname%ld", volcount); + snprintf (key, sizeof (key), "volname%"PRId64, volcount); ret = dict_set_dynstr (dict, key, volname); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to set " @@ -3582,7 +3582,6 @@ glusterd_snapshot_remove_commit (dict_t *dict, char **op_errstr, /* From origin glusterd check if * * any peers with snap bricks is down */ ret = glusterd_find_missed_snap (rsp_dict, snap_volinfo, - snap_volinfo->volname, &priv->peers, GF_SNAP_OPTION_TYPE_DELETE); if (ret) { @@ -3697,7 +3696,14 @@ glusterd_snapshot_update_snaps_post_validate (dict_t *dict, char **op_errstr, goto out; } - ret = glusterd_store_update_missed_snaps (dict, missed_snap_count); + ret = glusterd_add_missed_snaps_to_list (dict, missed_snap_count); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to add missed snaps to list"); + goto out; + } + + ret = glusterd_store_update_missed_snaps (); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to update missed_snaps_list"); @@ -3771,7 +3777,7 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, } for (i = 1; i <= volcount; i++) { - snprintf (key, sizeof (key), "volname%ld", i); + snprintf (key, sizeof (key), "volname%"PRId64, i); ret = dict_get_str (dict, key, &volname); if (ret) { gf_log (this->name, GF_LOG_ERROR, @@ -3922,7 +3928,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname, soft_limit_value = (active_hard_limit * conf->snap_max_soft_limit) / 100; - snprintf (buf, sizeof(buf), "volume%ld-volname", count); + snprintf (buf, sizeof(buf), "volume%"PRIu64"-volname", count); ret = dict_set_str (rsp_dict, buf, volinfo->volname); if (ret) { snprintf (err_str, PATH_MAX, @@ -3931,7 +3937,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname, } snprintf (buf, sizeof(buf), - "volume%ld-snap-max-hard-limit", count); + "volume%"PRIu64"-snap-max-hard-limit", count); ret = dict_set_uint64 (rsp_dict, buf, snap_max_limit); if (ret) { snprintf (err_str, PATH_MAX, @@ -3940,7 +3946,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname, } snprintf (buf, sizeof(buf), - "volume%ld-active-hard-limit", count); + "volume%"PRIu64"-active-hard-limit", count); ret = dict_set_uint64 (rsp_dict, buf, active_hard_limit); if (ret) { @@ -3950,7 +3956,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname, } snprintf (buf, sizeof(buf), - "volume%ld-snap-max-soft-limit", count); + "volume%"PRIu64"-snap-max-soft-limit", count); ret = dict_set_uint64 (rsp_dict, buf, soft_limit_value); if (ret) { snprintf (err_str, PATH_MAX, @@ -3984,7 +3990,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname, soft_limit_value = (active_hard_limit * conf->snap_max_soft_limit) / 100; - snprintf (buf, sizeof(buf), "volume%ld-volname", count); + snprintf (buf, sizeof(buf), "volume%"PRIu64"-volname", count); ret = dict_set_str (rsp_dict, buf, volinfo->volname); if (ret) { snprintf (err_str, PATH_MAX, @@ -3993,7 +3999,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname, } snprintf (buf, sizeof(buf), - "volume%ld-snap-max-hard-limit", count); + "volume%"PRIu64"-snap-max-hard-limit", count); ret = dict_set_uint64 (rsp_dict, buf, snap_max_limit); if (ret) { snprintf (err_str, PATH_MAX, @@ -4002,7 +4008,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname, } snprintf (buf, sizeof(buf), - "volume%ld-active-hard-limit", count); + "volume%"PRIu64"-active-hard-limit", count); ret = dict_set_uint64 (rsp_dict, buf, active_hard_limit); if (ret) { snprintf (err_str, PATH_MAX, @@ -4011,7 +4017,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname, } snprintf (buf, sizeof(buf), - "volume%ld-snap-max-soft-limit", count); + "volume%"PRIu64"-snap-max-soft-limit", count); ret = dict_set_uint64 (rsp_dict, buf, soft_limit_value); if (ret) { snprintf (err_str, PATH_MAX, @@ -4196,7 +4202,7 @@ glusterd_get_brick_lvm_details (dict_t *rsp_dict, * for the above given command with separator ":", * The output will be "vgname:lvsize" */ - runner_add_args (&runner, "lvs", device, "--noheading", "-o", + runner_add_args (&runner, LVS, device, "--noheading", "-o", "vg_name,data_percent,lv_size", "--separator", ":", NULL); runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); @@ -5320,6 +5326,30 @@ glusterd_free_snap_op (glusterd_snap_op_t *snap_op) } } +static inline void +glusterd_free_missed_snapinfo (glusterd_missed_snap_info *missed_snapinfo) +{ + glusterd_snap_op_t *snap_opinfo = NULL; + glusterd_snap_op_t *tmp = NULL; + + if (missed_snapinfo) { + list_for_each_entry_safe (snap_opinfo, tmp, + &missed_snapinfo->snap_ops, + snap_ops_list) { + glusterd_free_snap_op (snap_opinfo); + snap_opinfo = NULL; + } + + if (missed_snapinfo->node_uuid) + GF_FREE (missed_snapinfo->node_uuid); + + if (missed_snapinfo->snap_uuid) + GF_FREE (missed_snapinfo->snap_uuid); + + GF_FREE (missed_snapinfo); + } +} + /* Look for duplicates and accordingly update the list */ int32_t glusterd_update_missed_snap_entry (glusterd_missed_snap_info *missed_snapinfo, @@ -5337,6 +5367,13 @@ glusterd_update_missed_snap_entry (glusterd_missed_snap_info *missed_snapinfo, list_for_each_entry (snap_opinfo, &missed_snapinfo->snap_ops, snap_ops_list) { + /* If the entry is not for the same snap_vol_id + * then continue + */ + if (strcmp (snap_opinfo->snap_vol_id, + missed_snap_op->snap_vol_id)) + continue; + if ((!strcmp (snap_opinfo->brick_path, missed_snap_op->brick_path)) && (snap_opinfo->op == missed_snap_op->op)) { @@ -5348,8 +5385,10 @@ glusterd_update_missed_snap_entry (glusterd_missed_snap_info *missed_snapinfo, snap_opinfo->status = GD_MISSED_SNAP_DONE; gf_log (this->name, GF_LOG_INFO, "Updating missed snap status " - "for %s:%d:%s:%d as DONE", - missed_snapinfo->node_snap_info, + "for %s:%s=%s:%d:%s:%d as DONE", + missed_snapinfo->node_uuid, + missed_snapinfo->snap_uuid, + snap_opinfo->snap_vol_id, snap_opinfo->brick_num, snap_opinfo->brick_path, snap_opinfo->op); @@ -5362,15 +5401,19 @@ glusterd_update_missed_snap_entry (glusterd_missed_snap_info *missed_snapinfo, } else if ((snap_opinfo->brick_num == missed_snap_op->brick_num) && (snap_opinfo->op == GF_SNAP_OPTION_TYPE_CREATE) && - (missed_snap_op->op == - GF_SNAP_OPTION_TYPE_DELETE)) { + ((missed_snap_op->op == + GF_SNAP_OPTION_TYPE_DELETE) || + (missed_snap_op->op == + GF_SNAP_OPTION_TYPE_RESTORE))) { /* Optimizing create and delete entries for the same * brick and same node */ gf_log (this->name, GF_LOG_INFO, "Updating missed snap status " - "for %s:%d:%s:%d as DONE", - missed_snapinfo->node_snap_info, + "for %s:%s=%s:%d:%s:%d as DONE", + missed_snapinfo->node_uuid, + missed_snapinfo->snap_uuid, + snap_opinfo->snap_vol_id, snap_opinfo->brick_num, snap_opinfo->brick_path, snap_opinfo->op); @@ -5398,10 +5441,13 @@ out: /* Add new missed snap entry to the missed_snaps list. */ int32_t -glusterd_store_missed_snaps_list (char *missed_info, int32_t brick_num, - char *brick_path, int32_t snap_op, - int32_t snap_status) +glusterd_add_new_entry_to_list (char *missed_info, char *snap_vol_id, + int32_t brick_num, char *brick_path, + int32_t snap_op, int32_t snap_status) { + char *buf = NULL; + char *save_ptr = NULL; + char node_snap_info[PATH_MAX] = ""; int32_t ret = -1; glusterd_missed_snap_info *missed_snapinfo = NULL; glusterd_snap_op_t *missed_snap_op = NULL; @@ -5413,6 +5459,7 @@ glusterd_store_missed_snaps_list (char *missed_info, int32_t brick_num, this = THIS; GF_ASSERT(this); GF_ASSERT(missed_info); + GF_ASSERT(snap_vol_id); GF_ASSERT(brick_path); priv = this->private; @@ -5428,6 +5475,11 @@ glusterd_store_missed_snaps_list (char *missed_info, int32_t brick_num, goto out; } + missed_snap_op->snap_vol_id = gf_strdup(snap_vol_id); + if (!missed_snap_op->snap_vol_id) { + ret = -1; + goto out; + } missed_snap_op->brick_path = gf_strdup(brick_path); if (!missed_snap_op->brick_path) { ret = -1; @@ -5440,8 +5492,10 @@ glusterd_store_missed_snaps_list (char *missed_info, int32_t brick_num, /* Look for other entries for the same node and same snap */ list_for_each_entry (missed_snapinfo, &priv->missed_snaps_list, missed_snaps) { - if (!strcmp (missed_snapinfo->node_snap_info, - missed_info)) { + snprintf (node_snap_info, sizeof(node_snap_info), + "%s:%s", missed_snapinfo->node_uuid, + missed_snapinfo->snap_uuid); + if (!strcmp (node_snap_info, missed_info)) { /* Found missed snapshot info for * * the same node and same snap */ match = _gf_true; @@ -5458,8 +5512,24 @@ glusterd_store_missed_snaps_list (char *missed_info, int32_t brick_num, goto out; } free_missed_snap_info = _gf_true; - missed_snapinfo->node_snap_info = gf_strdup(missed_info); - if (!missed_snapinfo->node_snap_info) { + buf = strtok_r (missed_info, ":", &save_ptr); + if (!buf) { + ret = -1; + goto out; + } + missed_snapinfo->node_uuid = gf_strdup(buf); + if (!missed_snapinfo->node_uuid) { + ret = -1; + goto out; + } + + buf = strtok_r (NULL, ":", &save_ptr); + if (!buf) { + ret = -1; + goto out; + } + missed_snapinfo->snap_uuid = gf_strdup(buf); + if (!missed_snapinfo->snap_uuid) { ret = -1; goto out; } @@ -5486,12 +5556,8 @@ out: glusterd_free_snap_op (missed_snap_op); if (missed_snapinfo && - (free_missed_snap_info == _gf_true)) { - if (missed_snapinfo->node_snap_info) - GF_FREE (missed_snapinfo->node_snap_info); - - GF_FREE (missed_snapinfo); - } + (free_missed_snap_info == _gf_true)) + glusterd_free_missed_snapinfo (missed_snapinfo); } gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); @@ -5507,6 +5573,7 @@ glusterd_add_missed_snaps_to_list (dict_t *dict, int32_t missed_snap_count) char *save_ptr = NULL; char *nodeid = NULL; char *snap_uuid = NULL; + char *snap_vol_id = NULL; char *brick_path = NULL; char missed_info[PATH_MAX] = ""; char name_buf[PATH_MAX] = ""; @@ -5553,13 +5620,14 @@ glusterd_add_missed_snaps_to_list (dict_t *dict, int32_t missed_snap_count) */ nodeid = strtok_r (tmp, ":", &save_ptr); snap_uuid = strtok_r (NULL, "=", &save_ptr); + snap_vol_id = strtok_r (NULL, ":", &save_ptr); brick_num = atoi(strtok_r (NULL, ":", &save_ptr)); brick_path = strtok_r (NULL, ":", &save_ptr); snap_op = atoi(strtok_r (NULL, ":", &save_ptr)); snap_status = atoi(strtok_r (NULL, ":", &save_ptr)); if (!nodeid || !snap_uuid || !brick_path || - brick_num < 1 || snap_op < 1 || + !snap_vol_id || brick_num < 1 || snap_op < 1 || snap_status < 1) { gf_log (this->name, GF_LOG_ERROR, "Invalid missed_snap_entry"); @@ -5570,11 +5638,12 @@ glusterd_add_missed_snaps_to_list (dict_t *dict, int32_t missed_snap_count) snprintf (missed_info, sizeof(missed_info), "%s:%s", nodeid, snap_uuid); - ret = glusterd_store_missed_snaps_list (missed_info, - brick_num, - brick_path, - snap_op, - snap_status); + ret = glusterd_add_new_entry_to_list (missed_info, + snap_vol_id, + brick_num, + brick_path, + snap_op, + snap_status); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to store missed snaps_list"); @@ -5585,6 +5654,7 @@ glusterd_add_missed_snaps_to_list (dict_t *dict, int32_t missed_snap_count) tmp = NULL; } + ret = 0; out: if (tmp) GF_FREE (tmp); @@ -5592,3 +5662,126 @@ out: gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); return ret; } + +/* This function will restore origin volume to 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 + * + * @return 0 on success and negative value on error + */ +int +gd_restore_snap_volume (dict_t *rsp_dict, + glusterd_volinfo_t *orig_vol, + glusterd_volinfo_t *snap_vol) +{ + int ret = -1; + glusterd_volinfo_t *new_volinfo = NULL; + glusterd_snap_t *snap = NULL; + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + glusterd_volinfo_t *temp_volinfo = NULL; + glusterd_volinfo_t *voliter = NULL; + + this = THIS; + GF_ASSERT (this); + GF_ASSERT (rsp_dict); + conf = this->private; + GF_ASSERT (conf); + + 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); + + /* Snap volume must be stoped before performing the + * restore operation. + */ + ret = glusterd_stop_volume (snap_vol); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to stop " + "snap volume"); + goto out; + } + + /* 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 create volinfo"); + goto out; + } + + /* 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; + uuid_copy (new_volinfo->restored_from_snap, + snap_vol->snapshot->snap_id); + + /* Bump the version of the restored volume, so that nodes * + * which are done can sync during handshake */ + new_volinfo->version = orig_vol->version; + + list_for_each_entry_safe (voliter, temp_volinfo, + &orig_vol->snap_volumes, snapvol_list) { + list_add_tail (&voliter->snapvol_list, + &new_volinfo->snap_volumes); + } + /* Copy the snap vol info to the new_volinfo.*/ + ret = glusterd_snap_volinfo_restore (rsp_dict, 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; + } + + ret = glusterd_lvm_snapshot_remove (rsp_dict, orig_vol); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to remove " + "LVM backend"); + (void)glusterd_volinfo_delete (new_volinfo); + goto out; + } + + /* New volinfo always shows the status as created. Therefore + * set the status to the original volume's status. */ + glusterd_set_volume_status (new_volinfo, orig_vol->status); + + /* Once the new_volinfo is completely constructed then delete + * the orinal volinfo + */ + ret = glusterd_volinfo_delete (orig_vol); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to delete volinfo"); + (void)glusterd_volinfo_delete (new_volinfo); + goto out; + } + + list_add_tail (&new_volinfo->vol_list, &conf->volumes); + + /* Now delete the snap entry. As a first step delete the snap + * volume information stored in store. */ + ret = glusterd_snap_remove (rsp_dict, snap, _gf_false, _gf_true); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Failed to delete " + "snap %s", snap->snapname); + goto out; + } + + ret = glusterd_store_volinfo (new_volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to store volinfo"); + goto out; + } + + ret = 0; +out: + + return ret; +} |