From f834bbc2714a52db7955474ee362321c4f6617ce Mon Sep 17 00:00:00 2001 From: Avra Sengupta Date: Thu, 21 Nov 2013 03:48:32 +0000 Subject: glusterd/mgmtv3: Fetching snap mount path per brick. Fetching snap mount path per brick during pre-validate and aggregating it before commit to generate all brick volfiles and all client volfiles on all nodes. Added changes to propagate the same cg-id by generating it in pre-validate and sending the same to all the nodes during commit Also fixed volume-id mismatches caused in snap-volumes leading to failures of volume status Change-Id: I0b8ed81ac93077cd50313e6eeed00f71932cf2ac Signed-off-by: Avra Sengupta Signed-off-by: Rajesh Joseph --- xlators/mgmt/glusterd/src/glusterd-mgmt.c | 67 ++- xlators/mgmt/glusterd/src/glusterd-mgmt.h | 4 + xlators/mgmt/glusterd/src/glusterd-snapshot.c | 649 ++++++++++++++++++++------ 3 files changed, 576 insertions(+), 144 deletions(-) (limited to 'xlators') diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.c b/xlators/mgmt/glusterd/src/glusterd-mgmt.c index 539705021..852d60fb4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mgmt.c +++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.c @@ -371,9 +371,30 @@ out: return ret; } +int +glusterd_pre_validate_aggr_rsp_dict (glusterd_op_t op, dict_t *aggr, dict_t *rsp) +{ + int ret = 0; + + switch (op) { + case GD_OP_SNAP: + ret = glusterd_snap_pre_validate_use_rsp_dict (aggr, rsp); + if (ret) + goto out; + break; + default: + ret = -1; + gf_log ("", GF_LOG_ERROR, "Invalid op (%s)", gd_op_list[op]); + + break; + } +out: + return ret; +} + int32_t gd_mgmt_v3_pre_validate_cbk_fn (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) + int count, void *myframe) { int ret = -1; struct syncargs *args = NULL; @@ -382,6 +403,7 @@ gd_mgmt_v3_pre_validate_cbk_fn (struct rpc_req *req, struct iovec *iov, call_frame_t *frame = NULL; int op_ret = -1; int op_errno = -1; + dict_t *rsp_dict = NULL; GF_ASSERT(req); GF_ASSERT(iov); @@ -403,11 +425,39 @@ gd_mgmt_v3_pre_validate_cbk_fn (struct rpc_req *req, struct iovec *iov, if (ret < 0) goto out; + if (rsp.dict.dict_len) { + /* Unserialize the dictionary */ + rsp_dict = dict_new (); + + ret = dict_unserialize (rsp.dict.dict_val, + rsp.dict.dict_len, + &rsp_dict); + if (ret < 0) { + GF_FREE (rsp.dict.dict_val); + goto out; + } else { + rsp_dict->extra_stdfree = rsp.dict.dict_val; + } + } + uuid_copy (args->uuid, rsp.uuid); + pthread_mutex_lock (&args->lock_dict); + { + ret = glusterd_pre_validate_aggr_rsp_dict (rsp.op, args->dict, + rsp_dict); + } + pthread_mutex_unlock (&args->lock_dict); + if (ret) + gf_log ("", GF_LOG_ERROR, "%s", + "Failed to aggregate response from " + " node/brick"); op_ret = rsp.op_ret; op_errno = rsp.op_errno; out: + if (rsp_dict) + dict_unref (rsp_dict); + gd_mgmt_v3_collate_errors (args, op_ret, op_errno, NULL, GLUSTERD_MGMT_V3_PRE_VALIDATE, peerinfo, rsp.uuid); @@ -460,7 +510,7 @@ out: int glusterd_mgmt_v3_pre_validate (glusterd_conf_t *conf, glusterd_op_t op, - dict_t *req_dict, char **op_errstr, int npeers) + dict_t *req_dict, char **op_errstr, int npeers) { int ret = -1; int peer_cnt = 0; @@ -483,7 +533,7 @@ glusterd_mgmt_v3_pre_validate (glusterd_conf_t *conf, glusterd_op_t op, /* Pre Validation on local node */ ret = gd_mgmt_v3_pre_validate_fn (op, req_dict, op_errstr, - rsp_dict); + rsp_dict); if (ret) { gf_log (this->name, GF_LOG_ERROR, @@ -504,6 +554,15 @@ glusterd_mgmt_v3_pre_validate (glusterd_conf_t *conf, glusterd_op_t op, goto out; } + ret = glusterd_pre_validate_aggr_rsp_dict (op, req_dict, + rsp_dict); + if (ret) { + gf_log ("", GF_LOG_ERROR, "%s", + "Failed to aggregate response from " + " node/brick"); + goto out; + } + dict_unref (rsp_dict); rsp_dict = NULL; @@ -513,7 +572,7 @@ glusterd_mgmt_v3_pre_validate (glusterd_conf_t *conf, glusterd_op_t op, } /* Sending Pre Validation req to other nodes in the cluster */ - gd_syncargs_init (&args, NULL); + gd_syncargs_init (&args, req_dict); synctask_barrier_init((&args)); peer_cnt = 0; list_for_each_entry (peerinfo, peers, op_peers_list) { diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.h b/xlators/mgmt/glusterd/src/glusterd-mgmt.h index 8c085d18c..25ce32e01 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mgmt.h +++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.h @@ -38,4 +38,8 @@ glusterd_mgmt_v3_initiate_all_phases (rpcsvc_request_t *req, glusterd_op_t op, int32_t glusterd_mgmt_v3_initiate_snap_phases (rpcsvc_request_t *req, glusterd_op_t op, dict_t *dict); + +int +glusterd_snap_pre_validate_use_rsp_dict (dict_t *dst, dict_t *src); + #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index ea26059b5..6a1fc4cea 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -44,6 +44,8 @@ #include #endif +char * +generate_snapname (char *volname, char *name, gf_boolean_t volume_from_cg); /* This function will do the actual snapshot restore on the brick. @@ -540,17 +542,163 @@ out: return ret; } +int +glusterd_snap_create_pre_val_use_rsp_dict (dict_t *dst, dict_t *src) +{ + char *snap_mount = NULL; + char *tmpstr = NULL; + char snapmntname[PATH_MAX] = ""; + char snapbrckcnt[PATH_MAX] = ""; + char snapbrckord[PATH_MAX] = ""; + int ret = -1; + int64_t i = -1; + int64_t j = -1; + int64_t volume_count = 0; + int64_t brick_count = 0; + int64_t brick_order = 0; + + + if (!dst || !src) { + gf_log ("", GF_LOG_ERROR, "Source or Destination " + "dict is empty."); + goto out; + } + + ret = dict_get_int64 (src, "volcount", &volume_count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "failed to " + "get the volume count"); + goto out; + } + + for (i = 0; i < volume_count; i++) { + memset (snapbrckcnt, '\0', sizeof(snapbrckcnt)); + ret = snprintf (snapbrckcnt, sizeof(snapbrckcnt) - 1, + "vol%ld_brickcount", i+1); + ret = dict_get_int64 (src, snapbrckcnt, &brick_count); + if (ret) { + gf_log ("", GF_LOG_TRACE, + "No bricks for this volume in this dict"); + continue; + } + + for (j = 0; j < brick_count; j++) { + /* Fetching data from source dict */ + memset (snapmntname, '\0', sizeof(snapmntname)); + ret = snprintf (snapmntname, sizeof(snapmntname) - 1, + "vol%ld.brick%ld", i+1, j); + + ret = dict_get_ptr (src, snapmntname, (void **)&snap_mount); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Unable to fetch " + "snap mount path"); + goto out; + } + memset (snapbrckord, '\0', sizeof(snapbrckord)); + ret = snprintf (snapbrckord, sizeof(snapbrckord) - 1, + "vol%ld.brick%ld.order", i+1, j); + + ret = dict_get_int64 (src, snapbrckord, &brick_order); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to get brick order"); + goto out; + } + + /* Adding the data in the dst dict */ + memset (snapmntname, '\0', sizeof(snapmntname)); + ret = snprintf (snapmntname, sizeof(snapmntname) - 1, + "vol%ld.brick%ld", i+1, brick_order); + + tmpstr = gf_strdup (snap_mount); + if (!tmpstr) { + gf_log (THIS->name, GF_LOG_ERROR, "Out Of Memory"); + ret = -1; + goto out; + } + ret = dict_set_dynstr (dst, snapmntname, tmpstr); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to set %s", + snap_mount); + GF_FREE (tmpstr); + goto out; + } + } + } + + ret = 0; +out: + + gf_log (THIS->name, GF_LOG_TRACE, "Returning %d", ret); + return ret; +} + +int +glusterd_snap_pre_validate_use_rsp_dict (dict_t *dst, dict_t *src) +{ + int ret = -1; + int32_t snap_command = 0; + + if (!dst || !src) { + gf_log ("", GF_LOG_ERROR, "Source or Destination " + "dict is empty."); + goto out; + } + + ret = dict_get_int32 (dst, "type", &snap_command); + if (ret) { + gf_log ("", GF_LOG_ERROR, "unable to get the type of " + "the snapshot command"); + goto out; + } + + switch (snap_command) { + case GF_SNAP_OPTION_TYPE_CREATE: + ret = glusterd_snap_create_pre_val_use_rsp_dict (dst, src); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to use rsp dict"); + goto out; + } + break; + default: + break; + } + + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + int glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { - char *volname = NULL; - glusterd_volinfo_t *volinfo = NULL; - int64_t volume_count = 0; - char volname_buf[PATH_MAX] = {0, }; - int64_t i = 0; - xlator_t *this = NULL; - int ret = -1; + char *volname = NULL; + char *name = NULL; + char *device = NULL; + char *tmpstr = NULL; + char *snap_brick_dir = NULL; + char snap_brick_path[PATH_MAX] = ""; + char *mnt_pt = NULL; + char snapname[PATH_MAX] = ""; + char tmp[2046] = ""; + char volname_buf[PATH_MAX] = ""; + char snap_mount[PATH_MAX] = ""; + char snapmntname[PATH_MAX] = ""; + char snapbrckcnt[PATH_MAX] = ""; + char snapbrckord[PATH_MAX] = ""; + char snapvolidname[PATH_MAX] = ""; + int ret = -1; + int64_t i = 0; + int64_t volume_count = 0; + int64_t brick_count = 0; + int64_t brick_order = 0; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_volinfo_t *volinfo = NULL; + gf_boolean_t is_cg = _gf_false; + uuid_t *cg_id = NULL; + uuid_t *snap_volid = NULL; + xlator_t *this = NULL; this = THIS; @@ -560,6 +708,68 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, "get the volume count"); goto out; } + + //snap-name should not be set if volume_count > 1 + ret = dict_get_str (dict, "snap-name", &name); + if (volume_count > 1 && !ret) + GF_ASSERT (0); + + if (volume_count > 1) { + is_cg = _gf_true; + ret = dict_get_str (dict, "cg-name", &name); + if (is_origin_glusterd (dict)) { + /* Generate a transaction-id for this operation and + * save it in the dict */ + cg_id = GF_CALLOC (1, sizeof(uuid_t), gf_common_mt_uuid_t); + if (!cg_id) { + gf_log (this->name, GF_LOG_ERROR, + "Out Of Memory"); + ret = -1; + goto out; + } + + uuid_generate (*cg_id); + ret = dict_set_bin (dict, "cg-id", cg_id, sizeof(uuid_t)); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to set cg-id"); + GF_FREE (cg_id); + goto out; + } + } + } else if (volume_count == 1) + ret = dict_get_str (dict, "snap-name", &name); + + if (!name) { + name = generate_snapname (volname, NULL, is_cg); + if (!name) { + gf_log (this->name, GF_LOG_ERROR, + "strdup of internal snapname" + " ((%s) failed for the " + "volume %s", name, + volname); + goto out; + } + } + + if (!is_cg) + snprintf (snapname, sizeof (snapname), "%s", name); + + tmpstr = gf_strdup (name); + if (!tmpstr) { + gf_log (this->name, GF_LOG_ERROR, "Out Of Memory"); + ret = -1; + goto out; + } + ret = dict_set_dynstr (dict, "snap-name", tmpstr); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to set snap-name"); + ret = -1; + goto out; + } + + tmpstr = NULL; + for (i = 0; i < volume_count; i++) { snprintf (volname_buf, sizeof (volname_buf), "volname%ld", i+1); @@ -591,8 +801,210 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr, "for the volume %s", volname); goto out; } + + if (is_cg) { + memset(snapname, '\0', sizeof (snapname)); + snprintf (tmp, sizeof (tmp), "%s_snap", volinfo->volname); + snprintf (snapname, sizeof (snapname), "%s_%s", name, tmp); + } + //Also check whether geo replication is running + + brick_count = 0; + brick_order = 0; + /* Adding snap bricks mount paths to the dict */ + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (uuid_compare (brickinfo->uuid, MY_UUID)) { + brick_order++; + continue; + } + + memset (snapmntname, '\0', sizeof(snapmntname)); + memset (snapbrckord, '\0', sizeof(snapbrckord)); + memset (snap_mount, '\0', sizeof(snap_mount)); + + device = glusterd_get_brick_mount_details (brickinfo); + if (!device) { + gf_log (this->name, GF_LOG_ERROR, "getting device name for " + "the brick %s:%s failed", brickinfo->hostname, + brickinfo->path); + ret = -1; + goto out; + } + + device = glusterd_build_snap_device_path (device, snapname); + if (!device) { + gf_log (this->name, GF_LOG_WARNING, "cannot copy the " + "snapshot device name (volname: %s, " + "snapname: %s)", volinfo->volname, snapname); + ret = -1; + goto out; + } + + glusterd_replace_slash_with_hyphen (device); + if (device[0] == '-') + device[0] = '/'; + + ret = snprintf (snap_mount, sizeof(snap_mount) - 1, + "%s/%s%s-brick", + GLUSTERD_DEFAULT_SNAPS_BRICK_DIR, + snapname, device); + snap_mount[ret] = '\0'; + + ret = glusterd_get_brick_root (brickinfo->path, &mnt_pt); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "could not get the root of" + "the brick path %s", brickinfo->path); + goto out; + } + + if (strncmp (brickinfo->path, mnt_pt, strlen (mnt_pt))) { + gf_log (this->name, GF_LOG_WARNING, "brick: %s brick mount: %s", + brickinfo->path, mnt_pt); + goto out; + } + + snap_brick_dir = &brickinfo->path[strlen (mnt_pt)]; + if (snap_brick_dir) + snap_brick_dir++; + + snprintf (snap_brick_path, sizeof (snap_brick_path), "%s/%s", + snap_mount, snap_brick_dir); + + ret = snprintf (snapmntname, sizeof(snapmntname) - 1, + "vol%ld.brick%ld", i+1, brick_count); + snapmntname[ret] = '\0'; + + tmpstr = gf_strdup (snap_brick_path); + if (!tmpstr) { + gf_log ("", GF_LOG_ERROR, "Out Of Memory"); + ret = -1; + goto out; + } + ret = dict_set_dynstr (rsp_dict, snapmntname, tmpstr); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Failed to set %s", + snap_mount); + GF_FREE (tmpstr); + goto out; + } + + ret = snprintf (snapbrckord, sizeof(snapbrckord) - 1, + "vol%ld.brick%ld.order", i+1, brick_count); + snapbrckord[ret] = '\0'; + + ret = dict_set_int64 (rsp_dict, snapbrckord, brick_order); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Failed to set brick order"); + goto out; + } + + brick_count++; + brick_order++; + } + memset (snapbrckcnt, '\0', sizeof(snapbrckcnt)); + ret = snprintf (snapbrckcnt, sizeof(snapbrckcnt) - 1, + "vol%ld_brickcount", i+1); + snapbrckcnt[ret] = '\0'; + + ret = dict_set_int64 (rsp_dict, snapbrckcnt, brick_count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Failed to set %s", + snapbrckcnt); + goto out; + } + + if (is_origin_glusterd (dict)) { + snap_volid = GF_CALLOC (1, sizeof(uuid_t), gf_common_mt_uuid_t); + if (!snap_volid) { + gf_log (this->name, GF_LOG_ERROR, + "Out Of Memory"); + ret = -1; + goto out; + } + + memset (snapvolidname, '\0', sizeof(snapvolidname)); + ret = snprintf (snapvolidname, sizeof(snapvolidname) - 1, + "vol%ld_volid", i+1); + snapvolidname[ret] = '\0'; + + uuid_generate (*snap_volid); + ret = dict_set_bin (dict, snapvolidname, snap_volid, sizeof(uuid_t)); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to set snap_volid"); + goto out; + } + } + } + + ret = dict_set_int64 (rsp_dict, "volcount", volume_count); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Failed to set volcount"); + goto out; } + + ret = 0; +out: + gf_log ("", GF_LOG_TRACE, "Returning %d", ret); + return ret; +} + +int +glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, + dict_t *rsp_dict) +{ + int snap_command = 0; + xlator_t *this = NULL; + int ret = -1; + + this = THIS; + + GF_ASSERT (this); + GF_ASSERT (dict); + GF_ASSERT (rsp_dict); //not sure if this is needed, verify. + + ret = dict_get_int32 (dict, "type", &snap_command); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "unable to get the type of " + "the snapshot command"); + goto out; + } + + switch (snap_command) { + case (GF_SNAP_OPTION_TYPE_CREATE): + ret = glusterd_snapshot_create_prevalidate (dict, op_errstr, + rsp_dict); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Snapshot create " + "pre-validation failed"); + goto out; + } + break; + + case (GF_SNAP_OPTION_TYPE_CONFIG): + ret = glusterd_snapshot_config_prevalidate (dict, op_errstr); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Snapshot config " + "pre-validation failed"); + goto out; + } + break; + + case GF_SNAP_OPTION_TYPE_RESTORE: + ret = glusterd_snapshot_restore_prevalidate (dict, op_errstr); + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "Snapshot restore " + "validation failed"); + goto out; + } + break; + default: + gf_log (this->name, GF_LOG_WARNING, "invalid snap command"); + goto out; + } + + ret = 0; out: return ret; } @@ -2257,12 +2669,13 @@ out: int32_t glusterd_snap_create (glusterd_volinfo_t *volinfo, glusterd_volinfo_t *snap_volinfo, - char *description, uuid_t cg_id) + char *description, uuid_t *cg_id) { glusterd_snap_t *snap = NULL; xlator_t *this = NULL; glusterd_conf_t *priv = NULL; int ret = -1; + uuid_t snap_uuid; this = THIS; priv = this->private; @@ -2285,9 +2698,10 @@ glusterd_snap_create (glusterd_volinfo_t *volinfo, if (description) snap->description = gf_strdup (description); snap->time_stamp = time (NULL); - uuid_copy (snap->snap_id, snap_volinfo->volume_id); - if (!uuid_is_null (cg_id)) - uuid_copy (snap->cg_id, cg_id); + uuid_generate (snap_uuid); + uuid_copy (snap->snap_id, snap_uuid); + if (cg_id) + uuid_copy (snap->cg_id, *cg_id); snap->snap_volume = snap_volinfo; strcpy (snap->snap_name, snap_volinfo->volname); //TODO: replace strcpy with strncpy @@ -2456,7 +2870,6 @@ glusterd_snap_brick_create (char *device, glusterd_volinfo_t *snap_volinfo, int32_t ret = -1; xlator_t *this = NULL; glusterd_conf_t *priv = NULL; - glusterd_brickinfo_t *snap_brickinfo = NULL; char snap_brick_mount_path[PATH_MAX] = {0, }; char *tmp = NULL; char *mnt_pt = NULL; @@ -2520,7 +2933,6 @@ glusterd_snap_brick_create (char *device, glusterd_volinfo_t *snap_volinfo, snprintf (snap_brick_path, sizeof (snap_brick_path), "%s/%s", snap_brick_mount_path, snap_brick_dir); - entry = glusterd_get_mnt_entry_info (mnt_pt, mtab); if (!entry) { ret = -1; @@ -2548,23 +2960,6 @@ glusterd_snap_brick_create (char *device, glusterd_volinfo_t *snap_volinfo, gf_log (this->name, GF_LOG_DEBUG, "mounting the snapshot " "logical device %s successful", device); - ret = glusterd_brickinfo_new (&snap_brickinfo); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, - "initializing the brick for the snap " - "volume failed (snapname: %s)", snap_volinfo->volname); - goto out; - } - - strcpy (snap_brickinfo->hostname, original_brickinfo->hostname); - strcpy (snap_brickinfo->path, snap_brick_path); - LOCK (&snap_volinfo->lock); - { - list_add_tail (&snap_brickinfo->brick_list, - &snap_volinfo->bricks); - } - UNLOCK (&snap_volinfo->lock); - ret = stat (snap_brick_path, &statbuf); if (ret) { gf_log (this->name, GF_LOG_WARNING, "stat of the brick %s" @@ -2572,7 +2967,7 @@ glusterd_snap_brick_create (char *device, glusterd_volinfo_t *snap_volinfo, snap_brick_mount_path, strerror (errno)); goto out; } - ret = sys_lsetxattr (snap_brickinfo->path, + ret = sys_lsetxattr (snap_brick_path, GF_XATTR_VOL_ID_KEY, snap_volinfo->volume_id, 16, XATTR_REPLACE); @@ -2580,7 +2975,7 @@ glusterd_snap_brick_create (char *device, glusterd_volinfo_t *snap_volinfo, gf_log (this->name, GF_LOG_ERROR, "Failed to set " "extended attribute %s on %s. Reason: " "%s, snap: %s", GF_XATTR_VOL_ID_KEY, - snap_brickinfo->path, strerror (errno), + snap_brick_path, strerror (errno), snap_volinfo->volname); goto out; } @@ -2591,8 +2986,6 @@ out: gf_log (this->name, GF_LOG_WARNING, "unmounting the snap brick" " mount %s", snap_brick_mount_path); umount (snap_brick_mount_path); - if (snap_brickinfo) - glusterd_brickinfo_delete (snap_brickinfo); } if (mtab) endmntent (mtab); @@ -2608,18 +3001,21 @@ out: */ int32_t glusterd_do_snap (glusterd_volinfo_t *volinfo, char *name, dict_t *dict, - gf_boolean_t cg, uuid_t cg_id) + gf_boolean_t cg, uuid_t *cg_id, int volcount, uuid_t snap_volid) { - int32_t ret = -1; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - char *device = NULL; - char snapname[PATH_MAX] = {0, }; - char tmp[2046] = {0, }; - glusterd_volinfo_t *snap_volume = NULL; - char *description = NULL; - uuid_t snap_uuid = {0, }; + char snapname[PATH_MAX] = ""; + char tmp[2046] = ""; + char *snap_brick_mount_path = ""; + char snapmntname[PATH_MAX] = ""; + char *device = NULL; + char *description = NULL; + glusterd_brickinfo_t *snap_brickinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *snap_volume = NULL; + int32_t ret = -1; + int32_t brick_count = 0; + xlator_t *this = NULL; this = THIS; GF_ASSERT (this); @@ -2637,8 +3033,45 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *name, dict_t *dict, ret = glusterd_volinfo_dup (volinfo, &snap_volume); strcpy (snap_volume->volname, snapname); snap_volume->is_snap_volume = _gf_true; - uuid_generate (snap_uuid); - uuid_copy (snap_volume->volume_id, snap_uuid); + uuid_copy (snap_volume->volume_id, snap_volid); + + /* Adding snap brickinfos to the snap volinfo */ + brick_count = 0; + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + snap_brickinfo = NULL; + device = NULL; + ret = glusterd_brickinfo_new (&snap_brickinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "initializing the brick for the snap " + "volume failed (snapname: %s)", snap_volume->volname); + goto out; + } + + memset (snapmntname, '\0', sizeof(snapmntname)); + ret = snprintf (snapmntname, sizeof(snapmntname) - 1, + "vol%d.brick%d", volcount, brick_count); + snapmntname[ret] = '\0'; + + ret = dict_get_ptr (dict, snapmntname, (void **)&snap_brick_mount_path); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to fetch " + "snap mount path (%s)", snapmntname); + GF_FREE (snap_brickinfo); + goto out; + } + + strcpy (snap_brickinfo->hostname, brickinfo->hostname); + strcpy (snap_brickinfo->path, snap_brick_mount_path); + uuid_copy (snap_brickinfo->uuid, brickinfo->uuid); + LOCK (&snap_volume->lock); + { + list_add_tail (&snap_brickinfo->brick_list, + &snap_volume->bricks); + } + UNLOCK (&snap_volume->lock); + brick_count++; + } list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { if (uuid_compare (brickinfo->uuid, MY_UUID)) { @@ -2665,9 +3098,7 @@ glusterd_do_snap (glusterd_volinfo_t *volinfo, char *name, dict_t *dict, if (ret) continue; - /*create the complete brick here and add it to the - volinfo - */ + /* create the complete brick here */ ret = glusterd_snap_brick_create (device, snap_volume, brickinfo); if (ret) { @@ -2830,14 +3261,16 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, char *name = NULL; char *volname = NULL; char *tmp = NULL; - char volname_buf[PATH_MAX] = {0, }; + char volname_buf[PATH_MAX] = ""; + char snapvolidname[PATH_MAX] = ""; xlator_t *this = NULL; glusterd_volinfo_t *volinfo = NULL; glusterd_snap_cg_t *cg = NULL; glusterd_conf_t *priv = NULL; - uuid_t cg_id; + uuid_t *cg_id = NULL; + uuid_t *snap_volid = NULL; glusterd_snap_t *snap = NULL; - char err_str[PATH_MAX] = {0, }; + char err_str[PATH_MAX] = ""; this = THIS; GF_ASSERT (this); @@ -2851,45 +3284,18 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, goto out; } - //snap-name should not be set if volume_count > 1 ret = dict_get_str (dict, "snap-name", &name); - if (volume_count > 1 && !ret) - GF_ASSERT (0); - - if (volume_count > 1) { - is_cg = _gf_true; - ret = dict_get_str (dict, "cg-name", &name); - uuid_generate (cg_id); - cg = glusterd_new_snap_cg_object (volume_count); - if (!cg) { - gf_log (this->name, GF_LOG_ERROR, - "cannot create the consistency" - " group %s", name); - goto out; - } - } else if (volume_count == 1) { - ret = dict_get_str (dict, "snap-name", &name); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Unable to fetch snap-name"); + goto out; } - if (!name) { - name = generate_snapname (volname, NULL, is_cg); - if (!name) { - gf_log (this->name, GF_LOG_ERROR, - "strdup of internal snapname" - " ((%s) failed for the " - "volume %s", name, - volname); - goto out; - } - /* If the user has not provided the snapname/cg-name, then - one is generated by glusterd itself. Put it into the - dict, so that cli displays the name of the snap/cg that - was created. - */ - if (is_cg) - ret = dict_set_str (rsp_dict, "cg-name", name); - else - ret = dict_set_str (rsp_dict, "snap-name", name); + ret = dict_get_bin (dict, "cg-id", (void **)&cg_id); + if (ret) + gf_log (this->name, GF_LOG_DEBUG, "Not a cg."); + else { + is_cg = _gf_true; + gf_log (this->name, GF_LOG_DEBUG, "cg-id = %s", uuid_utoa(*cg_id)); } for (i = 1; i < volume_count + 1; i++) { @@ -2931,11 +3337,22 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, } } + memset (snapvolidname, '\0', sizeof(snapvolidname)); + ret = snprintf (snapvolidname, sizeof(snapvolidname) - 1, + "vol%d_volid", i); + + ret = dict_get_bin (dict, snapvolidname, (void **)&snap_volid); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to fetch snap_volid"); + goto out; + } + /* TODO: Create a stub where the bricks are added parallely by worker threads so that the snap creating happens parallely. */ - ret = glusterd_do_snap (volinfo, tmp, dict, is_cg, cg_id); + ret = glusterd_do_snap (volinfo, tmp, dict, is_cg, cg_id, i, *snap_volid); if (ret) { gf_log (this->name, GF_LOG_WARNING, "taking the " "snapshot of the volume %s failed", volname); @@ -2953,7 +3370,7 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr, goto out; } - uuid_copy (cg->cg_id, cg_id); + uuid_copy (cg->cg_id, *cg_id); strncpy (cg->cg_name, name, sizeof (cg->cg_name)); ret = glusterd_add_snap_cg (priv, cg); if (ret) { @@ -3259,55 +3676,6 @@ out: return ret; } -int -glusterd_snapshot_prevalidate (dict_t *dict, char **op_errstr, - dict_t *rsp_dict) -{ - int snap_command = 0; - xlator_t *this = NULL; - int ret = -1; - - this = THIS; - - GF_ASSERT (this); - GF_ASSERT (dict); - GF_ASSERT (rsp_dict); //not sure if this is needed, verify. - - ret = dict_get_int32 (dict, "type", &snap_command); - if (ret) { - gf_log (this->name, GF_LOG_ERROR, "unable to get the type of " - "the snapshot command"); - goto out; - } - - switch (snap_command) { - case (GF_SNAP_OPTION_TYPE_CREATE): - ret = glusterd_snapshot_create_prevalidate (dict, op_errstr, - rsp_dict); - break; - - case (GF_SNAP_OPTION_TYPE_CONFIG): - ret = glusterd_snapshot_config_prevalidate (dict, op_errstr); - break; - - case GF_SNAP_OPTION_TYPE_RESTORE: - ret = glusterd_snapshot_restore_prevalidate (dict, op_errstr); - if (ret) { - gf_log (this->name, GF_LOG_WARNING, "Snapshot restore " - "validation failed"); - goto out; - } - break; - default: - gf_log (this->name, GF_LOG_WARNING, "invalid snap command"); - goto out; - } - -out: - gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); - return ret; -} - int glusterd_handle_snapshot_fn (rpcsvc_request_t *req) { @@ -3404,6 +3772,7 @@ glusterd_handle_snapshot_fn (rpcsvc_request_t *req) case GF_SNAP_OPTION_TYPE_CONFIG: ret = glusterd_mgmt_v3_initiate_all_phases (req, cli_op, dict); break; + case GF_SNAP_OPTION_TYPE_DELETE: case GF_SNAP_OPTION_TYPE_START: case GF_SNAP_OPTION_TYPE_STOP: case GF_SNAP_OPTION_TYPE_STATUS: -- cgit