diff options
Diffstat (limited to 'xlators/nfs/server/src/nlm4.c')
| -rw-r--r-- | xlators/nfs/server/src/nlm4.c | 268 |
1 files changed, 150 insertions, 118 deletions
diff --git a/xlators/nfs/server/src/nlm4.c b/xlators/nfs/server/src/nlm4.c index 4ee3596fd..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,50 +886,64 @@ 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; - union gf_sock_union sock_union; - 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)); + switch (sock_union.sa.sa_family) { case AF_INET6: /* can not come here as NLM listens on IPv4 */ @@ -939,6 +959,9 @@ nlm4_establish_callback (void *csarg) case AF_INET: 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; @@ -978,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"); @@ -990,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 @@ -1028,12 +1051,17 @@ nlm4svc_send_granted (nfs3_call_state_t *cs) struct iobuf *iobuf = NULL; struct iobref *iobref = NULL; char peerip[INET6_ADDRSTRLEN+1]; - pthread_t thr; 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)); + switch (sock_union.sa.sa_family) { case AF_INET6: inet_ntop (AF_INET6, &sock_union.sin6.sin6_addr, peerip, @@ -1042,15 +1070,9 @@ nlm4svc_send_granted (nfs3_call_state_t *cs) case AF_INET: 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; @@ -1075,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) { @@ -1276,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 { @@ -1295,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, @@ -1797,7 +1821,7 @@ nlm4_add_share_to_inode (nlm_share_t *share) inode = share->inode; ret = inode_ctx_get (inode, this, &ctx); - if (ret || !head) { + if (ret == -1) { ictx = GF_CALLOC (1, sizeof (struct nfs_inode_ctx), gf_nfs_mt_inode_ctx); if (!ictx ) { @@ -2269,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}, - {"TEST", NLM4_TEST, nlm4svc_test, NULL}, - {"LOCK", NLM4_LOCK, nlm4svc_lock, NULL}, - {"CANCEL", NLM4_CANCEL, nlm4svc_cancel, NULL}, - {"UNLOCK", NLM4_UNLOCK, nlm4svc_unlock, 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}, - {"TEST", NLM4_TEST_MSG, NULL, NULL}, - {"LOCK", NLM4_LOCK_MSG, NULL, NULL}, - {"CANCEL", NLM4_CANCEL_MSG, NULL, NULL}, - {"UNLOCK", NLM4_UNLOCK_MSG, 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}, - {"TEST", NLM4_TEST_RES, NULL, NULL}, - {"LOCK", NLM4_LOCK_RES, NULL, NULL}, - {"CANCEL", NLM4_CANCEL_RES, NULL, NULL}, - {"UNLOCK", NLM4_UNLOCK_RES, 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}, - {"SM_NOTIFY", NLM4_SM_NOTIFY, NULL, NULL}, - {"SEVENTEEN", NLM4_SEVENTEEN, NULL, NULL}, - {"EIGHTEEN", NLM4_EIGHTEEN, NULL, NULL}, - {"NINETEEN", NLM4_NINETEEN, 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}, - {"UNSHARE", NLM4_UNSHARE, nlm4svc_unshare, NULL}, - {"NM_LOCK", NLM4_NM_LOCK, nlm4svc_nm_lock, NULL}, - {"FREE_ALL", NLM4_FREE_ALL, nlm4svc_free_all, 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 = { @@ -2332,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; @@ -2380,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); @@ -2436,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; |
