summaryrefslogtreecommitdiffstats
path: root/rpc/rpc-lib
diff options
context:
space:
mode:
Diffstat (limited to 'rpc/rpc-lib')
-rw-r--r--rpc/rpc-lib/src/Makefile.am4
-rw-r--r--rpc/rpc-lib/src/protocol-common.h4
-rw-r--r--rpc/rpc-lib/src/rpc-clnt.c7
-rw-r--r--rpc/rpc-lib/src/rpc-drc.c16
-rw-r--r--rpc/rpc-lib/src/rpcsvc.c200
-rw-r--r--rpc/rpc-lib/src/xdr-common.h15
-rw-r--r--rpc/rpc-lib/src/xdr-rpc.h17
7 files changed, 207 insertions, 56 deletions
diff --git a/rpc/rpc-lib/src/Makefile.am b/rpc/rpc-lib/src/Makefile.am
index 4cdeaad0b..ee2f27b25 100644
--- a/rpc/rpc-lib/src/Makefile.am
+++ b/rpc/rpc-lib/src/Makefile.am
@@ -2,10 +2,10 @@ lib_LTLIBRARIES = libgfrpc.la
libgfrpc_la_SOURCES = auth-unix.c rpcsvc-auth.c rpcsvc.c auth-null.c \
rpc-transport.c xdr-rpc.c xdr-rpcclnt.c rpc-clnt.c auth-glusterfs.c \
- rpc-drc.c
+ rpc-drc.c $(CONTRIBDIR)/sunrpc/xdr_sizeof.c
libgfrpc_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
-libgfrpc_la_LDFLAGS = -version-info $(LIBGFRPC_LT_VERSION)
+libgfrpc_la_LDFLAGS = -version-info $(LIBGFRPC_LT_VERSION) $(GF_LDFLAGS)
noinst_HEADERS = rpcsvc.h rpc-transport.h xdr-common.h xdr-rpc.h xdr-rpcclnt.h \
rpc-clnt.h rpcsvc-common.h protocol-common.h rpc-drc.h
diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h
index 90c16f91a..99d5a6259 100644
--- a/rpc/rpc-lib/src/protocol-common.h
+++ b/rpc/rpc-lib/src/protocol-common.h
@@ -108,7 +108,9 @@ enum gf_probe_resp {
GF_PROBE_SAME_UUID,
GF_PROBE_UNKNOWN_PEER,
GF_PROBE_ADD_FAILED,
- GF_PROBE_QUORUM_NOT_MET
+ GF_PROBE_QUORUM_NOT_MET,
+ GF_PROBE_MISSED_SNAP_CONFLICT,
+ GF_PROBE_SNAP_CONFLICT,
};
enum gf_deprobe_resp {
diff --git a/rpc/rpc-lib/src/rpc-clnt.c b/rpc/rpc-lib/src/rpc-clnt.c
index e095c55b3..3106342e9 100644
--- a/rpc/rpc-lib/src/rpc-clnt.c
+++ b/rpc/rpc-lib/src/rpc-clnt.c
@@ -717,8 +717,9 @@ rpc_clnt_handle_cbk (struct rpc_clnt *clnt, rpc_transport_pollin_t *msg)
}
gf_log (clnt->conn.name, GF_LOG_TRACE,
- "received rpc message (XID: 0x%lx, "
- "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) "
+ "receivd rpc message (XID: 0x%" GF_PRI_RPC_XID ", "
+ "Ver: %" GF_PRI_RPC_VERSION ", Program: %" GF_PRI_RPC_PROG_ID ", "
+ "ProgVers: %" GF_PRI_RPC_PROG_VERS ", Proc: %" GF_PRI_RPC_PROC ") "
"from rpc-transport (%s)", rpc_call_xid (&rpcmsg),
rpc_call_rpcvers (&rpcmsg), rpc_call_program (&rpcmsg),
rpc_call_progver (&rpcmsg), rpc_call_progproc (&rpcmsg),
@@ -1141,7 +1142,7 @@ xdr_serialize_glusterfs_auth (char *dest, struct auth_glusterfs_parms_v2 *au)
{
ssize_t ret = -1;
XDR xdr;
- uint64_t ngroups = 0;
+ u_long ngroups = 0;
int max_groups = 0;
if ((!dest) || (!au))
diff --git a/rpc/rpc-lib/src/rpc-drc.c b/rpc/rpc-lib/src/rpc-drc.c
index 7e77e038e..bc37324d3 100644
--- a/rpc/rpc-lib/src/rpc-drc.c
+++ b/rpc/rpc-lib/src/rpc-drc.c
@@ -127,14 +127,14 @@ int
drc_compare_reqs (const void *item, const void *rb_node_data, void *param)
{
int ret = -1;
- rpcsvc_request_t *req = NULL;
+ drc_cached_op_t *req = NULL;
drc_cached_op_t *reply = NULL;
GF_ASSERT (item);
GF_ASSERT (rb_node_data);
GF_ASSERT (param);
- req = (rpcsvc_request_t *)item;
+ req = (drc_cached_op_t *)item;
reply = (drc_cached_op_t *)rb_node_data;
ret = req->xid - reply->xid;
@@ -143,7 +143,7 @@ drc_compare_reqs (const void *item, const void *rb_node_data, void *param)
if (req->prognum == reply->prognum &&
req->procnum == reply->procnum &&
- req->progver == reply->progversion)
+ req->progversion == reply->progversion)
return 0;
return 1;
@@ -331,6 +331,12 @@ rpcsvc_drc_lookup (rpcsvc_request_t *req)
{
drc_client_t *client = NULL;
drc_cached_op_t *reply = NULL;
+ drc_cached_op_t new = {
+ .xid = req->xid,
+ .prognum = req->prognum,
+ .progversion = req->progver,
+ .procnum = req->procnum,
+ };
GF_ASSERT (req);
@@ -347,7 +353,7 @@ rpcsvc_drc_lookup (rpcsvc_request_t *req)
if (client->op_count == 0)
goto out;
- reply = rb_find (client->rbtree, req);
+ reply = rb_find (client->rbtree, &new);
out:
if (client)
@@ -460,7 +466,7 @@ rpcsvc_vacate_drc_entries (rpcsvc_drc_globals_t *drc)
client = reply->client;
- (void *)rb_delete (client->rbtree, reply);
+ rb_delete (client->rbtree, reply);
rpcsvc_drc_op_destroy (drc, reply);
rpcsvc_drc_client_unref (drc, client);
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
index 8be64c18a..1c13048f2 100644
--- a/rpc/rpc-lib/src/rpcsvc.c
+++ b/rpc/rpc-lib/src/rpcsvc.c
@@ -29,6 +29,7 @@
#include "rpc-common-xdr.h"
#include "syncop.h"
#include "rpc-drc.h"
+#include "protocol-common.h"
#include <errno.h>
#include <pthread.h>
@@ -59,6 +60,9 @@ int
rpcsvc_notify (rpc_transport_t *trans, void *mydata,
rpc_transport_event_t event, void *data, ...);
+static int
+match_subnet_v4 (const char *addrtok, const char *ipaddr);
+
rpcsvc_notify_wrapper_t *
rpcsvc_notify_wrapper_alloc (void)
{
@@ -129,32 +133,67 @@ rpcsvc_get_program_vector_sizer (rpcsvc_t *svc, uint32_t prognum,
return NULL;
}
+gf_boolean_t
+rpcsvc_can_outstanding_req_be_ignored (rpcsvc_request_t *req)
+{
+ /*
+ * If outstanding_rpc_limit is reached because of blocked locks and
+ * throttling is attempted then no unlock requests will be received. So
+ * the outstanding request count will never change i.e. it will always
+ * be equal to the limit. This also leads to ping timer expiry on
+ * client.
+ */
+
+ /*
+ * This is a hack and a necessity until grantedlock == fop completion.
+ * Ideally if we get a blocking lock request which cannot be granted
+ * right now, we should unwind the fop saying “request registered, will
+ * notify you when granted”, which is very hard to implement at the
+ * moment. Until we bring in such mechanism, we will need to live with
+ * not rate-limiting INODELK/ENTRYLK/LK fops
+ */
+
+ if ((req->prognum == GLUSTER_FOP_PROGRAM) &&
+ (req->progver == GLUSTER_FOP_VERSION)) {
+ if ((req->procnum == GFS3_OP_INODELK) ||
+ (req->procnum == GFS3_OP_FINODELK) ||
+ (req->procnum == GFS3_OP_ENTRYLK) ||
+ (req->procnum == GFS3_OP_FENTRYLK) ||
+ (req->procnum == GFS3_OP_LK))
+ return _gf_true;
+ }
+ return _gf_false;
+}
+
int
-rpcsvc_request_outstanding (rpcsvc_t *svc, rpc_transport_t *trans, int delta)
+rpcsvc_request_outstanding (rpcsvc_request_t *req, int delta)
{
int ret = 0;
int old_count = 0;
int new_count = 0;
int limit = 0;
- pthread_mutex_lock (&trans->lock);
+ if (rpcsvc_can_outstanding_req_be_ignored (req))
+ return 0;
+
+ pthread_mutex_lock (&req->trans->lock);
{
- limit = svc->outstanding_rpc_limit;
+ limit = req->svc->outstanding_rpc_limit;
if (!limit)
goto unlock;
- old_count = trans->outstanding_rpc_count;
- trans->outstanding_rpc_count += delta;
- new_count = trans->outstanding_rpc_count;
+ old_count = req->trans->outstanding_rpc_count;
+ req->trans->outstanding_rpc_count += delta;
+ new_count = req->trans->outstanding_rpc_count;
if (old_count <= limit && new_count > limit)
- ret = rpc_transport_throttle (trans, _gf_true);
+ ret = rpc_transport_throttle (req->trans, _gf_true);
if (old_count > limit && new_count <= limit)
- ret = rpc_transport_throttle (trans, _gf_false);
+ ret = rpc_transport_throttle (req->trans, _gf_false);
}
unlock:
- pthread_mutex_unlock (&trans->lock);
+ pthread_mutex_unlock (&req->trans->lock);
return ret;
}
@@ -315,7 +354,8 @@ rpcsvc_request_destroy (rpcsvc_request_t *req)
to the client. It is time to decrement the
outstanding request counter by 1.
*/
- rpcsvc_request_outstanding (req->svc, req->trans, -1);
+ if (req->prognum) //Only for initialized requests
+ rpcsvc_request_outstanding (req, -1);
rpc_transport_unref (req->trans);
@@ -397,12 +437,6 @@ rpcsvc_request_create (rpcsvc_t *svc, rpc_transport_t *trans,
goto err;
}
- /* We just received a new request from the wire. Account for
- it in the outsanding request counter to make sure we don't
- ingest too many concurrent requests from the same client.
- */
- ret = rpcsvc_request_outstanding (svc, trans, +1);
-
msgbuf = msg->vector[0].iov_base;
msglen = msg->vector[0].iov_len;
@@ -420,19 +454,28 @@ rpcsvc_request_create (rpcsvc_t *svc, rpc_transport_t *trans,
ret = -1;
rpcsvc_request_init (svc, trans, &rpcmsg, progmsg, msg, req);
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "received rpc-message (XID: 0x%lx, "
- "Ver: %ld, Program: %ld, ProgVers: %ld, Proc: %ld) from"
- " rpc-transport (%s)", rpc_call_xid (&rpcmsg),
+ gf_log (GF_RPCSVC, GF_LOG_TRACE, "received rpc-message "
+ "(XID: 0x%" GF_PRI_RPC_XID ", Ver: %" GF_PRI_RPC_VERSION ", Program: %" GF_PRI_RPC_PROG_ID ", "
+ "ProgVers: %" GF_PRI_RPC_PROG_VERS ", Proc: %" GF_PRI_RPC_PROC ") "
+ "from rpc-transport (%s)", rpc_call_xid (&rpcmsg),
rpc_call_rpcvers (&rpcmsg), rpc_call_program (&rpcmsg),
rpc_call_progver (&rpcmsg), rpc_call_progproc (&rpcmsg),
trans->name);
+ /* We just received a new request from the wire. Account for
+ it in the outsanding request counter to make sure we don't
+ ingest too many concurrent requests from the same client.
+ */
+ if (req->prognum) //Only for initialized requests
+ ret = rpcsvc_request_outstanding (req, +1);
+
if (rpc_call_rpcvers (&rpcmsg) != 2) {
/* LOG- TODO: print rpc version, also print the peerinfo
from transport */
gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC version not supported "
- "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, "
- "Proc: %ld) from trans (%s)", rpc_call_xid (&rpcmsg),
+ "(XID: 0x%" GF_PRI_RPC_XID ", Ver: %" GF_PRI_RPC_VERSION ", Program: %" GF_PRI_RPC_PROG_ID ", "
+ "ProgVers: %" GF_PRI_RPC_PROG_VERS ", Proc: %" GF_PRI_RPC_PROC ") "
+ "from trans (%s)", rpc_call_xid (&rpcmsg),
rpc_call_rpcvers (&rpcmsg), rpc_call_program (&rpcmsg),
rpc_call_progver (&rpcmsg), rpc_call_progproc (&rpcmsg),
trans->name);
@@ -448,8 +491,9 @@ rpcsvc_request_create (rpcsvc_t *svc, rpc_transport_t *trans,
*/
rpcsvc_request_seterr (req, AUTH_ERROR);
gf_log (GF_RPCSVC, GF_LOG_ERROR, "auth failed on request. "
- "(XID: 0x%lx, Ver: %ld, Prog: %ld, ProgVers: %ld, "
- "Proc: %ld) from trans (%s)", rpc_call_xid (&rpcmsg),
+ "(XID: 0x%" GF_PRI_RPC_XID ", Ver: %" GF_PRI_RPC_VERSION ", Program: %" GF_PRI_RPC_PROG_ID ", "
+ "ProgVers: %" GF_PRI_RPC_PROG_VERS ", Proc: %" GF_PRI_RPC_PROC ") "
+ "from trans (%s)", rpc_call_xid (&rpcmsg),
rpc_call_rpcvers (&rpcmsg), rpc_call_program (&rpcmsg),
rpc_call_progver (&rpcmsg), rpc_call_progproc (&rpcmsg),
trans->name);
@@ -794,15 +838,9 @@ err:
return txrecord;
}
-static inline int
-rpcsvc_get_callid (rpcsvc_t *rpc)
-{
- return GF_UNIVERSAL_ANSWER;
-}
-
int
rpcsvc_fill_callback (int prognum, int progver, int procnum, int payload,
- uint64_t xid, struct rpc_msg *request)
+ uint32_t xid, struct rpc_msg *request)
{
int ret = -1;
@@ -867,9 +905,9 @@ out:
return txrecord;
}
-struct iobuf *
+static struct iobuf *
rpcsvc_callback_build_record (rpcsvc_t *rpc, int prognum, int progver,
- int procnum, size_t payload, uint64_t xid,
+ int procnum, size_t payload, u_long xid,
struct iovec *recbuf)
{
struct rpc_msg request = {0, };
@@ -889,7 +927,7 @@ rpcsvc_callback_build_record (rpcsvc_t *rpc, int prognum, int progver,
&request);
if (ret == -1) {
gf_log ("rpcsvc", GF_LOG_WARNING, "cannot build a rpc-request "
- "xid (%"PRIu64")", xid);
+ "xid (%" GF_PRI_RPC_XID ")", xid);
goto out;
}
@@ -936,7 +974,6 @@ rpcsvc_callback_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
rpc_transport_req_t req;
int ret = -1;
int proglen = 0;
- uint64_t callid = 0;
if (!rpc) {
goto out;
@@ -944,15 +981,14 @@ rpcsvc_callback_submit (rpcsvc_t *rpc, rpc_transport_t *trans,
memset (&req, 0, sizeof (req));
- callid = rpcsvc_get_callid (rpc);
-
if (proghdr) {
proglen += iov_length (proghdr, proghdrcount);
}
request_iob = rpcsvc_callback_build_record (rpc, prog->prognum,
prog->progver, procnum,
- proglen, callid,
+ proglen,
+ GF_UNIVERSAL_ANSWER,
&rpchdr);
if (!request_iob) {
gf_log ("rpcsvc", GF_LOG_WARNING,
@@ -1253,7 +1289,7 @@ rpcsvc_program_register_portmap (rpcsvc_program_t *newprog, uint32_t port)
if (!(pmap_set (newprog->prognum, newprog->progver, IPPROTO_TCP,
port))) {
gf_log (GF_RPCSVC, GF_LOG_ERROR, "Could not register with"
- " portmap");
+ " portmap %d %d %u", newprog->prognum, newprog->progver, port);
goto out;
}
@@ -2181,6 +2217,13 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern,
goto err;
}
+ /* Compare IPv4 subnetwork */
+ if (strchr (addrtok, '/')) {
+ ret = match_subnet_v4 (addrtok, ip);
+ if (ret == 0)
+ goto err;
+ }
+
addrtok = strtok_r (NULL, ",", &svptr);
}
@@ -2327,8 +2370,20 @@ rpcsvc_auth_check (rpcsvc_t *svc, char *volname,
ret = dict_get_str (options, srchstr, &reject_str);
GF_FREE (srchstr);
- if (reject_str == NULL && !strcmp ("*", allow_str))
- return RPCSVC_AUTH_ACCEPT;
+
+ /*
+ * If "reject_str" is being set as '*' (anonymous), then NFS-server
+ * would reject everything. If the "reject_str" is not set and
+ * "allow_str" is set as '*' (anonymous), then NFS-server would
+ * accept mount requests from all clients.
+ */
+ if (reject_str != NULL) {
+ if (!strcmp ("*", reject_str))
+ return RPCSVC_AUTH_REJECT;
+ } else {
+ if (!strcmp ("*", allow_str))
+ return RPCSVC_AUTH_ACCEPT;
+ }
/* Non-default rule, authenticate */
if (!get_host_name (client_ip, &ip))
@@ -2461,6 +2516,71 @@ out:
return addrstr;
}
+/*
+ * match_subnet_v4() takes subnetwork address pattern and checks
+ * if the target IPv4 address has the same network address with
+ * the help of network mask.
+ *
+ * Returns 0 for SUCCESS and -1 otherwise.
+ *
+ * NB: Validation of subnetwork address pattern is not required
+ * as it's already being done at the time of CLI SET.
+ */
+static int
+match_subnet_v4 (const char *addrtok, const char *ipaddr)
+{
+ char *slash = NULL;
+ char *netaddr = NULL;
+ long prefixlen = -1;
+ int ret = -1;
+ uint32_t shift = 0;
+ struct sockaddr_in sin1 = {0, };
+ struct sockaddr_in sin2 = {0, };
+ struct sockaddr_in mask = {0, };
+
+ /* Copy the input */
+ netaddr = gf_strdup (addrtok);
+ if (netaddr == NULL) /* ENOMEM */
+ goto out;
+
+ /* Find the network socket addr of target */
+ if (inet_pton (AF_INET, ipaddr, &sin1.sin_addr) == 0)
+ goto out;
+
+ /* Find the network socket addr of subnet pattern */
+ slash = strchr (netaddr, '/');
+ *slash = '\0';
+ if (inet_pton (AF_INET, netaddr, &sin2.sin_addr) == 0)
+ goto out;
+
+ /*
+ * Find the network mask in network byte order.
+ * NB: 32 : Max len of IPv4 address.
+ */
+ prefixlen = atoi (slash + 1);
+ shift = 32 - (uint32_t)prefixlen;
+ mask.sin_addr.s_addr = htonl ((uint32_t)~0 << shift);
+
+ /*
+ * Check if both have same network address.
+ * Extract the network address from the IP addr by applying the
+ * network mask. If they match, return SUCCESS. i.e.
+ *
+ * (x == y) <=> (x ^ y == 0)
+ * (x & y) ^ (x & z) <=> x & (y ^ z)
+ *
+ * ((ip1 & mask) == (ip2 & mask)) <=> ((mask & (ip1 ^ ip2)) == 0)
+ */
+ if (((mask.sin_addr.s_addr) &
+ (sin1.sin_addr.s_addr ^ sin2.sin_addr.s_addr)) != 0)
+ goto out;
+
+ ret = 0; /* SUCCESS */
+out:
+ GF_FREE (netaddr);
+ return ret;
+}
+
rpcsvc_actor_t gluster_dump_actors[] = {
[GF_DUMP_NULL] = {"NULL", GF_DUMP_NULL, NULL, NULL, 0, DRC_NA},
diff --git a/rpc/rpc-lib/src/xdr-common.h b/rpc/rpc-lib/src/xdr-common.h
index f221192ad..631f4b284 100644
--- a/rpc/rpc-lib/src/xdr-common.h
+++ b/rpc/rpc-lib/src/xdr-common.h
@@ -18,8 +18,8 @@
#include <rpc/types.h>
#include <sys/types.h>
-#include <rpc/auth.h>
#include <rpc/xdr.h>
+#include <rpc/auth.h>
#include <sys/uio.h>
#ifdef __NetBSD__
@@ -64,11 +64,18 @@ enum gf_dump_procnum {
#define GF_AUTH_GLUSTERFS_MAX_LKOWNER(groups_len) \
(95 - groups_len)
-#if GF_DARWIN_HOST_OS
+#ifdef GF_LINUX_HOST_OS
+#define xdr_u_int32_t xdr_uint32_t
+#define xdr_u_int64_t xdr_uint64_t
+#endif
+
+#ifdef GF_DARWIN_HOST_OS
#define xdr_u_quad_t xdr_u_int64_t
#define xdr_quad_t xdr_int64_t
#define xdr_uint32_t xdr_u_int32_t
+#define xdr_uint64_t xdr_u_int64_t
#define uint64_t u_int64_t
+unsigned long xdr_sizeof (xdrproc_t func, void *data);
#endif
#if defined(__NetBSD__)
@@ -78,13 +85,11 @@ enum gf_dump_procnum {
#define xdr_uint64_t xdr_u_int64_t
#endif
-
-#if GF_SOLARIS_HOST_OS
+#ifdef GF_SOLARIS_HOST_OS
#define u_quad_t uint64_t
#define quad_t int64_t
#define xdr_u_quad_t xdr_uint64_t
#define xdr_quad_t xdr_int64_t
-#define xdr_uint32_t xdr_uint32_t
#endif
/* Returns the address of the byte that follows the
diff --git a/rpc/rpc-lib/src/xdr-rpc.h b/rpc/rpc-lib/src/xdr-rpc.h
index f5f4a941e..4663ef796 100644
--- a/rpc/rpc-lib/src/xdr-rpc.h
+++ b/rpc/rpc-lib/src/xdr-rpc.h
@@ -78,4 +78,21 @@ xdr_to_auth_unix_cred (char *msgbuf, int msglen, struct authunix_parms *au,
#define rpc_call_verf_flavour(call) (rpc_opaque_auth_flavour ((&(call)->ru.RM_cmb.cb_verf)))
#define rpc_call_verf_len(call) (rpc_opaque_auth_len ((&(call)->ru.RM_cmb.cb_verf)))
+
+#ifdef GF_DARWIN_HOST_OS
+#define GF_PRI_RPC_XID PRIu32
+#define GF_PRI_RPC_VERSION PRIu32
+#define GF_PRI_RPC_PROG_ID PRIu32
+#define GF_PRI_RPC_PROG_VERS PRIu32
+#define GF_PRI_RPC_PROC PRIu32
+#define GF_PRI_RPC_PROC_VERSION PRIu32
+#else
+#define GF_PRI_RPC_XID PRIu64
+#define GF_PRI_RPC_VERSION PRIu64
+#define GF_PRI_RPC_PROG_ID PRIu64
+#define GF_PRI_RPC_PROG_VERS PRIu64
+#define GF_PRI_RPC_PROC PRIu64
+#define GF_PRI_RPC_PROC_VERSION PRIu64
+#endif
+
#endif