From 35836d9ffe89e5891c91baeb3812974baa221441 Mon Sep 17 00:00:00 2001 From: Avra Sengupta Date: Mon, 19 Dec 2016 13:52:59 +0530 Subject: [PATCH 247/257] snapshot: Fix restore rollback to reassign snap volume ids to bricks Added further checks to ensure we do not go beyond prevalidate when trying to restore a snapshot which has a nfs-gansha conf file, in a cluster when nfs-ganesha is not enabled The error message for the particular scenario is: "Snapshot() has a nfs-ganesha export conf file. cluster.enable-shared-storage and nfs-ganesha should be enabled before restoring this snapshot." > Reviewed-on: http://review.gluster.org/16116 > Reviewed-by: Rajesh Joseph > Smoke: Gluster Build System > NetBSD-regression: NetBSD Build System > CentOS-regression: Gluster Build System Change-Id: I1b87e9907e0a5e162f26ef1ca89fe76e8da8610f BUG: 1403672 Signed-off-by: Avra Sengupta Reviewed-on: https://code.engineering.redhat.com/gerrit/93275 Reviewed-by: Jiffin Thottan Reviewed-by: Atin Mukherjee --- xlators/mgmt/glusterd/src/glusterd-errno.h | 1 + xlators/mgmt/glusterd/src/glusterd-ganesha.c | 32 ++++++ xlators/mgmt/glusterd/src/glusterd-messages.h | 19 +++- .../mgmt/glusterd/src/glusterd-snapshot-utils.c | 1 + xlators/mgmt/glusterd/src/glusterd-snapshot.c | 112 +++++++++++++++++++++ xlators/mgmt/glusterd/src/glusterd.h | 3 + 6 files changed, 163 insertions(+), 5 deletions(-) diff --git a/xlators/mgmt/glusterd/src/glusterd-errno.h b/xlators/mgmt/glusterd/src/glusterd-errno.h index 55d44a5..3301e44 100644 --- a/xlators/mgmt/glusterd/src/glusterd-errno.h +++ b/xlators/mgmt/glusterd/src/glusterd-errno.h @@ -27,6 +27,7 @@ enum glusterd_op_errno { EG_ISSNAP = 30813, /* Volume is a snap volume */ EG_GEOREPRUN = 30814, /* Geo-Replication is running */ EG_NOTTHINP = 30815, /* Bricks are not thinly provisioned */ + EG_NOGANESHA = 30816, /* Global nfs-ganesha is not enabled */ }; #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-ganesha.c b/xlators/mgmt/glusterd/src/glusterd-ganesha.c index 470d455..93c35c7 100644 --- a/xlators/mgmt/glusterd/src/glusterd-ganesha.c +++ b/xlators/mgmt/glusterd/src/glusterd-ganesha.c @@ -160,6 +160,38 @@ manage_service (char *action) " not recognized.", action); return ret; } + +/* + * Check if the cluster is a ganesha cluster or not * + */ +gf_boolean_t +glusterd_is_ganesha_cluster () { + int ret = -1; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + gf_boolean_t ret_bool = _gf_false; + + this = THIS; + GF_VALIDATE_OR_GOTO ("ganesha", this, out); + priv = this->private; + GF_VALIDATE_OR_GOTO (this->name, priv, out); + + ret = dict_get_str_boolean (priv->opts, + GLUSTERD_STORE_KEY_GANESHA_GLOBAL, + _gf_false); + if (ret == _gf_true) { + ret_bool = _gf_true; + gf_msg_debug (this->name, 0, + "nfs-ganesha is enabled for the cluster"); + } else + gf_msg_debug (this->name, 0, + "nfs-ganesha is disabled for the cluster"); + +out: + return ret_bool; + +} + /* Check if ganesha.enable is set to 'on', that checks if * a particular volume is exported via NFS-Ganesha */ gf_boolean_t diff --git a/xlators/mgmt/glusterd/src/glusterd-messages.h b/xlators/mgmt/glusterd/src/glusterd-messages.h index e39fb92..126a583 100644 --- a/xlators/mgmt/glusterd/src/glusterd-messages.h +++ b/xlators/mgmt/glusterd/src/glusterd-messages.h @@ -41,7 +41,7 @@ #define GLUSTERD_COMP_BASE GLFS_MSGID_GLUSTERD -#define GLFS_NUM_MESSAGES 587 +#define GLFS_NUM_MESSAGES 589 #define GLFS_MSGID_END (GLUSTERD_COMP_BASE + GLFS_NUM_MESSAGES + 1) /* Messaged with message IDs */ @@ -4728,7 +4728,7 @@ * @recommendation * */ -#define GD_MSG_BRICK_CLEANUP_SUCCESS (GLUSTERD_COMP_BASE + 584) +#define GD_MSG_BRICK_CLEANUP_SUCCESS (GLUSTERD_COMP_BASE + 585) /*! * @messageid @@ -4736,7 +4736,7 @@ * @recommendation * */ -#define GD_MSG_STATE_STR_GET_FAILED (GLUSTERD_COMP_BASE + 585) +#define GD_MSG_STATE_STR_GET_FAILED (GLUSTERD_COMP_BASE + 586) /*! * @messageid @@ -4744,7 +4744,7 @@ * @recommendedaction * */ -#define GD_MSG_RESET_BRICK_COMMIT_FORCE_REQ_RCVD (GLUSTERD_COMP_BASE + 586) +#define GD_MSG_RESET_BRICK_COMMIT_FORCE_REQ_RCVD (GLUSTERD_COMP_BASE + 587) /*! * @messageid @@ -4752,7 +4752,16 @@ * @recommendedaction * */ -#define GD_MSG_RESET_BRICK_CMD_FAIL (GLUSTERD_COMP_BASE + 587) +#define GD_MSG_RESET_BRICK_CMD_FAIL (GLUSTERD_COMP_BASE + 588) + +/*! + * @messageid + * @diagnosis + * @recommendedaction + * + */ +#define GD_MSG_NFS_GANESHA_DISABLED (GLUSTERD_COMP_BASE + 589) + /*------------*/ #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" #endif /* !_GLUSTERD_MESSAGES_H_ */ diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c index 4a3a2f7..26b2f73 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c @@ -3787,6 +3787,7 @@ glusterd_copy_nfs_ganesha_file (glusterd_volinfo_t *src_vol, GD_MSG_FILE_OP_FAILED, "Failed to open %s", dest ? src_path : dest_path); + ret = -1; goto out; } diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index 70595ef..47835a8 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -919,6 +919,76 @@ out: return ret; } +/* + * This function validates the particulat snapshot with respect to the current + * cluster. If the snapshot has ganesha enabled, and the cluster is not a nfs + * ganesha cluster, we fail the validation. Other scenarios where either the + * snapshot does not have ganesha enabled or it has and the cluster is a nfs + * ganesha cluster, we pass the validation + * + * @param snap snap object of the snapshot to be validated + * @return Negative value on Failure and 0 in success + */ +int32_t +glusterd_snapshot_validate_ganesha_conf (glusterd_snap_t *snap, + char **op_errstr, + uint32_t *op_errno) +{ + int ret = -1; + glusterd_volinfo_t *snap_vol = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO ("snapshot", this, out); + GF_VALIDATE_OR_GOTO (this->name, snap, out); + GF_VALIDATE_OR_GOTO (this->name, op_errstr, out); + GF_VALIDATE_OR_GOTO (this->name, op_errno, out); + + snap_vol = list_entry (snap->volumes.next, + glusterd_volinfo_t, vol_list); + + GF_VALIDATE_OR_GOTO (this->name, snap_vol, out); + + /* + * Check if the snapshot has ganesha enabled * + */ + if (glusterd_check_ganesha_export(snap_vol) == _gf_false) { + /* + * If the snapshot has not been exported via ganesha * + * then we can proceed. * + */ + ret = 0; + goto out; + } + + /* + * At this point we are certain that the snapshot has been exported * + * via ganesha. So we check if the cluster is a nfs-ganesha cluster * + * If it a nfs-ganesha cluster, then we proceed. Else we fail. * + */ + if (glusterd_is_ganesha_cluster() != _gf_true) { + ret = gf_asprintf (op_errstr, "Snapshot(%s) has a " + "nfs-ganesha export conf file. " + "cluster.enable-shared-storage and " + "nfs-ganesha should be enabled " + "before restoring this snapshot.", + snap->snapname); + *op_errno = EG_NOGANESHA; + if (ret < 0) { + goto out; + } + + gf_msg (this->name, GF_LOG_ERROR, EINVAL, + GD_MSG_NFS_GANESHA_DISABLED, "%s", *op_errstr); + ret = -1; + goto out; + } + + ret = 0; +out: + return ret; +} + /* This function is called before actual restore is taken place. This function * will validate whether the snapshot volumes are ready to be restored or not. * @@ -989,6 +1059,15 @@ glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr, goto out; } + ret = glusterd_snapshot_validate_ganesha_conf (snap, op_errstr, + op_errno); + if (ret) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_SNAPSHOT_OP_FAILED, + "ganesha conf validation failed."); + goto out; + } + ret = dict_set_str (rsp_dict, "snapname", snapname); if (ret) { gf_msg (this->name, GF_LOG_ERROR, 0, @@ -8844,6 +8923,7 @@ glusterd_snapshot_revert_partial_restored_vol (glusterd_volinfo_t *volinfo) int ret = 0; char pathname [PATH_MAX] = {0,}; char trash_path[PATH_MAX] = {0,}; + glusterd_brickinfo_t *brickinfo = NULL; glusterd_volinfo_t *reverted_vol = NULL; glusterd_volinfo_t *snap_vol = NULL; glusterd_volinfo_t *tmp_vol = NULL; @@ -8898,6 +8978,38 @@ glusterd_snapshot_revert_partial_restored_vol (glusterd_volinfo_t *volinfo) snapvol_list) { cds_list_add_tail (&snap_vol->snapvol_list, &reverted_vol->snap_volumes); + + cds_list_for_each_entry (brickinfo, &snap_vol->bricks, + brick_list) { + /* + * If the brick is not of this peer, or snapshot is * + * missed for the brick don't restore the xattr for it * + */ + if ((!gf_uuid_compare (brickinfo->uuid, MY_UUID)) && + (brickinfo->snap_status != -1)) { + /* + * We need to restore volume id of all snap * + * bricks to volume id of the snap volume. * + */ + ret = sys_lsetxattr (brickinfo->path, + GF_XATTR_VOL_ID_KEY, + snap_vol->volume_id, + sizeof (snap_vol->volume_id), + XATTR_REPLACE); + if (ret == -1) { + gf_msg (this->name, GF_LOG_ERROR, 0, + GD_MSG_SETXATTR_FAIL, + "Failed to set extended " + "attribute %s on %s. " + "Reason: %s, snap: %s", + GF_XATTR_VOL_ID_KEY, + brickinfo->path, + strerror (errno), + snap_vol->volname); + goto out; + } + } + } } /* Since we retrieved the volinfo from store now we don't diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index b926383..a21b0a1 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -1077,6 +1077,9 @@ int glusterd_op_stage_set_ganesha (dict_t *dict, char **op_errstr); int glusterd_op_set_ganesha (dict_t *dict, char **errstr); int ganesha_manage_export (dict_t *dict, char *value, char **op_errstr); int manage_export_config (char *volname, char *value, char **op_errstr); + +gf_boolean_t +glusterd_is_ganesha_cluster (); gf_boolean_t glusterd_check_ganesha_export (glusterd_volinfo_t *volinfo); int stop_ganesha (char **op_errstr); int tear_down_cluster (gf_boolean_t run_teardown); -- 2.9.3