summaryrefslogtreecommitdiffstats
path: root/xlators/nfs/server/src/nlm4.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/nfs/server/src/nlm4.c')
-rw-r--r--xlators/nfs/server/src/nlm4.c374
1 files changed, 213 insertions, 161 deletions
diff --git a/xlators/nfs/server/src/nlm4.c b/xlators/nfs/server/src/nlm4.c
index 9a0cd020a..5c5d87412 100644
--- a/xlators/nfs/server/src/nlm4.c
+++ b/xlators/nfs/server/src/nlm4.c
@@ -2,19 +2,10 @@
Copyright (c) 2012 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/>.
+ 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
@@ -149,8 +140,10 @@ nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh);
xlatorp = nfs3_fh_to_xlator (cst->nfs3state, \
&cst->resolvefh); \
uuid_unparse (cst->resolvefh.gfid, gfid); \
- sprintf (buf, "(%s) %s : %s", trans->peerinfo.identifier,\
- xlatorp ? xlatorp->name : "ERR", gfid); \
+ snprintf (buf, sizeof (buf), "(%s) %s : %s", \
+ trans->peerinfo.identifier, \
+ xlatorp ? xlatorp->name : "ERR", \
+ gfid); \
gf_log (GF_NLM, GF_LOG_ERROR, "Unable to resolve FH"\
": %s", buf); \
nfstat = nlm4_errno_to_nlm4stat (cst->resolve_errno);\
@@ -235,7 +228,7 @@ nlm_is_oh_same_lkowner (gf_lkowner_t *a, netobj *b)
!memcmp (a->data, b->n_bytes, a->len));
}
-nfsstat3
+nlm4_stats
nlm4_errno_to_nlm4stat (int errnum)
{
nlm4_stats stat = nlm4_denied;
@@ -345,13 +338,12 @@ nlm_set_rpc_clnt (rpc_clnt_t *rpc_clnt, char *caller_name)
break;
}
}
+
if (!nlmclnt_found) {
nlmclnt = GF_CALLOC (1, sizeof(*nlmclnt),
gf_nfs_mt_nlm4_nlmclnt);
- if (nlmclnt == NULL) {
- gf_log (GF_NLM, GF_LOG_ERROR, "mem-alloc error");
+ if (nlmclnt == NULL)
goto ret;
- }
INIT_LIST_HEAD(&nlmclnt->fdes);
INIT_LIST_HEAD(&nlmclnt->nlm_clients);
@@ -360,6 +352,7 @@ nlm_set_rpc_clnt (rpc_clnt_t *rpc_clnt, char *caller_name)
list_add (&nlmclnt->nlm_clients, &nlm_client_list);
nlmclnt->caller_name = gf_strdup (caller_name);
}
+
if (nlmclnt->rpc_clnt == NULL) {
nlmclnt->rpc_clnt = rpc_clnt_ref (rpc_clnt);
}
@@ -434,10 +427,11 @@ ret:
int
nlm4svc_submit_reply (rpcsvc_request_t *req, void *arg, nlm4_serializer sfunc)
{
- struct iovec outmsg = {0, };
- struct iobuf *iob = NULL;
- struct nfs3_state *nfs3 = NULL;
- int ret = -1;
+ struct iovec outmsg = {0, };
+ struct iobuf *iob = NULL;
+ struct nfs3_state *nfs3 = NULL;
+ int ret = -1;
+ ssize_t msglen = 0;
struct iobref *iobref = NULL;
if (!req)
@@ -462,7 +456,12 @@ nlm4svc_submit_reply (rpcsvc_request_t *req, void *arg, nlm4_serializer sfunc)
/* Use the given serializer to translate the give C structure in arg
* to XDR format which will be written into the buffer in outmsg.
*/
- outmsg.iov_len = sfunc (outmsg, arg);
+ msglen = sfunc (outmsg, arg);
+ if (msglen < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to encode message");
+ goto ret;
+ }
+ outmsg.iov_len = msglen;
iobref = iobref_new ();
if (iobref == NULL) {
@@ -470,7 +469,11 @@ nlm4svc_submit_reply (rpcsvc_request_t *req, void *arg, nlm4_serializer sfunc)
goto ret;
}
- iobref_add (iobref, iob);
+ ret = iobref_add (iobref, iob);
+ if (ret) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to add iob to iobref");
+ goto ret;
+ }
/* Then, submit the message for transmission. */
ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref);
@@ -594,9 +597,15 @@ nlm4_file_open_and_resume(nfs3_call_state_t *cs, nlm4_resume_fn_t resume)
{
fd_t *fd = NULL;
int ret = -1;
+ int flags = 0;
nlm_client_t *nlmclnt = NULL;
call_frame_t *frame = NULL;
+ if (cs->args.nlm4_lockargs.exclusive == _gf_false)
+ flags = O_RDONLY;
+ else
+ flags = O_WRONLY;
+
nlmclnt = nlm_get_uniq (cs->args.nlm4_lockargs.alock.caller_name);
if (nlmclnt == NULL) {
gf_log (GF_NLM, GF_LOG_ERROR, "nlm_get_uniq() returned NULL");
@@ -630,16 +639,13 @@ nlm4_file_open_and_resume(nfs3_call_state_t *cs, nlm4_resume_fn_t resume)
}
frame->root->pid = NFS_PID;
- frame->root->uid = 0;
- frame->root->gid = 0;
+ frame->root->uid = rpcsvc_request_uid (cs->req);
+ frame->root->gid = rpcsvc_request_gid (cs->req);
frame->local = cs;
- /*
- * This is the only place that we call STACK_WIND without nfs_fix_groups,
- * because in this particular case the relevant identify is in lk_owner and
- * we don't care about the fields that nfs_fix_groups would set up.
- */
+ nfs_fix_groups (cs->nfsx, frame->root);
+
STACK_WIND_COOKIE (frame, nlm4_file_open_cbk, cs->vol, cs->vol,
- cs->vol->fops->open, &cs->resolvedloc, O_RDWR,
+ cs->vol->fops->open, &cs->resolvedloc, flags,
cs->fd, NULL);
ret = 0;
err:
@@ -880,52 +886,65 @@ nlm4svc_send_granted_cbk (struct rpc_req *req, struct iovec *iov, int count,
return 0;
}
-int nlm_rpcclnt_notify (struct rpc_clnt *rpc, void *mydata,
- rpc_clnt_event_t fn, void *data)
+void
+nlm4svc_send_granted (nfs3_call_state_t *cs);
+
+int
+nlm_rpcclnt_notify (struct rpc_clnt *rpc_clnt, void *mydata,
+ rpc_clnt_event_t fn, void *data)
{
- nlm_condmutex_t *cm = NULL;
- int ret;
- cm = mydata;
+ int ret = 0;
+ char *caller_name = NULL;
+ nfs3_call_state_t *cs = NULL;
+
+ cs = mydata;
+ caller_name = cs->args.nlm4_lockargs.alock.caller_name;
+
switch (fn) {
case RPC_CLNT_CONNECT:
- ret = pthread_cond_broadcast (&cm->cond);
- if (ret!=0)
- gf_log (GF_NLM, GF_LOG_ERROR, "cond_broadcast error %s",
- strerror (errno));
+ ret = nlm_set_rpc_clnt (rpc_clnt, caller_name);
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to set rpc clnt");
+ goto err;
+ }
+ rpc_clnt_unref (rpc_clnt);
+ nlm4svc_send_granted (cs);
+
break;
+
case RPC_CLNT_MSG:
break;
+
case RPC_CLNT_DISCONNECT:
- nlm_unset_rpc_clnt(rpc);
+ nlm_unset_rpc_clnt (rpc_clnt);
break;
}
+
+ err:
return 0;
}
-void
-nlm4svc_send_granted (nfs3_call_state_t *cs);
-
void *
nlm4_establish_callback (void *csarg)
{
- nfs3_call_state_t *cs = NULL;
- struct sockaddr_storage sa;
- struct sockaddr *sockaddr = NULL;
- dict_t *options = NULL;
- char peerip[INET6_ADDRSTRLEN+1], *portstr = NULL;
- rpc_clnt_t *rpc_clnt = NULL;
- int port = -1;
- int ret = -1;
- char *caller_name = NULL;
+ int ret = -1;
+ nfs3_call_state_t *cs = NULL;
+ union gf_sock_union sock_union;
+ dict_t *options = NULL;
+ char peerip[INET6_ADDRSTRLEN+1] = {0};
+ char *portstr = NULL;
+ char myip[INET6_ADDRSTRLEN+1] = {0};
+ rpc_clnt_t *rpc_clnt = NULL;
+ int port = -1;
+
cs = (nfs3_call_state_t *) csarg;
glusterfs_this_set (cs->nfsx);
- caller_name = cs->args.nlm4_lockargs.alock.caller_name;
+ rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sock_union.storage,
+ sizeof (sock_union.storage));
- rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sa, sizeof (sa));
- sockaddr = (struct sockaddr*) &sa;
- switch (sockaddr->sa_family) {
+ switch (sock_union.sa.sa_family) {
case AF_INET6:
/* can not come here as NLM listens on IPv4 */
gf_log (GF_NLM, GF_LOG_ERROR, "NLM is not supported on IPv6 in"
@@ -938,9 +957,11 @@ nlm4_establish_callback (void *csarg)
break;
*/
case AF_INET:
- inet_ntop (AF_INET,
- &((struct sockaddr_in *)sockaddr)->sin_addr,
- peerip, INET6_ADDRSTRLEN+1);
+ inet_ntop (AF_INET, &sock_union.sin.sin_addr, peerip,
+ INET6_ADDRSTRLEN+1);
+ inet_ntop (AF_INET, &(((struct sockaddr_in *)&cs->trans->myinfo.sockaddr)->sin_addr),
+ myip, INET6_ADDRSTRLEN + 1);
+
break;
default:
break;
@@ -948,7 +969,7 @@ nlm4_establish_callback (void *csarg)
}
/* looks like libc rpc supports only ipv4 */
- port = pmap_getport ((struct sockaddr_in*)sockaddr, NLM_PROGRAM,
+ port = pmap_getport (&sock_union.sin, NLM_PROGRAM,
NLM_V4, IPPROTO_TCP);
if (port == 0) {
@@ -980,6 +1001,13 @@ nlm4_establish_callback (void *csarg)
gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_dynstr error");
goto err;
}
+
+ /* needed in case virtual IP is used */
+ ret = dict_set_dynstr (options, "transport.socket.source-addr",
+ gf_strdup (myip));
+ if (ret == -1)
+ goto err;
+
ret = dict_set_str (options, "auth-null", "on");
if (ret == -1) {
gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_dynstr error");
@@ -992,32 +1020,25 @@ nlm4_establish_callback (void *csarg)
gf_log (GF_NLM, GF_LOG_ERROR, "rpc_clnt NULL");
goto err;
}
- nlm_condmutex_t *cm;
- cm = GF_CALLOC (1, sizeof(*cm), gf_nfs_mt_nlm4_cm);
- pthread_mutex_init (&cm->mutex, NULL);
- pthread_cond_init (&cm->cond, NULL);
- ret = rpc_clnt_register_notify (rpc_clnt, nlm_rpcclnt_notify,
- cm);
+
+ ret = rpc_clnt_register_notify (rpc_clnt, nlm_rpcclnt_notify, cs);
if (ret == -1) {
gf_log (GF_NLM, GF_LOG_ERROR,"rpc_clnt_register_connect error");
goto err;
}
+
+ /* After this connect succeeds, granted msg is sent in notify */
ret = rpc_transport_connect (rpc_clnt->conn.trans, port);
- pthread_cond_wait (&cm->cond, &cm->mutex);
- pthread_mutex_destroy (&cm->mutex);
- GF_FREE (cm);
- rpc_clnt_set_connected (&rpc_clnt->conn);
- ret = nlm_set_rpc_clnt (rpc_clnt, caller_name);
- if (ret == -1) {
- gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_ptr error");
- goto err;
- }
- nlm4svc_send_granted (cs);
+
+ if (ret == -1 && EINPROGRESS == errno)
+ ret = 0;
+
err:
- if (rpc_clnt) {
+ if (ret == -1 && rpc_clnt) {
rpc_clnt_unref (rpc_clnt);
}
- return NULL;
+
+ return rpc_clnt;
}
void
@@ -1030,32 +1051,28 @@ nlm4svc_send_granted (nfs3_call_state_t *cs)
struct iobuf *iobuf = NULL;
struct iobref *iobref = NULL;
char peerip[INET6_ADDRSTRLEN+1];
- pthread_t thr;
- struct sockaddr_storage sa;
- struct sockaddr *sockaddr = NULL;
+ union gf_sock_union sock_union;
+ rpc_clnt = nlm_get_rpc_clnt (cs->args.nlm4_lockargs.alock.caller_name);
+ if (rpc_clnt == NULL) {
+ nlm4_establish_callback ((void*)cs);
+ return;
+ }
+
+ rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sock_union.storage,
+ sizeof (sock_union.storage));
- rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sa, sizeof (sa));
- sockaddr = (struct sockaddr*) &sa;
- switch (sockaddr->sa_family) {
+ switch (sock_union.sa.sa_family) {
case AF_INET6:
- inet_ntop (AF_INET6,
- &((struct sockaddr_in6 *)sockaddr)->sin6_addr,
- peerip, INET6_ADDRSTRLEN+1);
+ inet_ntop (AF_INET6, &sock_union.sin6.sin6_addr, peerip,
+ INET6_ADDRSTRLEN+1);
break;
case AF_INET:
- inet_ntop (AF_INET,
- &((struct sockaddr_in *)sockaddr)->sin_addr,
- peerip, INET6_ADDRSTRLEN+1);
+ inet_ntop (AF_INET, &sock_union.sin.sin_addr, peerip,
+ INET6_ADDRSTRLEN+1);
+ break;
default:
break;
- /* FIXME: handle the error */
- }
-
- rpc_clnt = nlm_get_rpc_clnt (cs->args.nlm4_lockargs.alock.caller_name);
- if (rpc_clnt == NULL) {
- pthread_create (&thr, NULL, nlm4_establish_callback, (void*)cs);
- return;
}
testargs.cookie = cs->args.nlm4_lockargs.cookie;
@@ -1080,13 +1097,15 @@ nlm4svc_send_granted (nfs3_call_state_t *cs)
goto ret;
}
- iobref_add (iobref, iobuf);
+ ret = iobref_add (iobref, iobuf);
+ if (ret) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to add iob to iobref");
+ goto ret;
+ }
ret = rpc_clnt_submit (rpc_clnt, &nlm4clntprog, NLM4_GRANTED,
- nlm4svc_send_granted_cbk,
- &outmsg, 1,
- NULL,
- 0, iobref, cs->frame, NULL, 0,
+ nlm4svc_send_granted_cbk, &outmsg, 1,
+ NULL, 0, iobref, cs->frame, NULL, 0,
NULL, 0, NULL);
if (ret < 0) {
@@ -1281,12 +1300,11 @@ nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
caller_name = cs->args.nlm4_lockargs.alock.caller_name;
- transit_cnt = nlm_dec_transit_count (cs->fd,
- caller_name);
+ transit_cnt = nlm_dec_transit_count (cs->fd, caller_name);
+
if (op_ret == -1) {
if (transit_cnt == 0)
- nlm_search_and_delete (cs->fd,
- caller_name);
+ nlm_search_and_delete (cs->fd, caller_name);
stat = nlm4_errno_to_nlm4stat (op_errno);
goto err;
} else {
@@ -1300,6 +1318,7 @@ nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
err:
if (cs->args.nlm4_lockargs.block) {
cs->frame = copy_frame (frame);
+ frame->local = NULL;
nlm4svc_send_granted (cs);
} else {
nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie,
@@ -1794,25 +1813,38 @@ nlm4_add_share_to_inode (nlm_share_t *share)
struct list_head *head = NULL;
xlator_t *this = NULL;
inode_t *inode = NULL;
+ struct nfs_inode_ctx *ictx = NULL;
+ struct nfs_state *priv = NULL;
this = THIS;
+ priv = this->private;
inode = share->inode;
ret = inode_ctx_get (inode, this, &ctx);
- head = (struct list_head *)ctx;
-
- if (ret || !head) {
- head = GF_CALLOC (1, sizeof (struct list_head),
- gf_common_mt_list_head);
- if (!head ) {
+ if (ret == -1) {
+ ictx = GF_CALLOC (1, sizeof (struct nfs_inode_ctx),
+ gf_nfs_mt_inode_ctx);
+ if (!ictx ) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "could not allocate nfs inode ctx");
ret = -1;
goto out;
}
+ ictx->generation = priv->generation;
+ head = &ictx->shares;
INIT_LIST_HEAD (head);
- ret = inode_ctx_put (inode, this, (uint64_t)head);
- if (ret)
+
+ ret = inode_ctx_put (inode, this, (uint64_t)ictx);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "could not store share list");
goto out;
+ }
+ }
+ else {
+ ictx = (struct nfs_inode_ctx *)ctx;
+ head = &ictx->shares;
}
list_add (&share->inode_list, head);
@@ -1834,6 +1866,7 @@ nlm4_approve_share_reservation (nfs3_call_state_t *cs)
inode_t *inode = NULL;
nlm_share_t *share = NULL;
struct list_head *head = NULL;
+ struct nfs_inode_ctx *ictx = NULL;
if (!cs)
goto out;
@@ -1845,8 +1878,9 @@ nlm4_approve_share_reservation (nfs3_call_state_t *cs)
ret = 0;
goto out;
}
+ ictx = (struct nfs_inode_ctx *)ctx;
- head = (struct list_head *)ctx;
+ head = &ictx->shares;
if (!head || list_empty (head))
goto out;
@@ -1916,8 +1950,7 @@ nlm4_create_share_reservation (nfs3_call_state_t *cs)
out:
if (ret && inode) {
inode_unref (inode);
- if (share)
- GF_FREE (share);
+ GF_FREE (share);
}
UNLOCK (&nlm_client_list_lk);
@@ -2020,18 +2053,19 @@ nlm4svc_share (rpcsvc_request_t *req)
int
nlm4_remove_share_reservation (nfs3_call_state_t *cs)
{
- int ret = -1;
- uint64_t ctx = 0;
- fsh_mode req_mode = 0;
- fsh_access req_access = 0;
- nlm_share_t *share = NULL;
- nlm_share_t *tmp = NULL;
- nlm_client_t *client = NULL;
- char *caller = NULL;
- inode_t *inode = NULL;
- xlator_t *this = NULL;
- struct list_head *head = NULL;
- nlm4_shareargs *args = NULL;
+ int ret = -1;
+ uint64_t ctx = 0;
+ fsh_mode req_mode = 0;
+ fsh_access req_access = 0;
+ nlm_share_t *share = NULL;
+ nlm_share_t *tmp = NULL;
+ nlm_client_t *client = NULL;
+ char *caller = NULL;
+ inode_t *inode = NULL;
+ xlator_t *this = NULL;
+ struct list_head *head = NULL;
+ nlm4_shareargs *args = NULL;
+ struct nfs_inode_ctx *ictx = NULL;
LOCK (&nlm_client_list_lk);
@@ -2061,8 +2095,9 @@ nlm4_remove_share_reservation (nfs3_call_state_t *cs)
inode->gfid, caller);
goto out;
}
+ ictx = (struct nfs_inode_ctx *)ctx;
- head = (struct list_head *)ctx;
+ head = &ictx->shares;
if (list_empty (head)) {
ret = -1;
goto out;
@@ -2258,34 +2293,34 @@ nlm4svc_sm_notify (struct nlm_sm_status *status)
rpcsvc_actor_t nlm4svc_actors[NLM4_PROC_COUNT] = {
/* 0 */
- {"NULL", NLM4_NULL, nlm4svc_null, NULL, NULL},
- {"TEST", NLM4_TEST, nlm4svc_test, NULL, NULL},
- {"LOCK", NLM4_LOCK, nlm4svc_lock, NULL, NULL},
- {"CANCEL", NLM4_CANCEL, nlm4svc_cancel, NULL, NULL},
- {"UNLOCK", NLM4_UNLOCK, nlm4svc_unlock, NULL, NULL},
+ {"NULL", NLM4_NULL, nlm4svc_null, NULL, 0, DRC_IDEMPOTENT},
+ {"TEST", NLM4_TEST, nlm4svc_test, NULL, 0, DRC_IDEMPOTENT},
+ {"LOCK", NLM4_LOCK, nlm4svc_lock, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"CANCEL", NLM4_CANCEL, nlm4svc_cancel, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"UNLOCK", NLM4_UNLOCK, nlm4svc_unlock, NULL, 0, DRC_NON_IDEMPOTENT},
/* 5 */
- {"GRANTED", NLM4_GRANTED, NULL, NULL, NULL},
- {"TEST", NLM4_TEST_MSG, NULL, NULL, NULL},
- {"LOCK", NLM4_LOCK_MSG, NULL, NULL, NULL},
- {"CANCEL", NLM4_CANCEL_MSG, NULL, NULL, NULL},
- {"UNLOCK", NLM4_UNLOCK_MSG, NULL, NULL, NULL},
+ {"GRANTED", NLM4_GRANTED, NULL, NULL, 0, DRC_NA},
+ {"TEST", NLM4_TEST_MSG, NULL, NULL, 0, DRC_NA},
+ {"LOCK", NLM4_LOCK_MSG, NULL, NULL, 0, DRC_NA},
+ {"CANCEL", NLM4_CANCEL_MSG, NULL, NULL, 0, DRC_NA},
+ {"UNLOCK", NLM4_UNLOCK_MSG, NULL, NULL, 0, DRC_NA},
/* 10 */
- {"GRANTED", NLM4_GRANTED_MSG, NULL, NULL, NULL},
- {"TEST", NLM4_TEST_RES, NULL, NULL, NULL},
- {"LOCK", NLM4_LOCK_RES, NULL, NULL, NULL},
- {"CANCEL", NLM4_CANCEL_RES, NULL, NULL, NULL},
- {"UNLOCK", NLM4_UNLOCK_RES, NULL, NULL, NULL},
+ {"GRANTED", NLM4_GRANTED_MSG, NULL, NULL, 0, DRC_NA},
+ {"TEST", NLM4_TEST_RES, NULL, NULL, 0, DRC_NA},
+ {"LOCK", NLM4_LOCK_RES, NULL, NULL, 0, DRC_NA},
+ {"CANCEL", NLM4_CANCEL_RES, NULL, NULL, 0, DRC_NA},
+ {"UNLOCK", NLM4_UNLOCK_RES, NULL, NULL, 0, DRC_NA},
/* 15 ; procedures 17,18,19 are not defined by nlm */
- {"GRANTED", NLM4_GRANTED_RES, NULL, NULL, NULL},
- {"SM_NOTIFY", NLM4_SM_NOTIFY, NULL, NULL, NULL},
- {"SEVENTEEN", NLM4_SEVENTEEN, NULL, NULL, NULL},
- {"EIGHTEEN", NLM4_EIGHTEEN, NULL, NULL, NULL},
- {"NINETEEN", NLM4_NINETEEN, NULL, NULL, NULL},
+ {"GRANTED", NLM4_GRANTED_RES, NULL, NULL, 0, DRC_NA},
+ {"SM_NOTIFY", NLM4_SM_NOTIFY, NULL, NULL, 0, DRC_NA},
+ {"SEVENTEEN", NLM4_SEVENTEEN, NULL, NULL, 0, DRC_NA},
+ {"EIGHTEEN", NLM4_EIGHTEEN, NULL, NULL, 0, DRC_NA},
+ {"NINETEEN", NLM4_NINETEEN, NULL, NULL, 0, DRC_NA},
/* 20 */
- {"SHARE", NLM4_SHARE, nlm4svc_share, NULL, NULL},
- {"UNSHARE", NLM4_UNSHARE, nlm4svc_unshare, NULL, NULL},
- {"NM_LOCK", NLM4_NM_LOCK, nlm4svc_nm_lock, NULL, NULL},
- {"FREE_ALL", NLM4_FREE_ALL, nlm4svc_free_all, NULL, NULL},
+ {"SHARE", NLM4_SHARE, nlm4svc_share, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"UNSHARE", NLM4_UNSHARE, nlm4svc_unshare, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"NM_LOCK", NLM4_NM_LOCK, nlm4svc_nm_lock, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"FREE_ALL", NLM4_FREE_ALL, nlm4svc_free_all, NULL, 0, DRC_IDEMPOTENT},
};
rpcsvc_program_t nlm4prog = {
@@ -2321,9 +2356,14 @@ nlm4svc_init(xlator_t *nfsx)
int ret = -1;
char *portstr = NULL;
pthread_t thr;
- struct timeval timeout = {0,};
+ struct timespec timeout = {0,};
FILE *pidfile = NULL;
pid_t pid = -1;
+ static gf_boolean_t nlm4_inited = _gf_false;
+
+ /* Already inited */
+ if (nlm4_inited)
+ return &nlm4prog;
nfs = (struct nfs_state*)nfsx->private;
@@ -2369,7 +2409,7 @@ nlm4svc_init(xlator_t *nfsx)
goto err;
}
- rpcsvc_create_listeners (nfs->rpcsvc, options, "NLM");
+ ret = rpcsvc_create_listeners (nfs->rpcsvc, options, "NLM");
if (ret == -1) {
gf_log (GF_NLM, GF_LOG_ERROR, "Unable to create listeners");
dict_unref (options);
@@ -2425,7 +2465,10 @@ nlm4svc_init(xlator_t *nfsx)
pthread_create (&thr, NULL, nsm_thread, (void*)NULL);
timeout.tv_sec = nlm_grace_period;
+ timeout.tv_nsec = 0;
+
gf_timer_call_after (nfsx->ctx, timeout, nlm_grace_period_over, NULL);
+ nlm4_inited = _gf_true;
return &nlm4prog;
err:
return NULL;
@@ -2444,7 +2487,8 @@ nlm_priv (xlator_t *this)
gf_proc_dump_add_section("nfs.nlm");
- LOCK (&nlm_client_list_lk);
+ if (TRY_LOCK (&nlm_client_list_lk))
+ goto out;
list_for_each_entry (client, &nlm_client_list, nlm_clients) {
@@ -2467,7 +2511,15 @@ nlm_priv (xlator_t *this)
gf_proc_dump_build_key (key, "nlm", "client-count");
gf_proc_dump_write (key, "%d", client_count);
-
+ ret = 0;
UNLOCK (&nlm_client_list_lk);
+
+ out:
+ if (ret) {
+ gf_proc_dump_build_key (key, "nlm", "statedump_error");
+ gf_proc_dump_write (key, "Unable to dump nlm state because "
+ "nlm_client_list_lk lock couldn't be acquired");
+ }
+
return ret;
}