summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-volume-ops.c')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-ops.c1102
1 files changed, 690 insertions, 412 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
index 85e7abba8..0d322b9ad 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
@@ -1,27 +1,21 @@
/*
- Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
+ Copyright (c) 2011-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
+#ifdef HAVE_BD_XLATOR
+#include <lvm2app.h>
+#endif
+
#include "common-utils.h"
#include "syscall.h"
#include "cli1-xdr.h"
@@ -36,20 +30,16 @@
#define glusterd_op_start_volume_args_get(dict, volname, flags) \
glusterd_op_stop_volume_args_get (dict, volname, flags)
+
int
-glusterd_handle_create_volume (rpcsvc_request_t *req)
+__glusterd_handle_create_volume (rpcsvc_request_t *req)
{
int32_t ret = -1;
gf_cli_req cli_req = {{0,}};
dict_t *dict = NULL;
- glusterd_brickinfo_t *brickinfo = NULL;
- char *brick = NULL;
char *bricks = NULL;
char *volname = NULL;
int brick_count = 0;
- char *tmpptr = NULL;
- int i = 0;
- char *brick_list = NULL;
void *cli_rsp = NULL;
char err_str[2048] = {0,};
gf_cli_rsp rsp = {0,};
@@ -58,29 +48,26 @@ glusterd_handle_create_volume (rpcsvc_request_t *req)
char *trans_type = NULL;
uuid_t volume_id = {0,};
uuid_t tmp_uuid = {0};
- glusterd_brickinfo_t *tmpbrkinfo = NULL;
- glusterd_volinfo_t tmpvolinfo = {{0},};
int32_t type = 0;
char *username = NULL;
char *password = NULL;
GF_ASSERT (req);
- INIT_LIST_HEAD (&tmpvolinfo.bricks);
-
this = THIS;
GF_ASSERT(this);
ret = -1;
- if (!xdr_to_generic (req->msg[0], &cli_req,
- (xdrproc_t)xdr_gf_cli_req)) {
- //failed to decode msg;
+ ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
+ if (ret < 0) {
req->rpc_err = GARBAGE_ARGS;
- snprintf (err_str, sizeof (err_str), "Garbage args received");
+ snprintf (err_str, sizeof (err_str), "Failed to decode request "
+ "received from cli");
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
- gf_log ("glusterd", GF_LOG_INFO, "Received create volume req");
+ gf_log (this->name, GF_LOG_DEBUG, "Received create volume req");
if (cli_req.dict.dict_len) {
/* Unserialize the dictionary */
@@ -90,11 +77,11 @@ glusterd_handle_create_volume (rpcsvc_request_t *req)
cli_req.dict.dict_len,
&dict);
if (ret < 0) {
- gf_log ("glusterd", GF_LOG_ERROR,
+ gf_log (this->name, GF_LOG_ERROR,
"failed to "
"unserialize req-buffer to dictionary");
snprintf (err_str, sizeof (err_str), "Unable to decode "
- "the buffer");
+ "the command");
goto out;
} else {
dict->extra_stdfree = cli_req.dict.dict_val;
@@ -104,47 +91,52 @@ glusterd_handle_create_volume (rpcsvc_request_t *req)
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume name");
snprintf (err_str, sizeof (err_str), "Unable to get volume "
"name");
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
- gf_cmd_log ("Volume create", "on volname: %s attempted", volname);
if ((ret = glusterd_check_volume_exists (volname))) {
- snprintf(err_str, 2048, "Volume %s already exists", volname);
- gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str);
+ snprintf (err_str, sizeof (err_str), "Volume %s already exists",
+ volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
ret = dict_get_int32 (dict, "count", &brick_count);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get count");
- snprintf (err_str, sizeof (err_str), "Unable to get volume "
- "brick count");
+ snprintf (err_str, sizeof (err_str), "Unable to get brick count"
+ " for volume %s", volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
ret = dict_get_int32 (dict, "type", &type);
- /*if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get type");
- snprintf (err_str, sizeof (err_str), "Unable to get volume "
- "type");
+ if (ret) {
+ snprintf (err_str, sizeof (err_str), "Unable to get type of "
+ "volume %s", volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
- }*/
+ }
ret = dict_get_str (dict, "transport", &trans_type);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get transport-type");
- snprintf (err_str, sizeof (err_str), "Unable to get volume "
- "transport-type");
+ snprintf (err_str, sizeof (err_str), "Unable to get "
+ "transport-type of volume %s", volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
ret = dict_get_str (dict, "bricks", &bricks);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get bricks");
- snprintf (err_str, sizeof (err_str), "Unable to get volume "
- "bricks");
+ snprintf (err_str, sizeof (err_str), "Unable to get bricks for "
+ "volume %s", volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
+ goto out;
+ }
+
+ if (!dict_get (dict, "force")) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get 'force' flag");
goto out;
}
@@ -152,116 +144,82 @@ glusterd_handle_create_volume (rpcsvc_request_t *req)
free_ptr = gf_strdup (uuid_utoa (volume_id));
ret = dict_set_dynstr (dict, "volume-id", free_ptr);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "unable to set volume-id");
snprintf (err_str, sizeof (err_str), "Unable to set volume "
- "id");
+ "id of volume %s", volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
free_ptr = NULL;
- if (bricks) {
- brick_list = gf_strdup (bricks);
- free_ptr = brick_list;
- }
-
- gf_cmd_log ("Volume create", "on volname: %s type:%s count:%d bricks:%s",
- volname, ((type == 0)? "DEFAULT":
- ((type == 1)? "STRIPE":"REPLICATE")), brick_count, bricks);
-
-
- while ( i < brick_count) {
- i++;
- brick= strtok_r (brick_list, " \n", &tmpptr);
- brick_list = tmpptr;
- ret = glusterd_brickinfo_from_brick (brick, &brickinfo);
- if (ret) {
- snprintf (err_str, sizeof (err_str), "Unable to get "
- "brick info from brick %s", brick);
- goto out;
- }
-
- ret = glusterd_new_brick_validate (brick, brickinfo, err_str,
- sizeof (err_str));
- if (ret)
- goto out;
- ret = glusterd_volume_brickinfo_get (brickinfo->uuid,
- brickinfo->hostname,
- brickinfo->path,
- &tmpvolinfo, &tmpbrkinfo,
- GF_PATH_PARTIAL);
- if (!ret) {
- ret = -1;
- snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s"
- " one of the bricks contain the other",
- tmpbrkinfo->hostname, tmpbrkinfo->path, brick);
- goto out;
- }
- list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks);
- brickinfo = NULL;
- }
-
/* generate internal username and password */
uuid_generate (tmp_uuid);
username = gf_strdup (uuid_utoa (tmp_uuid));
ret = dict_set_dynstr (dict, "internal-username", username);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set username for "
+ "volume %s", volname);
goto out;
+ }
uuid_generate (tmp_uuid);
password = gf_strdup (uuid_utoa (tmp_uuid));
ret = dict_set_dynstr (dict, "internal-password", password);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set password for "
+ "volume %s", volname);
goto out;
+ }
- ret = glusterd_op_begin (req, GD_OP_CREATE_VOLUME, dict);
- gf_cmd_log ("Volume create", "on volname: %s %s", volname,
- (ret != 0) ? "FAILED": "SUCCESS");
+ ret = glusterd_op_begin_synctask (req, GD_OP_CREATE_VOLUME, dict);
out:
if (ret) {
- if (dict)
- dict_unref (dict);
rsp.op_ret = -1;
rsp.op_errno = 0;
if (err_str[0] == '\0')
- snprintf (err_str, sizeof (err_str), "Operation failed");
+ snprintf (err_str, sizeof (err_str),
+ "Operation failed");
rsp.op_errstr = err_str;
cli_rsp = &rsp;
- glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL,
- (xdrproc_t)xdr_gf_cli_rsp);
-
+ glusterd_to_cli (req, cli_rsp, NULL, 0, NULL,
+ (xdrproc_t)xdr_gf_cli_rsp, dict);
ret = 0; //Client response sent, prevent second response
}
- if (free_ptr)
- GF_FREE(free_ptr);
-
- glusterd_volume_brickinfos_delete (&tmpvolinfo);
- if (brickinfo)
- glusterd_brickinfo_delete (brickinfo);
-
- glusterd_friend_sm ();
- glusterd_op_sm ();
+ GF_FREE(free_ptr);
return ret;
}
int
-glusterd_handle_cli_start_volume (rpcsvc_request_t *req)
+glusterd_handle_create_volume (rpcsvc_request_t *req)
+{
+ return glusterd_big_locked_handler (req,
+ __glusterd_handle_create_volume);
+}
+
+int
+__glusterd_handle_cli_start_volume (rpcsvc_request_t *req)
{
int32_t ret = -1;
gf_cli_req cli_req = {{0,}};
char *volname = NULL;
dict_t *dict = NULL;
glusterd_op_t cli_op = GD_OP_START_VOLUME;
+ char errstr[2048] = {0,};
+ xlator_t *this = NULL;
+ this = THIS;
+ GF_ASSERT (this);
GF_ASSERT (req);
- if (!xdr_to_generic (req->msg[0], &cli_req,
- (xdrproc_t)xdr_gf_cli_req)) {
- //failed to decode msg;
+ ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
+ if (ret < 0) {
+ snprintf (errstr, sizeof (errstr), "Failed to decode message "
+ "received from cli");
req->rpc_err = GARBAGE_ARGS;
+ gf_log (this->name, sizeof (errstr), "%s", errstr);
goto out;
}
@@ -273,59 +231,68 @@ glusterd_handle_cli_start_volume (rpcsvc_request_t *req)
cli_req.dict.dict_len,
&dict);
if (ret < 0) {
- gf_log (THIS->name, GF_LOG_ERROR,
+ gf_log (this->name, GF_LOG_ERROR,
"failed to "
"unserialize req-buffer to dictionary");
+ snprintf (errstr, sizeof (errstr), "Unable to decode "
+ "the command");
goto out;
}
}
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log (THIS->name, GF_LOG_ERROR, "dict get failed");
+ snprintf (errstr, sizeof (errstr), "Unable to get volume name");
+ gf_log (this->name, GF_LOG_ERROR, "%s", errstr);
goto out;
}
- gf_log ("glusterd", GF_LOG_INFO, "Received start vol req"
- "for volume %s", volname);
-
- ret = glusterd_op_begin (req, GD_OP_START_VOLUME, dict);
+ gf_log (this->name, GF_LOG_DEBUG, "Received start vol req"
+ " for volume %s", volname);
- gf_cmd_log ("volume start","on volname: %s %s", volname,
- ((ret == 0) ? "SUCCESS": "FAILED"));
+ ret = glusterd_op_begin_synctask (req, GD_OP_START_VOLUME, dict);
out:
- if (ret && dict)
- dict_unref (dict);
- if (cli_req.dict.dict_val)
- free (cli_req.dict.dict_val); //its malloced by xdr
+ free (cli_req.dict.dict_val); //its malloced by xdr
- glusterd_friend_sm ();
- glusterd_op_sm ();
-
- if (ret)
+ if (ret) {
+ if(errstr[0] == '\0')
+ snprintf (errstr, sizeof (errstr), "Operation failed");
ret = glusterd_op_send_cli_response (cli_op, ret, 0, req,
- NULL, "operation failed");
+ dict, errstr);
+ }
return ret;
}
+int
+glusterd_handle_cli_start_volume (rpcsvc_request_t *req)
+{
+ return glusterd_big_locked_handler (req,
+ __glusterd_handle_cli_start_volume);
+}
int
-glusterd_handle_cli_stop_volume (rpcsvc_request_t *req)
+__glusterd_handle_cli_stop_volume (rpcsvc_request_t *req)
{
int32_t ret = -1;
gf_cli_req cli_req = {{0,}};
char *dup_volname = NULL;
dict_t *dict = NULL;
glusterd_op_t cli_op = GD_OP_STOP_VOLUME;
+ xlator_t *this = NULL;
+ char err_str[2048] = {0,};
+ this = THIS;
+ GF_ASSERT (this);
GF_ASSERT (req);
- if (!xdr_to_generic (req->msg[0], &cli_req,
- (xdrproc_t)xdr_gf_cli_req)) {
- //failed to decode msg;
+ ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
+ if (ret < 0) {
+ snprintf (err_str, sizeof (err_str), "Failed to decode message "
+ "received from cli");
req->rpc_err = GARBAGE_ARGS;
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
if (cli_req.dict.dict_len) {
@@ -336,9 +303,11 @@ glusterd_handle_cli_stop_volume (rpcsvc_request_t *req)
cli_req.dict.dict_len,
&dict);
if (ret < 0) {
- gf_log ("glusterd", GF_LOG_ERROR,
+ gf_log (this->name, GF_LOG_ERROR,
"failed to "
"unserialize req-buffer to dictionary");
+ snprintf (err_str, sizeof (err_str), "Unable to decode "
+ "the command");
goto out;
}
}
@@ -346,48 +315,59 @@ glusterd_handle_cli_stop_volume (rpcsvc_request_t *req)
ret = dict_get_str (dict, "volname", &dup_volname);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume name");
+ snprintf (err_str, sizeof (err_str), "Failed to get volume "
+ "name");
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
- gf_log ("glusterd", GF_LOG_INFO, "Received stop vol req"
+ gf_log (this->name, GF_LOG_DEBUG, "Received stop vol req "
"for volume %s", dup_volname);
- ret = glusterd_op_begin (req, GD_OP_STOP_VOLUME, dict);
- gf_cmd_log ("Volume stop","on volname: %s %s", dup_volname,
- ((ret)?"FAILED":"SUCCESS"));
+ ret = glusterd_op_begin_synctask (req, GD_OP_STOP_VOLUME, dict);
out:
- if (cli_req.dict.dict_val)
- free (cli_req.dict.dict_val); //its malloced by xdr
-
- glusterd_friend_sm ();
- glusterd_op_sm ();
+ free (cli_req.dict.dict_val); //its malloced by xdr
if (ret) {
- if (dict)
- dict_unref (dict);
+ if (err_str[0] == '\0')
+ snprintf (err_str, sizeof (err_str),
+ "Operation failed");
ret = glusterd_op_send_cli_response (cli_op, ret, 0, req,
- NULL, "operation failed");
+ dict, err_str);
}
return ret;
}
int
-glusterd_handle_cli_delete_volume (rpcsvc_request_t *req)
+glusterd_handle_cli_stop_volume (rpcsvc_request_t *req)
+{
+ return glusterd_big_locked_handler (req,
+ __glusterd_handle_cli_stop_volume);
+}
+
+int
+__glusterd_handle_cli_delete_volume (rpcsvc_request_t *req)
{
int32_t ret = -1;
gf_cli_req cli_req = {{0,},};
glusterd_op_t cli_op = GD_OP_DELETE_VOLUME;
dict_t *dict = NULL;
char *volname = NULL;
+ char err_str[2048]= {0,};
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
GF_ASSERT (req);
- if (!xdr_to_generic (req->msg[0], &cli_req,
- (xdrproc_t)xdr_gf_cli_req)) {
- //failed to decode msg;
+ ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
+ if (ret < 0) {
+ snprintf (err_str, sizeof (err_str), "Failed to decode request "
+ "received from cli");
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
req->rpc_err = GARBAGE_ARGS;
goto out;
}
@@ -400,49 +380,52 @@ glusterd_handle_cli_delete_volume (rpcsvc_request_t *req)
cli_req.dict.dict_len,
&dict);
if (ret < 0) {
- gf_log (THIS->name, GF_LOG_ERROR,
+ gf_log (this->name, GF_LOG_ERROR,
"failed to "
"unserialize req-buffer to dictionary");
+ snprintf (err_str, sizeof (err_str), "Unable to decode "
+ "the command");
goto out;
}
}
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log (THIS->name, GF_LOG_ERROR,
- "Failed to get volname");
+ snprintf (err_str, sizeof (err_str), "Failed to get volume "
+ "name");
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
req->rpc_err = GARBAGE_ARGS;
goto out;
}
- gf_cmd_log ("Volume delete","on volname: %s attempted", volname);
-
- gf_log ("glusterd", GF_LOG_INFO, "Received delete vol req"
+ gf_log (this->name, GF_LOG_DEBUG, "Received delete vol req"
"for volume %s", volname);
- ret = glusterd_op_begin (req, GD_OP_DELETE_VOLUME, dict);
- gf_cmd_log ("Volume delete", "on volname: %s %s", volname,
- ((ret) ? "FAILED" : "SUCCESS"));
+ ret = glusterd_op_begin_synctask (req, GD_OP_DELETE_VOLUME, dict);
out:
- if (cli_req.dict.dict_val)
- free (cli_req.dict.dict_val); //its malloced by xdr
- if (ret && dict)
- dict_unref (dict);
-
- glusterd_friend_sm ();
- glusterd_op_sm ();
+ free (cli_req.dict.dict_val); //its malloced by xdr
if (ret) {
+ if (err_str[0] == '\0')
+ snprintf (err_str, sizeof (err_str),
+ "Operation failed");
ret = glusterd_op_send_cli_response (cli_op, ret, 0, req,
- NULL, "operation failed");
+ dict, err_str);
}
return ret;
}
int
-glusterd_handle_cli_heal_volume (rpcsvc_request_t *req)
+glusterd_handle_cli_delete_volume (rpcsvc_request_t *req)
+{
+ return glusterd_big_locked_handler (req,
+ __glusterd_handle_cli_delete_volume);
+}
+
+int
+__glusterd_handle_cli_heal_volume (rpcsvc_request_t *req)
{
int32_t ret = -1;
gf_cli_req cli_req = {{0,}};
@@ -451,18 +434,19 @@ glusterd_handle_cli_heal_volume (rpcsvc_request_t *req)
char *volname = NULL;
glusterd_volinfo_t *volinfo = NULL;
xlator_t *this = NULL;
- char *op_errstr = NULL;
+ char op_errstr[2048] = {0,};
GF_ASSERT (req);
- if (!xdr_to_generic (req->msg[0], &cli_req,
- (xdrproc_t)xdr_gf_cli_req)) {
+ ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
+ if (ret < 0) {
//failed to decode msg;
req->rpc_err = GARBAGE_ARGS;
goto out;
}
this = THIS;
+ GF_ASSERT (this);
if (cli_req.dict.dict_len) {
/* Unserialize the dictionary */
@@ -475,6 +459,8 @@ glusterd_handle_cli_heal_volume (rpcsvc_request_t *req)
gf_log (this->name, GF_LOG_ERROR,
"failed to "
"unserialize req-buffer to dictionary");
+ snprintf (op_errstr, sizeof (op_errstr),
+ "Unable to decode the command");
goto out;
} else {
dict->extra_stdfree = cli_req.dict.dict_val;
@@ -483,8 +469,9 @@ glusterd_handle_cli_heal_volume (rpcsvc_request_t *req)
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log (this->name, GF_LOG_ERROR, "failed to get volname");
- gf_asprintf (&op_errstr, "Unable to find volume name");
+ snprintf (op_errstr, sizeof (op_errstr), "Unable to find "
+ "volume name");
+ gf_log (this->name, GF_LOG_ERROR, "%s", op_errstr);
goto out;
}
@@ -493,7 +480,9 @@ glusterd_handle_cli_heal_volume (rpcsvc_request_t *req)
ret = glusterd_volinfo_find (volname, &volinfo);
if (ret) {
- gf_asprintf (&op_errstr, "Volume %s does not exist", volname);
+ snprintf (op_errstr, sizeof (op_errstr),
+ "Volume %s does not exist", volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", op_errstr);
goto out;
}
@@ -505,31 +494,29 @@ glusterd_handle_cli_heal_volume (rpcsvc_request_t *req)
if (ret)
goto out;
- ret = glusterd_op_begin (req, GD_OP_HEAL_VOLUME, dict);
-
- gf_cmd_log ("volume heal","on volname: %s %s", volname,
- ((ret == 0) ? "SUCCESS": "FAILED"));
+ ret = glusterd_op_begin_synctask (req, GD_OP_HEAL_VOLUME, dict);
out:
- if (ret && dict)
- dict_unref (dict);
-
- glusterd_friend_sm ();
- glusterd_op_sm ();
-
if (ret) {
- if (!op_errstr)
- op_errstr = gf_strdup ("operation failed");
+ if (op_errstr[0] == '\0')
+ snprintf (op_errstr, sizeof (op_errstr),
+ "operation failed");
ret = glusterd_op_send_cli_response (cli_op, ret, 0, req,
- NULL, op_errstr);
- GF_FREE (op_errstr);
+ dict, op_errstr);
}
return ret;
}
int
-glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req)
+glusterd_handle_cli_heal_volume (rpcsvc_request_t *req)
+{
+ return glusterd_big_locked_handler (req,
+ __glusterd_handle_cli_heal_volume);
+}
+
+int
+__glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req)
{
int32_t ret = -1;
gf_cli_req cli_req = {{0,}};
@@ -537,12 +524,18 @@ glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req)
char *options = NULL;
dict_t *dict = NULL;
int32_t option_cnt = 0;
+ glusterd_op_t cli_op = GD_OP_STATEDUMP_VOLUME;
+ char err_str[2048] = {0,};
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
GF_ASSERT (req);
ret = -1;
- if (!xdr_to_generic (req->msg[0], &cli_req,
- (xdrproc_t)xdr_gf_cli_req)) {
+ ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
+ if (ret < 0) {
req->rpc_err = GARBAGE_ARGS;
goto out;
}
@@ -554,50 +547,158 @@ glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req)
cli_req.dict.dict_len,
&dict);
if (ret < 0) {
- gf_log (THIS->name, GF_LOG_ERROR,
+ gf_log (this->name, GF_LOG_ERROR,
"failed to "
"unserialize req-buffer to dictionary");
+ snprintf (err_str, sizeof (err_str), "Unable to "
+ "decode the command");
goto out;
}
}
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log (THIS->name, GF_LOG_ERROR, "failed to get volname");
+ snprintf (err_str, sizeof (err_str), "Unable to get the volume "
+ "name");
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
ret = dict_get_str (dict, "options", &options);
if (ret) {
- gf_log (THIS->name, GF_LOG_ERROR, "failed to get options");
+ snprintf (err_str, sizeof (err_str), "Unable to get options");
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
ret = dict_get_int32 (dict, "option_cnt", &option_cnt);
if (ret) {
- gf_log (THIS->name, GF_LOG_ERROR, "failed to get option cnt");
+ snprintf (err_str , sizeof (err_str), "Unable to get option "
+ "count");
+ gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
goto out;
}
- gf_log ("glusterd", GF_LOG_INFO, "Received statedump request for "
+ gf_log (this->name, GF_LOG_INFO, "Received statedump request for "
"volume %s with options %s", volname, options);
- ret = glusterd_op_begin (req, GD_OP_STATEDUMP_VOLUME, dict);
-
- gf_cmd_log ("statedump", "on volume %s %s", volname,
- ((0 == ret) ? "SUCCEEDED" : "FAILED"));
+ ret = glusterd_op_begin_synctask (req, GD_OP_STATEDUMP_VOLUME, dict);
out:
- if (ret && dict)
- dict_unref (dict);
- if (cli_req.dict.dict_val)
- free (cli_req.dict.dict_val);
- glusterd_friend_sm ();
- glusterd_op_sm();
+ if (ret) {
+ if (err_str[0] == '\0')
+ snprintf (err_str, sizeof (err_str),
+ "Operation failed");
+ ret = glusterd_op_send_cli_response (cli_op, ret, 0, req,
+ dict, err_str);
+ }
+ free (cli_req.dict.dict_val);
return ret;
}
+int
+glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req)
+{
+ return glusterd_big_locked_handler (req,
+ __glusterd_handle_cli_statedump_volume);
+}
+
+#ifdef HAVE_BD_XLATOR
+/*
+ * Validates if given VG in the brick exists or not. Also checks if VG has
+ * GF_XATTR_VOL_ID_KEY tag set to avoid using same VG for multiple bricks.
+ * Tag is checked only during glusterd_op_stage_create_volume. Tag is set during
+ * glusterd_validate_and_create_brickpath().
+ * @brick - brick info, @check_tag - check for VG tag or not
+ * @msg - Error message to return to caller
+ */
+int
+glusterd_is_valid_vg (glusterd_brickinfo_t *brick, int check_tag, char *msg)
+{
+ lvm_t handle = NULL;
+ vg_t vg = NULL;
+ char *vg_name = NULL;
+ int retval = 0;
+ char *p = NULL;
+ char *ptr = NULL;
+ struct dm_list *dm_lvlist = NULL;
+ struct dm_list *dm_seglist = NULL;
+ struct lvm_lv_list *lv_list = NULL;
+ struct lvm_property_value prop = {0, };
+ struct lvm_lvseg_list *seglist = NULL;
+ struct dm_list *taglist = NULL;
+ struct lvm_str_list *strl = NULL;
+
+ handle = lvm_init (NULL);
+ if (!handle) {
+ sprintf (msg, "lvm_init failed, could not validate vg");
+ return -1;
+ }
+ if (*brick->vg == '\0') { /* BD xlator has vg in brick->path */
+ p = gf_strdup (brick->path);
+ vg_name = strtok_r (p, "/", &ptr);
+ } else
+ vg_name = brick->vg;
+
+ vg = lvm_vg_open (handle, vg_name, "r", 0);
+ if (!vg) {
+ sprintf (msg, "no such vg: %s", vg_name);
+ retval = -1;
+ goto out;
+ }
+ if (!check_tag)
+ goto next;
+
+ taglist = lvm_vg_get_tags (vg);
+ if (!taglist)
+ goto next;
+
+ dm_list_iterate_items (strl, taglist) {
+ if (!strncmp(strl->str, GF_XATTR_VOL_ID_KEY,
+ strlen (GF_XATTR_VOL_ID_KEY))) {
+ sprintf (msg, "VG %s is already part of"
+ " a brick", vg_name);
+ retval = -1;
+ goto out;
+ }
+ }
+next:
+
+ brick->caps = CAPS_BD | CAPS_OFFLOAD_COPY | CAPS_OFFLOAD_SNAPSHOT;
+
+ dm_lvlist = lvm_vg_list_lvs (vg);
+ if (!dm_lvlist)
+ goto out;
+
+ dm_list_iterate_items (lv_list, dm_lvlist) {
+ dm_seglist = lvm_lv_list_lvsegs (lv_list->lv);
+ dm_list_iterate_items (seglist, dm_seglist) {
+ prop = lvm_lvseg_get_property (seglist->lvseg,
+ "segtype");
+ if (!prop.is_valid || !prop.value.string)
+ continue;
+ if (!strcmp (prop.value.string, "thin-pool")) {
+ brick->caps |= CAPS_THIN;
+ gf_log (THIS->name, GF_LOG_INFO, "Thin Pool "
+ "\"%s\" will be used for thin LVs",
+ lvm_lv_get_name (lv_list->lv));
+ break;
+ }
+ }
+ }
+
+ retval = 0;
+out:
+ if (vg)
+ lvm_vg_close (vg);
+ lvm_quit (handle);
+ if (p)
+ GF_FREE (p);
+ return retval;
+}
+#endif
+
/* op-sm */
int
glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr)
@@ -613,73 +714,68 @@ glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr)
int32_t i = 0;
char *brick = NULL;
char *tmpptr = NULL;
- char cmd_str[1024];
xlator_t *this = NULL;
glusterd_conf_t *priv = NULL;
char msg[2048] = {0};
uuid_t volume_uuid;
char *volume_uuid_str;
+ gf_boolean_t is_force = _gf_false;
this = THIS;
- if (!this) {
- gf_log ("glusterd", GF_LOG_ERROR,
- "this is NULL");
- goto out;
- }
-
+ GF_ASSERT (this);
priv = this->private;
- if (!priv) {
- gf_log ("glusterd", GF_LOG_ERROR,
- "priv is NULL");
- goto out;
- }
+ GF_ASSERT (priv);
ret = dict_get_str (dict, "volname", &volname);
-
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume name");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name");
goto out;
}
exists = glusterd_check_volume_exists (volname);
-
if (exists) {
snprintf (msg, sizeof (msg), "Volume %s already exists",
volname);
- gf_log ("", GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
ret = -1;
goto out;
} else {
ret = 0;
}
+
ret = dict_get_int32 (dict, "count", &brick_count);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get count");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get brick count "
+ "for volume %s", volname);
goto out;
}
+
ret = dict_get_str (dict, "volume-id", &volume_uuid_str);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume id");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get volume id of "
+ "volume %s", volname);
goto out;
}
+
ret = uuid_parse (volume_uuid_str, volume_uuid);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to parse volume id");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to parse volume id of"
+ " volume %s", volname);
goto out;
}
ret = dict_get_str (dict, "bricks", &bricks);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get bricks");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get bricks for "
+ "volume %s", volname);
goto out;
}
+ is_force = dict_get_str_boolean (dict, "force", _gf_false);
+
if (bricks) {
brick_list = gf_strdup (bricks);
if (!brick_list) {
ret = -1;
- gf_log ("", GF_LOG_ERROR, "Out of memory");
goto out;
} else {
free_ptr = brick_list;
@@ -695,30 +791,38 @@ glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr)
!glusterd_is_valid_volfpath (volname, brick)) {
snprintf (msg, sizeof (msg), "brick path %s is too "
"long.", brick);
- gf_log ("", GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
-
ret = -1;
goto out;
}
- ret = glusterd_brickinfo_from_brick (brick, &brick_info);
+ ret = glusterd_brickinfo_new_from_brick (brick, &brick_info);
+ if (ret)
+ goto out;
+
+ ret = glusterd_new_brick_validate (brick, brick_info, msg,
+ sizeof (msg));
if (ret)
goto out;
- snprintf (cmd_str, 1024, "%s", brick_info->path);
+
ret = glusterd_resolve_brick (brick_info);
if (ret) {
- gf_log ("glusterd", GF_LOG_ERROR, "cannot resolve "
- "brick: %s:%s", brick_info->hostname,
- brick_info->path);
+ gf_log (this->name, GF_LOG_ERROR, FMTSTR_RESOLVE_BRICK,
+ brick_info->hostname, brick_info->path);
goto out;
}
- if (!uuid_compare (brick_info->uuid, priv->uuid)) {
- ret = glusterd_brick_create_path (brick_info->hostname,
- brick_info->path,
- volume_uuid,
- 0777, op_errstr);
+ if (!uuid_compare (brick_info->uuid, MY_UUID)) {
+
+#ifdef HAVE_BD_XLATOR
+ if (brick_info->vg[0]) {
+ ret = glusterd_is_valid_vg (brick_info, 1, msg);
+ if (ret)
+ goto out;
+ }
+#endif
+ ret = glusterd_validate_and_create_brickpath (brick_info,
+ volume_uuid, op_errstr,
+ is_force);
if (ret)
goto out;
brick_list = tmpptr;
@@ -727,11 +831,15 @@ glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr)
brick_info = NULL;
}
out:
- if (free_ptr)
- GF_FREE (free_ptr);
+ GF_FREE (free_ptr);
if (brick_info)
glusterd_brickinfo_delete (brick_info);
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
+
+ if (msg[0] != '\0') {
+ gf_log (this->name, GF_LOG_ERROR, "%s", msg);
+ *op_errstr = gf_strdup (msg);
+ }
+ gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
@@ -740,19 +848,23 @@ int
glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, int *flags)
{
int ret = -1;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
if (!dict || !volname || !flags)
goto out;
ret = dict_get_str (dict, "volname", volname);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume name");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name");
goto out;
}
ret = dict_get_int32 (dict, "flags", flags);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get flags");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get flags");
goto out;
}
out:
@@ -801,14 +913,16 @@ glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr)
glusterd_brickinfo_t *brickinfo = NULL;
char msg[2048];
glusterd_conf_t *priv = NULL;
+ xlator_t *this = NULL;
+ uuid_t volume_id = {0,};
+ char volid[50] = {0,};
+ char xattr_volid[50] = {0,};
+ int caps = 0;
- priv = THIS->private;
- if (!priv) {
- gf_log ("glusterd", GF_LOG_ERROR,
- "priv is NULL");
- ret = -1;
- goto out;
- }
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
ret = glusterd_op_start_volume_args_get (dict, &volname, &flags);
if (ret)
@@ -817,63 +931,110 @@ glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr)
exists = glusterd_check_volume_exists (volname);
if (!exists) {
- snprintf (msg, sizeof (msg), "Volume %s does not exist", volname);
- gf_log ("", GF_LOG_ERROR, "%s",
- msg);
- *op_errstr = gf_strdup (msg);
+ snprintf (msg, sizeof (msg), FMTSTR_CHECK_VOL_EXISTS, volname);
ret = -1;
- } else {
- ret = 0;
+ goto out;
}
ret = glusterd_volinfo_find (volname, &volinfo);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, FMTSTR_CHECK_VOL_EXISTS,
+ volname);
goto out;
+ }
ret = glusterd_validate_volume_id (dict, volinfo);
if (ret)
goto out;
+ if (!(flags & GF_CLI_FLAG_OP_FORCE)) {
+ if (glusterd_is_volume_started (volinfo)) {
+ snprintf (msg, sizeof (msg), "Volume %s already "
+ "started", volname);
+ ret = -1;
+ goto out;
+ }
+ }
+
list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
ret = glusterd_resolve_brick (brickinfo);
if (ret) {
- gf_log ("", GF_LOG_ERROR,
- "Unable to resolve brick %s:%s",
+ gf_log (this->name, GF_LOG_ERROR, FMTSTR_RESOLVE_BRICK,
brickinfo->hostname, brickinfo->path);
goto out;
}
- /* we should not be creating the directory if 'force' option
- is not given. This may lead to issues where the actual data
- disk is not mounted after a machine reboot, but because
- 'glusterd' restarts the processes, the export directories
- can be automatically created and brick would start */
- if ((flags & GF_CLI_FLAG_OP_FORCE) &&
- !uuid_compare (brickinfo->uuid, priv->uuid)) {
- ret = glusterd_brick_create_path (brickinfo->hostname,
- brickinfo->path,
- volinfo->volume_id,
- 0777, op_errstr);
- if (ret)
- goto out;
- }
+ if (uuid_compare (brickinfo->uuid, MY_UUID))
+ continue;
- if (!(flags & GF_CLI_FLAG_OP_FORCE)) {
- if (glusterd_is_volume_started (volinfo)) {
- snprintf (msg, sizeof (msg), "Volume %s already"
- " started", volname);
- gf_log ("glusterd", GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
- ret = -1;
+ ret = gf_lstat_dir (brickinfo->path, NULL);
+ if (ret && (flags & GF_CLI_FLAG_OP_FORCE)) {
+ continue;
+ } else if (ret) {
+ snprintf (msg, sizeof (msg), "Failed to find "
+ "brick directory %s for volume %s. "
+ "Reason : %s", brickinfo->path,
+ volname, strerror (errno));
+ goto out;
+ }
+ ret = sys_lgetxattr (brickinfo->path, GF_XATTR_VOL_ID_KEY,
+ volume_id, 16);
+ if (ret < 0 && (!(flags & GF_CLI_FLAG_OP_FORCE))) {
+ snprintf (msg, sizeof (msg), "Failed to get "
+ "extended attribute %s for brick dir %s. "
+ "Reason : %s", GF_XATTR_VOL_ID_KEY,
+ brickinfo->path, strerror (errno));
+ ret = -1;
+ goto out;
+ } else if (ret < 0) {
+ ret = sys_lsetxattr (brickinfo->path,
+ GF_XATTR_VOL_ID_KEY,
+ volinfo->volume_id, 16,
+ XATTR_CREATE);
+ if (ret) {
+ snprintf (msg, sizeof (msg), "Failed to set "
+ "extended attribute %s on %s. Reason: "
+ "%s", GF_XATTR_VOL_ID_KEY,
+ brickinfo->path, strerror (errno));
goto out;
+ } else {
+ continue;
}
}
+ if (uuid_compare (volinfo->volume_id, volume_id)) {
+ snprintf (msg, sizeof (msg), "Volume id mismatch for "
+ "brick %s:%s. Expected volume id %s, "
+ "volume id %s found", brickinfo->hostname,
+ brickinfo->path,
+ uuid_utoa_r (volinfo->volume_id, volid),
+ uuid_utoa_r (volume_id, xattr_volid));
+ ret = -1;
+ goto out;
+ }
+#ifdef HAVE_BD_XLATOR
+ if (brickinfo->vg[0])
+ caps = CAPS_BD | CAPS_THIN |
+ CAPS_OFFLOAD_COPY | CAPS_OFFLOAD_SNAPSHOT;
+ /* Check for VG/thin pool if its BD volume */
+ if (brickinfo->vg[0]) {
+ ret = glusterd_is_valid_vg (brickinfo, 0, msg);
+ if (ret)
+ goto out;
+ /* if anyone of the brick does not have thin support,
+ disable it for entire volume */
+ caps &= brickinfo->caps;
+ } else
+ caps = 0;
+#endif
}
+ volinfo->caps = caps;
ret = 0;
out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
-
+ if (ret && (msg[0] != '\0')) {
+ gf_log (this->name, GF_LOG_ERROR, "%s", msg);
+ *op_errstr = gf_strdup (msg);
+ }
return ret;
}
@@ -887,7 +1048,10 @@ glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr)
gf_boolean_t is_run = _gf_false;
glusterd_volinfo_t *volinfo = NULL;
char msg[2048] = {0};
+ xlator_t *this = NULL;
+ this = THIS;
+ GF_ASSERT (this);
ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags);
if (ret)
@@ -896,18 +1060,18 @@ glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr)
exists = glusterd_check_volume_exists (volname);
if (!exists) {
- snprintf (msg, sizeof (msg), "Volume %s does not exist", volname);
- gf_log ("", GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
+ snprintf (msg, sizeof (msg), FMTSTR_CHECK_VOL_EXISTS, volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", msg);
ret = -1;
goto out;
- } else {
- ret = 0;
}
ret = glusterd_volinfo_find (volname, &volinfo);
- if (ret)
+ if (ret) {
+ snprintf (msg, sizeof (msg), FMTSTR_CHECK_VOL_EXISTS, volname);
+ gf_log (this->name, GF_LOG_ERROR, "%s", msg);
goto out;
+ }
ret = glusterd_validate_volume_id (dict, volinfo);
if (ret)
@@ -920,25 +1084,22 @@ glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr)
if (_gf_false == glusterd_is_volume_started (volinfo)) {
snprintf (msg, sizeof(msg), "Volume %s "
"is not in the started state", volname);
- gf_log ("", GF_LOG_ERROR, "Volume %s "
- "has not been started", volname);
- *op_errstr = gf_strdup (msg);
+ gf_log (this->name, GF_LOG_ERROR, "%s", msg);
ret = -1;
goto out;
}
ret = glusterd_check_gsync_running (volinfo, &is_run);
if (ret && (is_run == _gf_false))
- gf_log ("", GF_LOG_WARNING, "Unable to get the status"
+ gf_log (this->name, GF_LOG_WARNING, "Unable to get the status"
" of active "GEOREP" session");
if (is_run) {
- gf_log ("", GF_LOG_WARNING, GEOREP" sessions active"
+ gf_log (this->name, GF_LOG_WARNING, GEOREP" sessions active"
"for the volume %s ", volname);
snprintf (msg, sizeof(msg), GEOREP" sessions are active "
"for the volume '%s'.\nUse 'volume "GEOREP" "
- "status' command for more info. Use 'force'"
- "option to ignore and stop stop the volume",
+ "status' command for more info. Use 'force' "
+ "option to ignore and stop the volume.",
volname);
- *op_errstr = gf_strdup (msg);
ret = -1;
goto out;
}
@@ -947,8 +1108,8 @@ glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr)
snprintf (msg, sizeof (msg), "Replace brick is in progress on "
"volume %s. Please retry after replace-brick "
"operation is committed or aborted", volname);
- gf_log (THIS->name, GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
+ gf_log (this->name, GF_LOG_WARNING, "replace-brick in progress "
+ "on volume %s", volname);
ret = -1;
goto out;
}
@@ -956,23 +1117,22 @@ glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr)
if (glusterd_is_defrag_on (volinfo)) {
snprintf (msg, sizeof(msg), "rebalance session is "
"in progress for the volume '%s'", volname);
- gf_log (THIS->name, GF_LOG_WARNING, "%s", msg);
- *op_errstr = gf_strdup (msg);
+ gf_log (this->name, GF_LOG_WARNING, "%s", msg);
ret = -1;
goto out;
}
- if (volinfo->rb_status != GF_RB_STATUS_NONE) {
+ if (volinfo->rep_brick.rb_status != GF_RB_STATUS_NONE) {
snprintf (msg, sizeof(msg), "replace-brick session is "
"in progress for the volume '%s'", volname);
- gf_log (THIS->name, GF_LOG_WARNING, "%s", msg);
- *op_errstr = gf_strdup (msg);
+ gf_log (this->name, GF_LOG_WARNING, "%s", msg);
ret = -1;
goto out;
}
out:
-
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
+ if (msg[0] != 0)
+ *op_errstr = gf_strdup (msg);
+ gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
@@ -985,21 +1145,20 @@ glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr)
gf_boolean_t exists = _gf_false;
glusterd_volinfo_t *volinfo = NULL;
char msg[2048] = {0};
+ xlator_t *this = NULL;
- ret = dict_get_str (dict, "volname", &volname);
+ this = THIS;
+ GF_ASSERT (this);
+ ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume name");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name");
goto out;
}
exists = glusterd_check_volume_exists (volname);
-
if (!exists) {
- snprintf (msg, sizeof (msg), "Volume %s does not exist",
- volname);
- gf_log ("", GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
+ snprintf (msg, sizeof (msg), FMTSTR_CHECK_VOL_EXISTS, volname);
ret = -1;
goto out;
} else {
@@ -1007,9 +1166,10 @@ glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr)
}
ret = glusterd_volinfo_find (volname, &volinfo);
-
- if (ret)
+ if (ret) {
+ snprintf (msg, sizeof (msg), FMTSTR_CHECK_VOL_EXISTS, volname);
goto out;
+ }
ret = glusterd_validate_volume_id (dict, volinfo);
if (ret)
@@ -1019,8 +1179,16 @@ glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr)
snprintf (msg, sizeof (msg), "Volume %s has been started."
"Volume needs to be stopped before deletion.",
volname);
- gf_log ("", GF_LOG_ERROR, "%s", msg);
- *op_errstr = gf_strdup (msg);
+ ret = -1;
+ goto out;
+ }
+
+ if (volinfo->snap_count > 0 || !list_empty(&volinfo->snap_volumes)) {
+ snprintf (msg, sizeof (msg), "Cannot delete Volume %s ,"
+ "as it has %ld snapshots. "
+ "To delete the volume, "
+ "first delete all the snapshots under it.",
+ volname, volinfo->snap_count);
ret = -1;
goto out;
}
@@ -1028,7 +1196,11 @@ glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr)
ret = 0;
out:
- gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
+ if (msg[0] != '\0') {
+ gf_log (this->name, GF_LOG_ERROR, "%s", msg);
+ *op_errstr = gf_strdup (msg);
+ }
+ gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
@@ -1044,11 +1216,13 @@ glusterd_op_stage_heal_volume (dict_t *dict, char **op_errstr)
glusterd_conf_t *priv = NULL;
dict_t *opt_dict = NULL;
gf_xl_afr_op_t heal_op = GF_AFR_OP_INVALID;
+ xlator_t *this = NULL;
- priv = THIS->private;
+ this = THIS;
+ priv = this->private;
if (!priv) {
ret = -1;
- gf_log (THIS->name, GF_LOG_ERROR,
+ gf_log (this->name, GF_LOG_ERROR,
"priv is NULL");
goto out;
}
@@ -1063,7 +1237,7 @@ glusterd_op_stage_heal_volume (dict_t *dict, char **op_errstr)
if (ret) {
ret = -1;
snprintf (msg, sizeof (msg), "Volume %s does not exist", volname);
- gf_log (THIS->name, GF_LOG_ERROR, "%s", msg);
+ gf_log (this->name, GF_LOG_ERROR, "%s", msg);
*op_errstr = gf_strdup (msg);
goto out;
}
@@ -1077,7 +1251,7 @@ glusterd_op_stage_heal_volume (dict_t *dict, char **op_errstr)
snprintf (msg, sizeof (msg), "Volume %s is not of type "
"replicate", volname);
*op_errstr = gf_strdup (msg);
- gf_log (THIS->name, GF_LOG_WARNING, "%s", msg);
+ gf_log (this->name, GF_LOG_WARNING, "%s", msg);
goto out;
}
@@ -1103,29 +1277,37 @@ glusterd_op_stage_heal_volume (dict_t *dict, char **op_errstr)
snprintf (msg, sizeof (msg), "Self-heal-daemon is "
"disabled. Heal will not be triggered on volume %s",
volname);
- gf_log (THIS->name, GF_LOG_WARNING, "%s", msg);
- *op_errstr = gf_strdup (msg);
- goto out;
- }
-
- if (!glusterd_nodesvc_is_running ("glustershd")) {
- ret = -1;
- snprintf (msg, sizeof (msg), "Self-heal daemon is not "
- "running. Check self-heal daemon log file.");
+ gf_log (this->name, GF_LOG_WARNING, "%s", msg);
*op_errstr = gf_strdup (msg);
- gf_log (THIS->name, GF_LOG_WARNING, "%s", msg);
goto out;
}
ret = dict_get_int32 (dict, "heal-op", (int32_t*)&heal_op);
if (ret || (heal_op == GF_AFR_OP_INVALID)) {
ret = -1;
- snprintf (msg, sizeof (msg), "Invalid heal-op");
- *op_errstr = gf_strdup (msg);
- gf_log (THIS->name, GF_LOG_WARNING, "%s", msg);
+ *op_errstr = gf_strdup("Invalid heal-op");
+ gf_log (this->name, GF_LOG_WARNING, "%s", "Invalid heal-op");
goto out;
}
+ switch (heal_op) {
+ case GF_AFR_OP_INDEX_SUMMARY:
+ case GF_AFR_OP_STATISTICS_HEAL_COUNT:
+ case GF_AFR_OP_STATISTICS_HEAL_COUNT_PER_REPLICA:
+ break;
+ default:
+ if (!glusterd_is_nodesvc_online("glustershd")){
+ ret = -1;
+ *op_errstr = gf_strdup ("Self-heal daemon is "
+ "not running. Check self-heal "
+ "daemon log file.");
+ gf_log (this->name, GF_LOG_WARNING, "%s",
+ "Self-heal daemon is not running."
+ "Check self-heal daemon log file.");
+ goto out;
+ }
+ }
+
ret = 0;
out:
gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
@@ -1247,7 +1429,6 @@ out:
return ret;
}
-
int
glusterd_op_create_volume (dict_t *dict, char **op_errstr)
{
@@ -1269,6 +1450,8 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
char *str = NULL;
char *username = NULL;
char *password = NULL;
+ int caps = 0;
+ char msg[1024] __attribute__((unused)) = {0, };
this = THIS;
GF_ASSERT (this);
@@ -1280,15 +1463,14 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
- "Unable to allocate memory");
+ "Unable to allocate memory for volinfo");
goto out;
}
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log (this->name, GF_LOG_ERROR,
- "Unable to get volume name");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name");
goto out;
}
@@ -1297,13 +1479,15 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
ret = dict_get_int32 (dict, "type", &volinfo->type);
if (ret) {
- gf_log (this->name, GF_LOG_ERROR, "Unable to get type");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get type of volume"
+ " %s", volname);
goto out;
}
ret = dict_get_int32 (dict, "count", &volinfo->brick_count);
if (ret) {
- gf_log (this->name, GF_LOG_ERROR, "Unable to get count");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get brick count of"
+ " volume %s", volname);
goto out;
}
@@ -1317,7 +1501,8 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
ret = dict_get_str (dict, "bricks", &bricks);
if (ret) {
- gf_log (this->name, GF_LOG_ERROR, "Unable to get bricks");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get bricks for "
+ "volume %s", volname);
goto out;
}
@@ -1329,28 +1514,44 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
if (GF_CLUSTER_TYPE_REPLICATE == volinfo->type) {
ret = dict_get_int32 (dict, "replica-count",
&volinfo->replica_count);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "replica count for volume %s", volname);
goto out;
+ }
} else if (GF_CLUSTER_TYPE_STRIPE == volinfo->type) {
ret = dict_get_int32 (dict, "stripe-count",
&volinfo->stripe_count);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get stripe"
+ " count for volume %s", volname);
goto out;
+ }
} else if (GF_CLUSTER_TYPE_STRIPE_REPLICATE == volinfo->type) {
ret = dict_get_int32 (dict, "stripe-count",
&volinfo->stripe_count);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get stripe"
+ " count for volume %s", volname);
goto out;
+ }
ret = dict_get_int32 (dict, "replica-count",
&volinfo->replica_count);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "replica count for volume %s", volname);
goto out;
+ }
}
/* dist-leaf-count is the count of brick nodes for a given
subvolume of distribute */
- volinfo->dist_leaf_count = (volinfo->stripe_count *
- volinfo->replica_count);
+ volinfo->dist_leaf_count = glusterd_get_dist_leaf_count (volinfo);
+
+ /* subvol_count is the count of number of subvolumes present
+ for a given distribute volume */
+ volinfo->subvol_count = (volinfo->brick_count /
+ volinfo->dist_leaf_count);
/* Keep sub-count same as earlier, for the sake of backward
compatibility */
@@ -1360,27 +1561,28 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
ret = dict_get_str (dict, "transport", &trans_type);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
- "Unable to get transport");
+ "Unable to get transport type of volume %s", volname);
goto out;
}
ret = dict_get_str (dict, "volume-id", &str);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
- "Unable to get volume-id");
+ "Unable to get volume-id of volume %s", volname);
goto out;
}
ret = uuid_parse (str, volinfo->volume_id);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
- "unable to parse uuid %s", str);
+ "unable to parse uuid %s of volume %s", str, volname);
goto out;
}
ret = dict_get_str (dict, "internal-username", &username);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
- "unable to get internal username");
+ "unable to get internal username of volume %s",
+ volname);
goto out;
}
glusterd_auth_set_username (volinfo, username);
@@ -1388,7 +1590,8 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
ret = dict_get_str (dict, "internal-password", &password);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
- "unable to get internal password");
+ "unable to get internal password of volume %s",
+ volname);
goto out;
}
glusterd_auth_set_password (volinfo, password);
@@ -1411,20 +1614,49 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
if (count)
brick = strtok_r (brick_list+1, " \n", &saveptr);
+ caps = CAPS_BD | CAPS_THIN | CAPS_OFFLOAD_COPY | CAPS_OFFLOAD_SNAPSHOT;
while ( i <= count) {
- ret = glusterd_brickinfo_from_brick (brick, &brickinfo);
+ ret = glusterd_brickinfo_new_from_brick (brick, &brickinfo);
if (ret)
goto out;
ret = glusterd_resolve_brick (brickinfo);
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, FMTSTR_RESOLVE_BRICK,
+ brickinfo->hostname, brickinfo->path);
goto out;
+ }
+
+#ifdef HAVE_BD_XLATOR
+ if (!uuid_compare (brickinfo->uuid, MY_UUID)) {
+ if (brickinfo->vg[0]) {
+ ret = glusterd_is_valid_vg (brickinfo, 0, msg);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "%s",
+ msg);
+ goto out;
+ }
+
+ /* if anyone of the brick does not have thin
+ support, disable it for entire volume */
+ caps &= brickinfo->caps;
+
+
+ } else
+ caps = 0;
+ }
+#endif
+
list_add_tail (&brickinfo->brick_list, &volinfo->bricks);
brick = strtok_r (NULL, " \n", &saveptr);
i++;
}
+ gd_update_volume_op_versions (volinfo);
+
+ volinfo->caps = caps;
+
ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT);
if (ret) {
glusterd_store_delete_volume (volinfo);
@@ -1438,18 +1670,12 @@ glusterd_op_create_volume (dict_t *dict, char **op_errstr)
goto out;
}
- ret = glusterd_volume_compute_cksum (volinfo);
- if (ret) {
- *op_errstr = gf_strdup ("Failed to compute checksum of volume");
- goto out;
- }
-
- volinfo->defrag_status = 0;
+ volinfo->rebal.defrag_status = 0;
list_add_tail (&volinfo->vol_list, &priv->volumes);
vol_added = _gf_true;
+
out:
- if (free_ptr)
- GF_FREE(free_ptr);
+ GF_FREE(free_ptr);
if (!vol_added && volinfo)
glusterd_volinfo_delete (volinfo);
return ret;
@@ -1463,18 +1689,28 @@ glusterd_op_start_volume (dict_t *dict, char **op_errstr)
int flags = 0;
glusterd_volinfo_t *volinfo = NULL;
glusterd_brickinfo_t *brickinfo = NULL;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
ret = glusterd_op_start_volume_args_get (dict, &volname, &flags);
if (ret)
goto out;
ret = glusterd_volinfo_find (volname, &volinfo);
-
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, FMTSTR_CHECK_VOL_EXISTS,
+ volname);
goto out;
+ }
+
list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
- ret = glusterd_brick_start (volinfo, brickinfo);
- if (ret)
+ ret = glusterd_brick_start (volinfo, brickinfo, _gf_true);
+ /* If 'force' try to start all bricks regardless of success or
+ * failure
+ */
+ if (!(flags & GF_CLI_FLAG_OP_FORCE) && ret)
goto out;
}
@@ -1487,7 +1723,48 @@ glusterd_op_start_volume (dict_t *dict, char **op_errstr)
ret = glusterd_nodesvcs_handle_graph_change (volinfo);
out:
- gf_log ("", GF_LOG_DEBUG, "returning %d ", ret);
+ gf_log (this->name, GF_LOG_DEBUG, "returning %d ", ret);
+ 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;
}
@@ -1499,30 +1776,28 @@ 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;
+ GF_ASSERT (this);
ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags);
if (ret)
goto out;
ret = glusterd_volinfo_find (volname, &volinfo);
-
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, FMTSTR_CHECK_VOL_EXISTS,
+ volname);
goto out;
-
- list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
- ret = glusterd_brick_stop (volinfo, brickinfo);
- 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;
}
@@ -1543,18 +1818,20 @@ glusterd_op_delete_volume (dict_t *dict)
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
- gf_log ("", GF_LOG_ERROR, "Unable to get volume name");
+ gf_log (this->name, GF_LOG_ERROR, "Unable to get volume name");
goto out;
}
ret = glusterd_volinfo_find (volname, &volinfo);
-
- if (ret)
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, FMTSTR_CHECK_VOL_EXISTS,
+ volname);
goto out;
+ }
ret = glusterd_delete_volume (volinfo);
out:
- gf_log ("", GF_LOG_DEBUG, "returning %d", ret);
+ gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret);
return ret;
}
@@ -1596,8 +1873,14 @@ glusterd_op_statedump_volume (dict_t *dict, char **op_errstr)
ret = glusterd_brick_statedump (volinfo, brickinfo,
options, option_cnt,
op_errstr);
+ /* Let us take the statedump of other bricks instead of
+ * exiting, if statedump of this brick fails.
+ */
if (ret)
- goto out;
+ gf_log (THIS->name, GF_LOG_WARNING, "could not "
+ "take the statedump of the brick %s:%s."
+ " Proceeding to other bricks",
+ brickinfo->hostname, brickinfo->path);
}
}
@@ -1666,7 +1949,9 @@ glusterd_clearlocks_unmount (glusterd_volinfo_t *volinfo, char *mntpt)
runner_add_args (&runner, "/bin/umount", "-f", NULL);
runner_argprintf (&runner, "%s", mntpt);
+ synclock_unlock (&priv->big_lock);
ret = runner_run (&runner);
+ synclock_lock (&priv->big_lock);
if (ret) {
ret = 0;
gf_log ("", GF_LOG_DEBUG,
@@ -1738,7 +2023,9 @@ glusterd_clearlocks_mount (glusterd_volinfo_t *volinfo, char **xl_opts,
}
runner_argprintf (&runner, "%s", mntpt);
+ synclock_unlock (&priv->big_lock);
ret = runner_run (&runner);
+ synclock_lock (&priv->big_lock);
if (ret) {
gf_log (THIS->name, GF_LOG_DEBUG,
"Could not start glusterfs");
@@ -1774,7 +2061,7 @@ glusterd_clearlocks_get_local_client_ports (glusterd_volinfo_t *volinfo,
index = -1;
list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
index++;
- if (uuid_compare (brickinfo->uuid, priv->uuid))
+ if (uuid_compare (brickinfo->uuid, MY_UUID))
continue;
port = pmap_registry_search (THIS, brickinfo->path,
@@ -1802,7 +2089,7 @@ out:
}
int
-glusterd_op_clearlocks_volume (dict_t *dict, char **op_errstr)
+glusterd_op_clearlocks_volume (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
{
int32_t ret = -1;
int i = 0;
@@ -1817,7 +2104,6 @@ glusterd_op_clearlocks_volume (dict_t *dict, char **op_errstr)
char result[PATH_MAX] = {0,};
char *mntpt = NULL;
char **xl_opts = NULL;
- dict_t *ctx = NULL;
glusterd_volinfo_t *volinfo = NULL;
ret = dict_get_str (dict, "volname", &volname);
@@ -1906,14 +2192,8 @@ glusterd_op_clearlocks_volume (dict_t *dict, char **op_errstr)
goto umount;
}
- ctx = glusterd_op_get_ctx ();
- if (!ctx)
- /*Impossible. Only originator glusterd can
- * come here. */
- goto umount;
-
free_ptr = gf_strdup(result);
- if (dict_set_dynstr (ctx, "lk-summary", free_ptr)) {
+ if (dict_set_dynstr (rsp_dict, "lk-summary", free_ptr)) {
GF_FREE (free_ptr);
snprintf (msg, sizeof (msg), "Failed to set clear-locks "
"result");
@@ -1937,11 +2217,9 @@ out:
GF_FREE (xl_opts);
}
- if (cmd_str)
- GF_FREE (cmd_str);
+ GF_FREE (cmd_str);
- if (mntpt)
- GF_FREE (mntpt);
+ GF_FREE (mntpt);
return ret;
}