diff options
| -rwxr-xr-x | tests/bugs/bug-913555.t | 66 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 26 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 48 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 3 | 
4 files changed, 142 insertions, 1 deletions
diff --git a/tests/bugs/bug-913555.t b/tests/bugs/bug-913555.t new file mode 100755 index 00000000000..0e08bd377ae --- /dev/null +++ b/tests/bugs/bug-913555.t @@ -0,0 +1,66 @@ +#!/bin/bash + +# Test that a volume becomes unwritable when the cluster loses quorum. + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +function vglusterd { +	wd=$1/wd-$2 +	cp -r /var/lib/glusterd $wd +	rm -rf $wd/peers/* $wd/vols/* +	echo -n "UUID=$(uuidgen)\noperating-version=1\n" > $wd/glusterd.info +	opt1="management.transport.socket.bind-address=127.0.0.$2" +	opt2="management.working-directory=$wd" +	glusterd --xlator-option $opt1 --xlator-option $opt2 +} + +function check_fs { +	df $1 &> /dev/null +	echo $? +} + +function check_peers { +	$VCLI peer status | grep 'Peer in Cluster (Connected)' | wc -l +} + +cleanup; + +topwd=$(mktemp -d) +trap "rm -rf $topwd" EXIT + +vglusterd $topwd 100 +VCLI="$CLI --remote-host=127.0.0.100" +vglusterd $topwd 101 +TEST $VCLI peer probe 127.0.0.101 +vglusterd $topwd 102 +TEST $VCLI peer probe 127.0.0.102 + +EXPECT_WITHIN 20 2 check_peers + +create_cmd="$VCLI volume create $V0" +for i in $(seq 100 102); do +	mkdir -p $B0/$V0$i +	create_cmd="$create_cmd 127.0.0.$i:$B0/$V0$i" +done + +TEST $create_cmd +TEST $VCLI volume set $V0 cluster.server-quorum-type server +TEST $VCLI volume start $V0 +TEST glusterfs --volfile-server=127.0.0.100 --volfile-id=$V0 $M0 + +# Kill one pseudo-node, make sure the others survive and volume stays up. +kill -9 $(ps -ef | grep gluster | grep 127.0.0.102 | awk '{print $2}') +EXPECT_WITHIN 20 1 check_peers +fs_status=$(check_fs $M0) +nnodes=$(pidof glusterfsd | wc -w) +TEST [ "$fs_status" = 0 -a "$nnodes" = 2 ] + +# Kill another pseudo-node, make sure the last one dies and volume goes down. +kill -9 $(ps -ef | grep gluster | grep 127.0.0.101 | awk '{print $2}') +EXPECT_WITHIN 20 0 check_peers +fs_status=$(check_fs $M0) +nnodes=$(pidof glusterfsd | wc -w) +TEST [ "$fs_status" = 1 -a "$nnodes" = 0 ] + +cleanup diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index d69f8352010..d5bad0f2751 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -707,6 +707,7 @@ glusterd_handle_cli_probe (rpcsvc_request_t *req)          glusterd_peerinfo_t             *peerinfo = NULL;          gf_boolean_t                    run_fsm = _gf_true;          xlator_t                        *this = NULL; +        char                            *bind_name = NULL;          GF_ASSERT (req);          this = THIS; @@ -736,7 +737,16 @@ glusterd_handle_cli_probe (rpcsvc_request_t *req)          gf_log ("glusterd", GF_LOG_INFO, "Received CLI probe req %s %d",                  cli_req.hostname, cli_req.port); -        if (glusterd_is_local_addr(cli_req.hostname)) { +        if (dict_get_str(this->options,"transport.socket.bind-address", +                         &bind_name) == 0) { +                gf_log ("glusterd", GF_LOG_DEBUG, +                        "only checking probe address vs. bind address"); +                ret = glusterd_is_same_address(bind_name,cli_req.hostname); +        } +        else { +                ret = glusterd_is_local_addr(cli_req.hostname); +        } +        if (ret) {                  glusterd_xfer_cli_probe_resp (req, 0, GF_PROBE_LOCALHOST, NULL,                                                cli_req.hostname, cli_req.port);                  ret = 0; @@ -2429,6 +2439,7 @@ glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo,          dict_t                 *options = NULL;          int                    ret = -1;          glusterd_peerctx_t     *peerctx = NULL; +        data_t                 *data = NULL;          peerctx = GF_CALLOC (1, sizeof (*peerctx), gf_gld_mt_peerctx_t);          if (!peerctx) @@ -2445,6 +2456,19 @@ glusterd_friend_rpc_create (xlator_t *this, glusterd_peerinfo_t *peerinfo,          if (ret)                  goto out; +        /* +         * For simulated multi-node testing, we need to make sure that we +         * create our RPC endpoint with the same address that the peer would +         * use to reach us. +         */ +        if (this->options) { +                data = dict_get(this->options,"transport.socket.bind-address"); +                if (data) { +                        ret = dict_set(options, +                                       "transport.socket.source-addr",data); +                } +        } +          ret = glusterd_rpc_create (&peerinfo->rpc, options,                                     glusterd_peer_rpc_notify, peerctx);          if (ret) { diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 093c59ce87a..4db538b0223 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -7397,3 +7397,51 @@ glusterd_copy_uuid_to_dict (uuid_t uuid, dict_t *dict, char *key)          return 0;  } + +gf_boolean_t +glusterd_is_same_address (char *name1, char *name2) +{ +        struct addrinfo         *addr1 = NULL; +        struct addrinfo         *addr2 = NULL; +        struct addrinfo         *p = NULL;        +        struct addrinfo         *q = NULL;        +        gf_boolean_t            ret = _gf_false; +        int                     gai_err = 0; + +        gai_err = getaddrinfo(name1,NULL,NULL,&addr1); +        if (gai_err != 0) { +                gf_log (name1, GF_LOG_WARNING, +                        "error in getaddrinfo: %s\n", gai_strerror(gai_err)); +                goto out; +        } + +        gai_err = getaddrinfo(name2,NULL,NULL,&addr2); +        if (gai_err != 0) { +                gf_log (name2, GF_LOG_WARNING, +                        "error in getaddrinfo: %s\n", gai_strerror(gai_err)); +                goto out; +        } + +        for (p = addr1; p; p = p->ai_next) { +                for (q = addr2; q; q = q->ai_next) { +                        if (p->ai_addrlen != q->ai_addrlen) { +                                continue; +                        } +                        if (memcmp(p->ai_addr,q->ai_addr,p->ai_addrlen)) { +                                continue; +                        } +                        ret = _gf_true; +                        goto out; +                } +        } + +out: +        if (addr1) { +                freeaddrinfo(addr1); +        } +        if (addr2) { +                freeaddrinfo(addr2); +        } +        return ret; + +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index b5f005560c2..6084f5714b3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -509,4 +509,7 @@ glusterd_generate_and_set_task_id (dict_t *dict, char *key);  int  glusterd_copy_uuid_to_dict (uuid_t uuid, dict_t *dict, char *key); + +gf_boolean_t +glusterd_is_same_address (char *name1, char *name2);  #endif  | 
