diff options
| author | Krishna Srinivas <ksriniva@redhat.com> | 2012-02-20 14:34:39 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2012-02-20 07:26:51 -0800 | 
| commit | ed2036979499cb272336187c06955aa5e484023d (patch) | |
| tree | a2173280ad5753aa4d674e86e6ed66bcdcd6f973 | |
| parent | db20a0f8a99f715a77366e518720612f043d5c9e (diff) | |
NLM - Network Lock Manger V4
Change-Id: Ic31b8bb10a28408da2a623f4ecc0c60af01c64af
BUG: 795421
Signed-off-by: Krishna Srinivas <ksriniva@redhat.com>
Reviewed-on: http://review.gluster.com/2711
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amarts@redhat.com>
31 files changed, 3298 insertions, 35 deletions
diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index d4cc3464a93..ff956ec2cff 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -489,7 +489,7 @@ fd_bind (fd_t *fd)  static fd_t * -__fd_create (inode_t *inode, pid_t pid) +__fd_create (inode_t *inode, uint64_t pid)  {          fd_t *fd = NULL; @@ -535,6 +535,21 @@ fd_create (inode_t *inode, pid_t pid)  {          fd_t *fd = NULL; +        fd = __fd_create (inode, (uint64_t)pid); +        if (!fd) +                goto out; + +        fd = fd_ref (fd); + +out: +        return fd; +} + +fd_t * +fd_create_uint64 (inode_t *inode, uint64_t pid) +{ +        fd_t *fd = NULL; +          fd = __fd_create (inode, pid);          if (!fd)                  goto out; @@ -547,7 +562,7 @@ out:  static fd_t * -__fd_lookup (inode_t *inode, pid_t pid) +__fd_lookup (inode_t *inode, uint64_t pid)  {          fd_t *iter_fd = NULL;          fd_t *fd = NULL; @@ -579,13 +594,31 @@ fd_lookup (inode_t *inode, pid_t pid)          LOCK (&inode->lock);          { -                fd = __fd_lookup (inode, pid); +                fd = __fd_lookup (inode, (uint64_t)pid);          }          UNLOCK (&inode->lock);          return fd;  } +fd_t * +fd_lookup_uint64 (inode_t *inode, uint64_t pid) +{ +        fd_t *fd = NULL; + +        if (!inode) { +                gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode"); +                return NULL; +        } + +        LOCK (&inode->lock); +        { +                fd = __fd_lookup (inode, pid); +        } +        UNLOCK (&inode->lock); + +        return fd; +}  fd_t * @@ -593,10 +626,10 @@ __fd_anonymous (inode_t *inode)  {          fd_t *fd = NULL; -        fd = __fd_lookup (inode, -1); +        fd = __fd_lookup (inode, (uint64_t)-1);          if (!fd) { -                fd = __fd_create (inode, -1); +                fd = __fd_create (inode, (uint64_t)-1);                  if (!fd)                          return NULL; @@ -806,7 +839,7 @@ fd_dump (fd_t *fd, char *prefix)                  return;          memset(key, 0, sizeof(key)); -        gf_proc_dump_write("pid", "%d", fd->pid); +        gf_proc_dump_write("pid", "%llu", fd->pid);          gf_proc_dump_write("refcount", "%d", fd->refcount);          gf_proc_dump_write("flags", "%d", fd->flags);  } diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h index 6b0ed891ff0..531dd44f2a2 100644 --- a/libglusterfs/src/fd.h +++ b/libglusterfs/src/fd.h @@ -52,7 +52,7 @@ struct _fd_ctx {   * See the comment there to know why.   */  struct _fd { -        pid_t             pid; +        uint64_t             pid;  	int32_t           flags;          int32_t           refcount;          struct list_head  inode_list; @@ -130,10 +130,14 @@ fd_unref (fd_t *fd);  fd_t *  fd_create (struct _inode *inode, pid_t pid); +fd_t * +fd_create_uint64 (struct _inode *inode, uint64_t pid);  fd_t *  fd_lookup (struct _inode *inode, pid_t pid); +fd_t * +fd_lookup_uint64 (struct _inode *inode, uint64_t pid);  fd_t *  fd_anonymous (inode_t *inode); diff --git a/rpc/rpc-lib/src/rpc-clnt.c b/rpc/rpc-lib/src/rpc-clnt.c index adf6fd87620..ec73631d484 100644 --- a/rpc/rpc-lib/src/rpc-clnt.c +++ b/rpc/rpc-lib/src/rpc-clnt.c @@ -1056,6 +1056,8 @@ rpc_clnt_new (dict_t *options,                  goto out;          } +        rpc->auth_null = dict_get_str_boolean (options, "auth-null", 0); +          rpc = rpc_clnt_ref (rpc);          INIT_LIST_HEAD (&rpc->programs); @@ -1136,19 +1138,26 @@ rpc_clnt_fill_request (int prognum, int progver, int procnum,          request->rm_call.cb_vers = progver;          request->rm_call.cb_proc = procnum; -        /* TODO: Using AUTH_GLUSTERFS for time-being. Make it modular in -         * future so it is easy to plug-in new authentication schemes. +        /* TODO: Using AUTH_(GLUSTERFS/NULL) in a kludgy way for time-being. +         * Make it modular in future so it is easy to plug-in new +         * authentication schemes.           */ -        ret = xdr_serialize_glusterfs_auth (auth_data, au); -        if (ret == -1) { -                gf_log ("rpc-clnt", GF_LOG_DEBUG, "cannot encode credentials"); -                goto out; -        } - -        request->rm_call.cb_cred.oa_flavor = AUTH_GLUSTERFS_v2; -        request->rm_call.cb_cred.oa_base   = auth_data; -        request->rm_call.cb_cred.oa_length = ret; +        if (auth_data) { +                ret = xdr_serialize_glusterfs_auth (auth_data, au); +                if (ret == -1) { +                        gf_log ("rpc-clnt", GF_LOG_DEBUG, +                                "cannot encode credentials"); +                        goto out; +                } +                request->rm_call.cb_cred.oa_flavor = AUTH_GLUSTERFS_v2; +                request->rm_call.cb_cred.oa_base   = auth_data; +                request->rm_call.cb_cred.oa_length = ret; +        } else { +                request->rm_call.cb_cred.oa_flavor = AUTH_NULL; +                request->rm_call.cb_cred.oa_base   = NULL; +                request->rm_call.cb_cred.oa_length = 0; +        }          request->rm_call.cb_verf.oa_flavor = AUTH_NONE;          request->rm_call.cb_verf.oa_base = NULL;          request->rm_call.cb_verf.oa_length = 0; @@ -1228,8 +1237,13 @@ rpc_clnt_record_build_record (struct rpc_clnt *clnt, int prognum, int progver,          record = iobuf_ptr (request_iob);  /* Now we have it. */          /* Fill the rpc structure and XDR it into the buffer got above. */ -        ret = rpc_clnt_fill_request (prognum, progver, procnum, xid, -                                     au, &request, auth_data); +        if (clnt->auth_null) +                ret = rpc_clnt_fill_request (prognum, progver, procnum, +                                             xid, NULL, &request, NULL); +        else +                ret = rpc_clnt_fill_request (prognum, progver, procnum, +                                             xid, au, &request, auth_data); +          if (ret == -1) {                  gf_log (clnt->conn.trans->name, GF_LOG_WARNING,                          "cannot build a rpc-request xid (%"PRIu64")", xid); diff --git a/rpc/rpc-lib/src/rpc-clnt.h b/rpc/rpc-lib/src/rpc-clnt.h index 7034da70584..dcd926da93f 100644 --- a/rpc/rpc-lib/src/rpc-clnt.h +++ b/rpc/rpc-lib/src/rpc-clnt.h @@ -169,7 +169,7 @@ struct rpc_req {          void                  *conn_private;  }; -struct rpc_clnt { +typedef struct rpc_clnt {          pthread_mutex_t        lock;          rpc_clnt_notify_t      notifyfn;          rpc_clnt_connection_t  conn; @@ -186,7 +186,8 @@ struct rpc_clnt {          glusterfs_ctx_t       *ctx;          int                   refcount; -}; +        int                   auth_null; +} rpc_clnt_t;  struct rpc_clnt *rpc_clnt_new (dict_t *options, glusterfs_ctx_t *ctx, @@ -229,7 +230,6 @@ rpc_clnt_unref (struct rpc_clnt *rpc);  void rpc_clnt_set_connected (rpc_clnt_connection_t *conn);  void rpc_clnt_unset_connected (rpc_clnt_connection_t *conn); -  void rpc_clnt_reconnect (void *trans_ptr);  void rpc_clnt_reconfig (struct rpc_clnt *rpc, struct rpc_clnt_config *config); diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h index b1547670484..5b297d8cfc5 100644 --- a/rpc/rpc-lib/src/rpcsvc.h +++ b/rpc/rpc-lib/src/rpcsvc.h @@ -265,6 +265,7 @@ struct rpcsvc_request {  #define rpcsvc_request_set_vecstate(req, state)  ((req)->vecstate = state)  #define rpcsvc_request_vecstate(req) ((req)->vecstate)  #define rpcsvc_request_transport(req) ((req)->trans) +#define rpcsvc_request_transport_ref(req) (rpc_transport_ref((req)->trans))  #define RPCSVC_ACTOR_SUCCESS    0 diff --git a/rpc/xdr/src/Makefile.am b/rpc/xdr/src/Makefile.am index 57c19338782..7174815b841 100644 --- a/rpc/xdr/src/Makefile.am +++ b/rpc/xdr/src/Makefile.am @@ -14,11 +14,13 @@ libgfxdr_la_SOURCES =  xdr-generic.c rpc-common-xdr.c \  			cli1-xdr.c \  			glusterd1-xdr.c \  			portmap-xdr.c \ -			xdr-nfs3.c msg-nfs3.c +			nlm4-xdr.c xdr-nfs3.c msg-nfs3.c nsm-xdr.c \ +			nlmcbk-xdr.c  noinst_HEADERS = xdr-generic.h rpc-common-xdr.h \  		glusterfs3-xdr.h glusterfs3.h \  		cli1-xdr.h \  		glusterd1-xdr.h \  		portmap-xdr.h \ -		xdr-nfs3.h msg-nfs3.h +		nlm4-xdr.h xdr-nfs3.h msg-nfs3.h nsm-xdr.h \ +		nlmcbk-xdr.h diff --git a/rpc/xdr/src/msg-nfs3.c b/rpc/xdr/src/msg-nfs3.c index 5fc92123cee..f800b3128fa 100644 --- a/rpc/xdr/src/msg-nfs3.c +++ b/rpc/xdr/src/msg-nfs3.c @@ -474,4 +474,59 @@ xdr_serialize_nfsstat3 (struct iovec outmsg, nfsstat3 *s)                                            (xdrproc_t)xdr_nfsstat3);  } +ssize_t +xdr_to_nlm4_testargs (struct iovec inmsg, nlm4_testargs *args) +{ +        return xdr_to_generic (inmsg, (void*)args, +                               (xdrproc_t)xdr_nlm4_testargs); +} + +ssize_t +xdr_serialize_nlm4_testres (struct iovec outmsg, nlm4_testres *res) +{ +        return xdr_serialize_generic (outmsg, (void*)res, +                                      (xdrproc_t)xdr_nlm4_testres); +} + +ssize_t +xdr_to_nlm4_lockargs (struct iovec inmsg, nlm4_lockargs *args) +{ +        return xdr_to_generic (inmsg, (void*)args, +                               (xdrproc_t)xdr_nlm4_lockargs); +} + +ssize_t +xdr_serialize_nlm4_res (struct iovec outmsg, nlm4_res *res) +{ +        return xdr_serialize_generic (outmsg, (void*)res, +                                      (xdrproc_t)xdr_nlm4_res); +} + +ssize_t +xdr_to_nlm4_cancelargs (struct iovec inmsg, nlm4_cancargs *args) +{ +        return xdr_to_generic (inmsg, (void*)args, +                               (xdrproc_t)xdr_nlm4_cancargs); +} + +ssize_t +xdr_to_nlm4_unlockargs (struct iovec inmsg, nlm4_unlockargs *args) +{ +        return xdr_to_generic (inmsg, (void*)args, +                               (xdrproc_t)xdr_nlm4_unlockargs); +} + +ssize_t +xdr_serialize_nlm4_testargs (struct iovec outmsg, nlm4_testargs *args) +{ +        return xdr_serialize_generic (outmsg, (void*)args, +                                      (xdrproc_t)xdr_nlm4_testargs); +} + +ssize_t +xdr_to_nlm4_res (struct iovec inmsg, nlm4_res *args) +{ +        return xdr_to_generic (inmsg, (void*)args, +                               (xdrproc_t)xdr_nlm4_res); +} diff --git a/rpc/xdr/src/msg-nfs3.h b/rpc/xdr/src/msg-nfs3.h index f828979e79f..1310e02f897 100644 --- a/rpc/xdr/src/msg-nfs3.h +++ b/rpc/xdr/src/msg-nfs3.h @@ -26,7 +26,7 @@  #endif  #include "xdr-nfs3.h" - +#include "nlm4-xdr.h"  #include <sys/types.h>  #include <sys/uio.h> @@ -183,4 +183,29 @@ xdr_serialize_mountstat3 (struct iovec outmsg, mountstat3 *m);  extern ssize_t  xdr_serialize_nfsstat3 (struct iovec outmsg, nfsstat3 *s); + +extern ssize_t +xdr_to_nlm4_testargs (struct iovec inmsg, nlm4_testargs *args); + +extern ssize_t +xdr_serialize_nlm4_testres (struct iovec outmsg, nlm4_testres *res); + +extern ssize_t +xdr_to_nlm4_lockargs (struct iovec inmsg, nlm4_lockargs *args); + +extern ssize_t +xdr_serialize_nlm4_res (struct iovec outmsg, nlm4_res *res); + +extern ssize_t +xdr_to_nlm4_cancelargs (struct iovec inmsg, nlm4_cancargs *args); + +extern ssize_t +xdr_to_nlm4_unlockargs (struct iovec inmsg, nlm4_unlockargs *args); + +extern ssize_t +xdr_serialize_nlm4_testargs (struct iovec outmsg, nlm4_testargs *args); + +extern ssize_t +xdr_to_nlm4_res (struct iovec inmsg, nlm4_res *args); +  #endif diff --git a/rpc/xdr/src/nlm4-xdr.c b/rpc/xdr/src/nlm4-xdr.c new file mode 100644 index 00000000000..b41fbb15cac --- /dev/null +++ b/rpc/xdr/src/nlm4-xdr.c @@ -0,0 +1,243 @@ +/* +  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/>. +*/ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "nlm4-xdr.h" + +bool_t +xdr_netobj (XDR *xdrs, netobj *objp) +{ +	 if (!xdr_bytes (xdrs, (char **)&objp->n_bytes, (u_int *) &objp->n_len, MAXNETOBJ_SZ)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fsh_mode (XDR *xdrs, fsh_mode *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fsh_access (XDR *xdrs, fsh_access *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_stats (XDR *xdrs, nlm4_stats *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_stat (XDR *xdrs, nlm4_stat *objp) +{ +	 if (!xdr_nlm4_stats (xdrs, &objp->stat)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_holder (XDR *xdrs, nlm4_holder *objp) +{ +	 if (!xdr_bool (xdrs, &objp->exclusive)) +		 return FALSE; +	 if (!xdr_uint32_t (xdrs, &objp->svid)) +		 return FALSE; +	 if (!xdr_netobj (xdrs, &objp->oh)) +		 return FALSE; +	 if (!xdr_uint64_t (xdrs, &objp->l_offset)) +		 return FALSE; +	 if (!xdr_uint64_t (xdrs, &objp->l_len)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_lock (XDR *xdrs, nlm4_lock *objp) +{ +	 if (!xdr_string (xdrs, &objp->caller_name, MAXNAMELEN)) +		 return FALSE; +	 if (!xdr_netobj (xdrs, &objp->fh)) +		 return FALSE; +	 if (!xdr_netobj (xdrs, &objp->oh)) +		 return FALSE; +	 if (!xdr_uint32_t (xdrs, &objp->svid)) +		 return FALSE; +	 if (!xdr_uint64_t (xdrs, &objp->l_offset)) +		 return FALSE; +	 if (!xdr_uint64_t (xdrs, &objp->l_len)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_share (XDR *xdrs, nlm4_share *objp) +{ +	 if (!xdr_string (xdrs, &objp->caller_name, MAXNAMELEN)) +		 return FALSE; +	 if (!xdr_netobj (xdrs, &objp->fh)) +		 return FALSE; +	 if (!xdr_netobj (xdrs, &objp->oh)) +		 return FALSE; +	 if (!xdr_fsh_mode (xdrs, &objp->mode)) +		 return FALSE; +	 if (!xdr_fsh_access (xdrs, &objp->access)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_testrply (XDR *xdrs, nlm4_testrply *objp) +{ +	 if (!xdr_nlm4_stats (xdrs, &objp->stat)) +		 return FALSE; +	switch (objp->stat) { +	case nlm4_denied: +		 if (!xdr_nlm4_holder (xdrs, &objp->nlm4_testrply_u.holder)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_nlm4_testres (XDR *xdrs, nlm4_testres *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_nlm4_testrply (xdrs, &objp->stat)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_testargs (XDR *xdrs, nlm4_testargs *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->exclusive)) +		 return FALSE; +	 if (!xdr_nlm4_lock (xdrs, &objp->alock)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_res (XDR *xdrs, nlm4_res *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_nlm4_stat (xdrs, &objp->stat)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_lockargs (XDR *xdrs, nlm4_lockargs *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->block)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->exclusive)) +		 return FALSE; +	 if (!xdr_nlm4_lock (xdrs, &objp->alock)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->reclaim)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->state)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_cancargs (XDR *xdrs, nlm4_cancargs *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->block)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->exclusive)) +		 return FALSE; +	 if (!xdr_nlm4_lock (xdrs, &objp->alock)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_unlockargs (XDR *xdrs, nlm4_unlockargs *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_nlm4_lock (xdrs, &objp->alock)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_shareargs (XDR *xdrs, nlm4_shareargs *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_nlm4_share (xdrs, &objp->share)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->reclaim)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nlm4_shareres (XDR *xdrs, nlm4_shareres *objp) +{ +	 if (!xdr_netobj (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_nlm4_stats (xdrs, &objp->stat)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->sequence)) +		 return FALSE; +	return TRUE; +} + +/* +bool_t +xdr_nlm_sm_status (XDR *xdrs, nlm_sm_status *objp) +{ +	 if (!xdr_string (xdrs, &objp->mon_name, LM_MAXSTRLEN)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->state)) +		 return FALSE; +	 if (!xdr_opaque (xdrs, objp->priv, 16)) +		 return FALSE; +	return TRUE; +} +*/ diff --git a/rpc/xdr/src/nlm4-xdr.h b/rpc/xdr/src/nlm4-xdr.h new file mode 100644 index 00000000000..dd3e664bb4c --- /dev/null +++ b/rpc/xdr/src/nlm4-xdr.h @@ -0,0 +1,242 @@ +/* +  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/>. +*/ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _NLM_H_RPCGEN +#define _NLM_H_RPCGEN + +#include <rpc/rpc.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAXNETOBJ_SZ 1024 +#define LM_MAXSTRLEN 1024 +#define MAXNAMELEN 1025 + +/* + * The following enums are actually bit encoded for efficient + * boolean algebra.... DON'T change them..... + */ + +enum fsh_mode { +	fsm_DN = 0, +	fsm_DR = 1, +	fsm_DW = 2, +	fsm_DRW = 3, +}; +typedef enum fsh_mode fsh_mode; + +enum fsh_access { +	fsa_NONE = 0, +	fsa_R = 1, +	fsa_W = 2, +	fsa_RW = 3, +}; +typedef enum fsh_access fsh_access; +/* definitions for NLM version 4 */ + +enum nlm4_stats { +	nlm4_granted = 0, +	nlm4_denied = 1, +	nlm4_denied_nolock = 2, +	nlm4_blocked = 3, +	nlm4_denied_grace_period = 4, +	nlm4_deadlck = 5, +	nlm4_rofs = 6, +	nlm4_stale_fh = 7, +	nlm4_fbig = 8, +	nlm4_failed = 9, +}; +typedef enum nlm4_stats nlm4_stats; + +struct nlm4_stat { +	nlm4_stats stat; +}; +typedef struct nlm4_stat nlm4_stat; + +struct nlm4_holder { +	bool_t exclusive; +	u_int32_t svid; +	netobj oh; +	u_int64_t l_offset; +	u_int64_t l_len; +}; +typedef struct nlm4_holder nlm4_holder; + +struct nlm4_lock { +	char *caller_name; +	netobj fh; +	netobj oh; +	u_int32_t svid; +	u_int64_t l_offset; +	u_int64_t l_len; +}; +typedef struct nlm4_lock nlm4_lock; + +struct nlm4_share { +	char *caller_name; +	netobj fh; +	netobj oh; +	fsh_mode mode; +	fsh_access access; +}; +typedef struct nlm4_share nlm4_share; + +struct nlm4_testrply { +	nlm4_stats stat; +	union { +		struct nlm4_holder holder; +	} nlm4_testrply_u; +}; +typedef struct nlm4_testrply nlm4_testrply; + +struct nlm4_testres { +	netobj cookie; +	nlm4_testrply stat; +}; +typedef struct nlm4_testres nlm4_testres; + +struct nlm4_testargs { +	netobj cookie; +	bool_t exclusive; +	struct nlm4_lock alock; +}; +typedef struct nlm4_testargs nlm4_testargs; + +struct nlm4_res { +	netobj cookie; +	nlm4_stat stat; +}; +typedef struct nlm4_res nlm4_res; + +struct nlm4_lockargs { +	netobj cookie; +	bool_t block; +	bool_t exclusive; +	struct nlm4_lock alock; +	bool_t reclaim; +	int state; +}; +typedef struct nlm4_lockargs nlm4_lockargs; + +struct nlm4_cancargs { +	netobj cookie; +	bool_t block; +	bool_t exclusive; +	struct nlm4_lock alock; +}; +typedef struct nlm4_cancargs nlm4_cancargs; + +struct nlm4_unlockargs { +	netobj cookie; +	struct nlm4_lock alock; +}; +typedef struct nlm4_unlockargs nlm4_unlockargs; + +struct nlm4_shareargs { +	netobj cookie; +	nlm4_share share; +	bool_t reclaim; +}; +typedef struct nlm4_shareargs nlm4_shareargs; + +struct nlm4_shareres { +	netobj cookie; +	nlm4_stats stat; +	int sequence; +}; +typedef struct nlm4_shareres nlm4_shareres; + +#define NLM4_NULL 0 +#define NLM4_TEST 1 +#define NLM4_LOCK 2 +#define NLM4_CANCEL 3 +#define NLM4_UNLOCK 4 +#define NLM4_GRANTED 5 +#define NLM4_TEST_MSG 6 +#define NLM4_LOCK_MSG 7 +#define NLM4_CANCEL_MSG 8 +#define NLM4_UNLOCK_MSG 9 +#define NLM4_GRANTED_MSG 10 +#define NLM4_TEST_RES 11 +#define NLM4_LOCK_RES 12 +#define NLM4_CANCEL_RES 13 +#define NLM4_UNLOCK_RES 14 +#define NLM4_GRANTED_RES 15 +#define NLM4_SM_NOTIFY 16 +#define NLM4_SHARE 20 +#define NLM4_UNSHARE 21 +#define NLM4_NM_LOCK 22 +#define NLM4_FREE_ALL 23 +#define NLM4_PROC_COUNT 24 + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern  bool_t xdr_netobj (XDR *, netobj*); +extern  bool_t xdr_fsh_mode (XDR *, fsh_mode*); +extern  bool_t xdr_fsh_access (XDR *, fsh_access*); +extern  bool_t xdr_nlm4_stats (XDR *, nlm4_stats*); +extern  bool_t xdr_nlm4_stat (XDR *, nlm4_stat*); +extern  bool_t xdr_nlm4_holder (XDR *, nlm4_holder*); +extern  bool_t xdr_nlm4_lock (XDR *, nlm4_lock*); +extern  bool_t xdr_nlm4_share (XDR *, nlm4_share*); +extern  bool_t xdr_nlm4_testrply (XDR *, nlm4_testrply*); +extern  bool_t xdr_nlm4_testres (XDR *, nlm4_testres*); +extern  bool_t xdr_nlm4_testargs (XDR *, nlm4_testargs*); +extern  bool_t xdr_nlm4_res (XDR *, nlm4_res*); +extern  bool_t xdr_nlm4_lockargs (XDR *, nlm4_lockargs*); +extern  bool_t xdr_nlm4_cancargs (XDR *, nlm4_cancargs*); +extern  bool_t xdr_nlm4_unlockargs (XDR *, nlm4_unlockargs*); +extern  bool_t xdr_nlm4_shareargs (XDR *, nlm4_shareargs*); +extern  bool_t xdr_nlm4_shareres (XDR *, nlm4_shareres*); + +#else /* K&R C */ +extern bool_t xdr_netobj (); +extern bool_t xdr_fsh_mode (); +extern bool_t xdr_fsh_access (); +extern bool_t xdr_nlm4_stats (); +extern bool_t xdr_nlm4_stat (); +extern bool_t xdr_nlm4_holder (); +extern bool_t xdr_nlm4_lock (); +extern bool_t xdr_nlm4_share (); +extern bool_t xdr_nlm4_testrply (); +extern bool_t xdr_nlm4_testres (); +extern bool_t xdr_nlm4_testargs (); +extern bool_t xdr_nlm4_res (); +extern bool_t xdr_nlm4_lockargs (); +extern bool_t xdr_nlm4_cancargs (); +extern bool_t xdr_nlm4_unlockargs (); +extern bool_t xdr_nlm4_shareargs (); +extern bool_t xdr_nlm4_shareres (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_NLM_H_RPCGEN */ diff --git a/rpc/xdr/src/nlm4.x b/rpc/xdr/src/nlm4.x new file mode 100644 index 00000000000..d738b27770d --- /dev/null +++ b/rpc/xdr/src/nlm4.x @@ -0,0 +1,158 @@ +/* +  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/>. +*/ + +/* .x file defined as according to the RFC */ + +const MAXNETOBJ_SZ = 1024; +const LM_MAXSTRLEN = 1024; +const MAXNAMELEN = 1025; + +typedef opaque netobj<MAXNETOBJ_SZ>; + +#ifdef RPC_HDR +%/* +% * The following enums are actually bit encoded for efficient +% * boolean algebra.... DON'T change them..... +% */ +#endif +enum	fsh_mode { +	fsm_DN  = 0,	/* deny none */ +	fsm_DR  = 1,	/* deny read */ +	fsm_DW  = 2,	/* deny write */ +	fsm_DRW = 3	/* deny read/write */ +}; + +enum	fsh_access { +	fsa_NONE = 0,	/* for completeness */ +	fsa_R    = 1,	/* read only */ +	fsa_W    = 2,	/* write only */ +	fsa_RW   = 3	/* read/write */ +}; + +#ifdef RPC_HDR +%/* definitions for NLM version 4 */ +#endif +enum nlm4_stats { +	nlm4_granted			= 0, +	nlm4_denied			= 1, +	nlm4_denied_nolock		= 2, +	nlm4_blocked			= 3, +	nlm4_denied_grace_period	= 4, +	nlm4_deadlck			= 5, +	nlm4_rofs			= 6, +	nlm4_stale_fh			= 7, +	nlm4_fbig			= 8, +	nlm4_failed			= 9 +}; + +struct nlm4_stat { +	nlm4_stats stat; +}; + +struct nlm4_holder { +	bool exclusive; +	u_int32_t svid; +	netobj oh; +	u_int64_t l_offset; +	u_int64_t l_len; +}; + +struct nlm4_lock { +	string caller_name<MAXNAMELEN>; +	netobj fh; +	netobj oh; +	u_int32_t svid; +	u_int64_t l_offset; +	u_int64_t l_len; +}; + +struct nlm4_share { +	string caller_name<MAXNAMELEN>; +	netobj fh; +	netobj oh; +	fsh_mode mode; +	fsh_access access; +}; + +union nlm4_testrply switch (nlm4_stats stat) { +	case nlm_denied: +		struct nlm4_holder holder; +	default: +		void; +}; + +struct nlm4_testres { +	netobj cookie; +	nlm4_testrply stat; +}; + +struct nlm4_testargs { +	netobj cookie; +	bool exclusive; +	struct nlm4_lock alock; +}; + +struct nlm4_res { +	netobj cookie; +	nlm4_stat stat; +}; + +struct nlm4_lockargs { +	netobj cookie; +	bool block; +	bool exclusive; +	struct nlm4_lock alock; +	bool reclaim;		/* used for recovering locks */ +	int state;		/* specify local status monitor state */ +}; + +struct nlm4_cancargs { +	netobj cookie; +	bool block; +	bool exclusive; +	struct nlm4_lock alock; +}; + +struct nlm4_unlockargs { +	netobj cookie; +	struct nlm4_lock alock; +}; + +struct	nlm4_shareargs { +	netobj	cookie; +	nlm4_share	share; +	bool	reclaim; +}; + +struct	nlm4_shareres { +	netobj	cookie; +	nlm4_stats	stat; +	int	sequence; +}; + +/* + * argument for the procedure called by rpc.statd when a monitored host + * status change. + * XXX assumes LM_MAXSTRLEN == SM_MAXSTRLEN + */ +struct nlm_sm_status { +	string mon_name<LM_MAXSTRLEN>; /* name of host */ +	int state;			/* new state */ +	opaque priv[16];		/* private data */ +}; diff --git a/rpc/xdr/src/nlmcbk-xdr.c b/rpc/xdr/src/nlmcbk-xdr.c new file mode 100644 index 00000000000..26446ab1bf4 --- /dev/null +++ b/rpc/xdr/src/nlmcbk-xdr.c @@ -0,0 +1,37 @@ +/* +  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/>. +*/ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "nlmcbk-xdr.h" + +bool_t +xdr_nlm_sm_status (XDR *xdrs, nlm_sm_status *objp) +{ +	 if (!xdr_string (xdrs, &objp->mon_name, LM_MAXSTRLEN)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->state)) +		 return FALSE; +	 if (!xdr_opaque (xdrs, objp->priv, 16)) +		 return FALSE; +	return TRUE; +} diff --git a/rpc/xdr/src/nlmcbk-xdr.h b/rpc/xdr/src/nlmcbk-xdr.h new file mode 100644 index 00000000000..4d6d670ab38 --- /dev/null +++ b/rpc/xdr/src/nlmcbk-xdr.h @@ -0,0 +1,74 @@ +/* +  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/>. +*/ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _NLMCBK_H_RPCGEN +#define _NLMCBK_H_RPCGEN + +#include <rpc/rpc.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +#define LM_MAXSTRLEN 1024 + +struct nlm_sm_status { +	char *mon_name; +	int state; +	char priv[16]; +}; +typedef struct nlm_sm_status nlm_sm_status; + +#define NLMCBK_PROGRAM 100021 +#define NLMCBK_V1 1 + +#if defined(__STDC__) || defined(__cplusplus) +#define NLMCBK_SM_NOTIFY 16 +extern  void * nlmcbk_sm_notify_0(struct nlm_sm_status *, CLIENT *); +extern  void * nlmcbk_sm_notify_0_svc(struct nlm_sm_status *, struct svc_req *); +extern int nlmcbk_program_0_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define NLMCBK_SM_NOTIFY 16 +extern  void * nlmcbk_sm_notify_0(); +extern  void * nlmcbk_sm_notify_0_svc(); +extern int nlmcbk_program_0_freeresult (); +#endif /* K&R C */ + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern  bool_t xdr_nlm_sm_status (XDR *, nlm_sm_status*); + +#else /* K&R C */ +extern bool_t xdr_nlm_sm_status (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_NLMCBK_H_RPCGEN */ diff --git a/rpc/xdr/src/nlmcbk.x b/rpc/xdr/src/nlmcbk.x new file mode 100644 index 00000000000..49901047eb3 --- /dev/null +++ b/rpc/xdr/src/nlmcbk.x @@ -0,0 +1,33 @@ +/* +  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/>. +*/ + +const LM_MAXSTRLEN = 1024; + +struct nlm_sm_status { +        string mon_name<LM_MAXSTRLEN>; /* name of host */ +        int state;                      /* new state */ +        opaque priv[16];                /* private data */ +}; + +program NLMCBK_PROGRAM { +	version NLMCBK_V0 { +		void NLMCBK_SM_NOTIFY(struct nlm_sm_status) = 1; +	} = 0; +} = 1238477; + diff --git a/rpc/xdr/src/nsm-xdr.c b/rpc/xdr/src/nsm-xdr.c new file mode 100644 index 00000000000..8c41b4365a2 --- /dev/null +++ b/rpc/xdr/src/nsm-xdr.c @@ -0,0 +1,105 @@ +/* +  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/>. +*/ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "nsm-xdr.h" + +bool_t +xdr_sm_name (XDR *xdrs, sm_name *objp) +{ +	 if (!xdr_string (xdrs, &objp->mon_name, SM_MAXSTRLEN)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_res (XDR *xdrs, res *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_sm_stat_res (XDR *xdrs, sm_stat_res *objp) +{ +	 if (!xdr_res (xdrs, &objp->res_stat)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->state)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_sm_stat (XDR *xdrs, sm_stat *objp) +{ +	 if (!xdr_int (xdrs, &objp->state)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_my_id (XDR *xdrs, my_id *objp) +{ +	 if (!xdr_string (xdrs, &objp->my_name, SM_MAXSTRLEN)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->my_prog)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->my_vers)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->my_proc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mon_id (XDR *xdrs, mon_id *objp) +{ +	 if (!xdr_string (xdrs, &objp->mon_name, SM_MAXSTRLEN)) +		 return FALSE; +	 if (!xdr_my_id (xdrs, &objp->my_id)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mon (XDR *xdrs, mon *objp) +{ +	 if (!xdr_mon_id (xdrs, &objp->mon_id)) +		 return FALSE; +	 if (!xdr_opaque (xdrs, objp->priv, 16)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nsm_callback_status (XDR *xdrs, nsm_callback_status *objp) +{ +	 if (!xdr_string (xdrs, &objp->mon_name, SM_MAXSTRLEN)) +		 return FALSE; +	 if (!xdr_int (xdrs, &objp->state)) +		 return FALSE; +	 if (!xdr_opaque (xdrs, objp->priv, 16)) +		 return FALSE; +	return TRUE; +} diff --git a/rpc/xdr/src/nsm-xdr.h b/rpc/xdr/src/nsm-xdr.h new file mode 100644 index 00000000000..9de642c1572 --- /dev/null +++ b/rpc/xdr/src/nsm-xdr.h @@ -0,0 +1,95 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _NSM_H_RPCGEN +#define _NSM_H_RPCGEN + +#include <rpc/rpc.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +#define SM_MAXSTRLEN 1024 + +struct sm_name { +	char *mon_name; +}; +typedef struct sm_name sm_name; + +enum res { +	STAT_SUCC = 0, +	STAT_FAIL = 1, +}; +typedef enum res res; + +struct sm_stat_res { +	res res_stat; +	int state; +}; +typedef struct sm_stat_res sm_stat_res; + +struct sm_stat { +	int state; +}; +typedef struct sm_stat sm_stat; + +struct my_id { +	char *my_name; +	int my_prog; +	int my_vers; +	int my_proc; +}; +typedef struct my_id my_id; + +struct mon_id { +	char *mon_name; +	struct my_id my_id; +}; +typedef struct mon_id mon_id; + +struct mon { +	struct mon_id mon_id; +	char priv[16]; +}; +typedef struct mon mon; + +struct nsm_callback_status { +	char *mon_name; +	int state; +	char priv[16]; +}; +typedef struct nsm_callback_status nsm_callback_status; + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern  bool_t xdr_sm_name (XDR *, sm_name*); +extern  bool_t xdr_res (XDR *, res*); +extern  bool_t xdr_sm_stat_res (XDR *, sm_stat_res*); +extern  bool_t xdr_sm_stat (XDR *, sm_stat*); +extern  bool_t xdr_my_id (XDR *, my_id*); +extern  bool_t xdr_mon_id (XDR *, mon_id*); +extern  bool_t xdr_mon (XDR *, mon*); +extern  bool_t xdr_nsm_callback_status (XDR *, nsm_callback_status*); + +#else /* K&R C */ +extern bool_t xdr_sm_name (); +extern bool_t xdr_res (); +extern bool_t xdr_sm_stat_res (); +extern bool_t xdr_sm_stat (); +extern bool_t xdr_my_id (); +extern bool_t xdr_mon_id (); +extern bool_t xdr_mon (); +extern bool_t xdr_nsm_callback_status (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_NSM_H_RPCGEN */ diff --git a/rpc/xdr/src/nsm.x b/rpc/xdr/src/nsm.x new file mode 100644 index 00000000000..8f97b1aaa1f --- /dev/null +++ b/rpc/xdr/src/nsm.x @@ -0,0 +1,47 @@ +/* + * This defines the maximum length of the string + * identifying the caller. + */ +const SM_MAXSTRLEN = 1024; + +struct sm_name { +    string mon_name<SM_MAXSTRLEN>; +}; + +enum res { +    STAT_SUCC = 0,   /*  NSM agrees to monitor.  */ +    STAT_FAIL = 1    /*  NSM cannot monitor.  */ +}; + +struct sm_stat_res { +    res    res_stat; +    int    state; +}; + +struct sm_stat { +    int    state;    /*  state number of NSM  */ +}; + +struct my_id { +    string my_name<SM_MAXSTRLEN>;  /*  hostname  */ +    int    my_prog;                /*  RPC program number  */ +    int    my_vers;                /*  program version number  */ +    int    my_proc;                /*  procedure number  */ +}; + +struct mon_id { +    string mon_name<SM_MAXSTRLEN>; /* name of the host to be monitored */ +    struct my_id my_id; +}; + +struct mon { +    struct mon_id mon_id; +    opaque    priv[16];        /*  private information  */ +}; + +struct nsm_callback_status { +    string mon_name<SM_MAXSTRLEN>; +    int    state; +    opaque priv[16];        /*  for private information  */ +}; + diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c index bd30ca4937d..17bc802a000 100644 --- a/xlators/features/locks/src/posix.c +++ b/xlators/features/locks/src/posix.c @@ -284,6 +284,27 @@ unwind:          return 0;  } +int +pl_locks_by_fd (pl_inode_t *pl_inode, fd_t *fd) +{ +       posix_lock_t *l = NULL; +       int found = 0; + +       pthread_mutex_lock (&pl_inode->mutex); +       { + +               list_for_each_entry (l, &pl_inode->ext_list, list) { +                       if ((l->fd_num == fd_to_fdnum(fd))) { +                               found = 1; +                               break; +                       } +               } + +       } +       pthread_mutex_unlock (&pl_inode->mutex); +       return found; +} +  static void  delete_locks_of_fd (xlator_t *this, pl_inode_t *pl_inode, fd_t *fd)  { @@ -1219,6 +1240,12 @@ pl_lk (call_frame_t *frame, xlator_t *this,  unwind:          pl_trace_out (this, frame, fd, NULL, cmd, flock, op_ret, op_errno, NULL);          pl_update_refkeeper (this, fd->inode); + +        if (pl_locks_by_fd(pl_inode, fd)) +                flock->l_type = F_RDLCK; +        else +                flock->l_type = F_UNLCK; +          STACK_UNWIND_STRICT (lk, frame, op_ret, op_errno, flock);  out:          return 0; diff --git a/xlators/nfs/server/src/Makefile.am b/xlators/nfs/server/src/Makefile.am index 8fd28638506..a2c76a5021d 100644 --- a/xlators/nfs/server/src/Makefile.am +++ b/xlators/nfs/server/src/Makefile.am @@ -2,10 +2,10 @@ xlator_LTLIBRARIES = server.la  xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/nfs  nfsrpclibdir = $(top_srcdir)/rpc/rpc-lib/src  server_la_LDFLAGS = -module -avoidversion -server_la_SOURCES = nfs.c nfs-common.c nfs-fops.c nfs-inodes.c nfs-generics.c mount3.c nfs3-fh.c nfs3.c nfs3-helpers.c +server_la_SOURCES = nfs.c nfs-common.c nfs-fops.c nfs-inodes.c nfs-generics.c mount3.c nfs3-fh.c nfs3.c nfs3-helpers.c nlm4.c nlmcbk_svc.c  server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la -noinst_HEADERS = nfs.h nfs-common.h nfs-fops.h nfs-inodes.h nfs-generics.h mount3.h nfs3-fh.h nfs3.h nfs3-helpers.h nfs-mem-types.h +noinst_HEADERS = nfs.h nfs-common.h nfs-fops.h nfs-inodes.h nfs-generics.h mount3.h nfs3-fh.h nfs3.h nfs3-helpers.h nfs-mem-types.h nlm4.h  AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\  	-DLIBDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/auth\" \ diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c index 8774da07581..2624c50e378 100644 --- a/xlators/nfs/server/src/nfs-fops.c +++ b/xlators/nfs/server/src/nfs-fops.c @@ -121,6 +121,7 @@ nfs_create_frame (xlator_t *xl, nfs_user_t *nfu)          frame->root->pid = NFS_PID;          frame->root->uid = nfu->uid;          frame->root->gid = nfu->gids[NFS_PRIMGID_IDX]; +        frame->root->lk_owner = nfu->lk_owner;          if (nfu->ngrps == 1)                  goto err;       /* Done, we only got primary gid */ @@ -133,15 +134,13 @@ nfs_create_frame (xlator_t *xl, nfs_user_t *nfu)                  frame->root->groups[y] = nfu->gids[x];          } -        set_lk_owner_from_uint64 (&frame->root->lk_owner, nfs_frame_getctr ()); -  err:          return frame;  }  #define nfs_fop_handle_frame_create(fram, xla, nfuser, retval, errlabel)      \          do {                                                                  \ -                fram = nfs_create_frame (xla, (nfuser));                      \ +                fram = nfs_create_frame (xla, (nfuser));                \                  if (!fram) {                                                  \                          retval = (-ENOMEM);                                   \                          gf_log (GF_NFS, GF_LOG_ERROR,"Frame creation failed");\ @@ -1362,6 +1361,49 @@ err:          return ret;  } +int32_t +nfs_fop_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                int32_t op_ret, int32_t op_errno, struct gf_flock *flock) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_lk_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (nfl, progcbk, frame); + +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, flock); + +        nfs_stack_destroy (nfl, frame); +        return 0; +} + + +int +nfs_fop_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, +            int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!fd) || (!nfu)) +                return ret; + +        nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err); +        nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err); + +        STACK_WIND_COOKIE (frame, nfs_fop_lk_cbk, xl, xl, xl->fops->lk, +                           fd, cmd, flock); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (nfl, frame); +        } + +        return ret; +} +  int32_t  nfs_fop_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, diff --git a/xlators/nfs/server/src/nfs-fops.h b/xlators/nfs/server/src/nfs-fops.h index 48565215e38..2801da2c319 100644 --- a/xlators/nfs/server/src/nfs-fops.h +++ b/xlators/nfs/server/src/nfs-fops.h @@ -134,7 +134,7 @@ nfs_fop_local_wipe (xlator_t *xl, struct nfs_fop_local *l);  #define nfs_fop_handle_local_init(fram,nfx, nfloc, cbck,prgloc,retval,lab)  \          do {                                                                \ -                prog_data_to_nfl (nfx, nfloc, fram, cbck, prgloc);          \ +                prog_data_to_nfl (nfx, nfloc, fram, cbck, prgloc);      \                  if (!nfloc) {                                               \                          gf_log (GF_NFS,GF_LOG_ERROR,"Failed to init local");\                          retval = -ENOMEM;                                   \ @@ -236,4 +236,9 @@ nfs_fop_stat (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,  extern int  nfs_fop_access (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,                  int32_t accesstest, fop_access_cbk_t cbk, void *local); + +extern int +nfs_fop_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, +            int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local); +  #endif diff --git a/xlators/nfs/server/src/nfs-generics.c b/xlators/nfs/server/src/nfs-generics.c index 642879b8afc..dbb79fc9c2f 100644 --- a/xlators/nfs/server/src/nfs-generics.c +++ b/xlators/nfs/server/src/nfs-generics.c @@ -151,7 +151,6 @@ nfs_truncate (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,          return ret;  } -  int  nfs_read (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, size_t size,            off_t offset, fop_readv_cbk_t cbk, void *local) @@ -159,6 +158,12 @@ nfs_read (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, size_t size,          return nfs_fop_read (nfsx, xl, nfu, fd, size, offset, cbk, local);  } +int +nfs_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, +        int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local) +{ +        return nfs_fop_lk ( nfsx, xl, nfu, fd, cmd, flock, cbk, local); +}  int  nfs_fsync (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, @@ -330,3 +335,4 @@ nfs_opendir (xlator_t *nfsx, xlator_t *fopxl, nfs_user_t *nfu, loc_t *pathloc,          return nfs_inode_opendir (nfsx, fopxl, nfu, pathloc, cbk, local);  } + diff --git a/xlators/nfs/server/src/nfs-generics.h b/xlators/nfs/server/src/nfs-generics.h index 237a0ad09bc..11f191f5fd9 100644 --- a/xlators/nfs/server/src/nfs-generics.h +++ b/xlators/nfs/server/src/nfs-generics.h @@ -161,4 +161,7 @@ nfs_opendir (xlator_t *nfsx, xlator_t *fopxl, nfs_user_t *nfu, loc_t *pathloc,  extern int  nfs_access (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,              int32_t accesstest, fop_access_cbk_t cbk, void *local); +extern int +nfs_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, +        int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local);  #endif diff --git a/xlators/nfs/server/src/nfs-mem-types.h b/xlators/nfs/server/src/nfs-mem-types.h index 57f5f90b2fe..e2dae4a3403 100644 --- a/xlators/nfs/server/src/nfs-mem-types.h +++ b/xlators/nfs/server/src/nfs-mem-types.h @@ -43,6 +43,10 @@ enum gf_nfs_mem_types_ {          gf_nfs_mt_mnt3_resolve,          gf_nfs_mt_mnt3_export,          gf_nfs_mt_inode_q, +	gf_nfs_mt_nlm4_state, +	gf_nfs_mt_nlm4_cm, +	gf_nfs_mt_nlm4_fde, +        gf_nfs_mt_nlm4_nlmclnt,          gf_nfs_mt_end  };  #endif diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index d92a0e126e6..67efe530746 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -40,6 +40,7 @@  #include "nfs3.h"  #include "nfs-mem-types.h"  #include "nfs3-helpers.h" +#include "nlm4.h"  /* Every NFS version must call this function with the init function   * for its particular version. @@ -172,6 +173,13 @@ nfs_add_all_initiators (struct nfs_state *nfs)                  goto ret;          } +        ret = nfs_add_initer (&nfs->versions, nlm4svc_init); +        if (ret == -1) { +                gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol" +                        " initializer"); +                goto ret; +        } +          ret = 0;  ret:          return ret; @@ -747,6 +755,13 @@ init (xlator_t *this) {                  goto err;          } +        ret = nlm4_init_state (this); +        if (ret == -1) { +                gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NLM" +                        "state"); +                goto err; +        } +          ret = nfs_init_versions (nfs, this);          if (ret == -1) {                  gf_log (GF_NFS, GF_LOG_ERROR, "Failed to initialize " diff --git a/xlators/nfs/server/src/nfs.h b/xlators/nfs/server/src/nfs.h index 3113e32cc0b..706cba86f3e 100644 --- a/xlators/nfs/server/src/nfs.h +++ b/xlators/nfs/server/src/nfs.h @@ -28,6 +28,7 @@  #include "rpcsvc.h"  #include "dict.h"  #include "xlator.h" +#include "lkowner.h"  #define GF_NFS                  "nfs" @@ -69,6 +70,8 @@ struct nfs_state {          rpcsvc_t                *rpcsvc;          struct list_head        versions;          struct mount3_state     *mstate; +        struct nfs3_state       *nfs3state; +        struct nlm4_state       *nlm4state;          struct mem_pool         *foppool;          unsigned int            memfactor;          xlator_list_t           *subvols; @@ -82,6 +85,7 @@ struct nfs_state {          int                     enable_ino32;          unsigned int            override_portnum;          int                     allow_insecure; +        struct rpc_clnt         *rpc_clnt;  };  #define gf_nfs_dvm_on(nfsstt)   (((struct nfs_state *)nfsstt)->dynamicvolumes == GF_NFS_DVM_ON) @@ -102,6 +106,7 @@ typedef struct nfs_user_info {          uid_t   uid;          gid_t   gids[NFS_NGROUPS];          int     ngrps; +        gf_lkowner_t lk_owner;  } nfs_user_t;  extern int diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 527101de22b..1cb8d07e656 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -450,6 +450,8 @@ nfs3_call_state_wipe (nfs3_call_state_t *cs)                  iobuf_unref (cs->iob);          if (cs->iobref)                  iobref_unref (cs->iobref); +        if (cs->trans) +                rpc_transport_unref (cs->trans);          memset (cs, 0, sizeof (*cs));          mem_put (cs);          /* Already refd by fd_lookup, so no need to ref again. */ @@ -5483,6 +5485,7 @@ nfs3_init_state (xlator_t *nfsx)                  goto free_localpool;          } +        nfs->nfs3state = nfs3;          ret = 0;  free_localpool: diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h index 3e99184c7ad..4a595e5ef22 100644 --- a/xlators/nfs/server/src/nfs3.h +++ b/xlators/nfs/server/src/nfs3.h @@ -34,6 +34,7 @@  #include "nfs-common.h"  #include "xdr-nfs3.h"  #include "mem-pool.h" +#include "nlm4.h"  #include <sys/statvfs.h> @@ -94,7 +95,7 @@ struct nfs3_export {  #define GF_NFS3_DEFAULT_VOLACCESS       (GF_NFS3_VOLACCESS_RW)  /* The NFSv3 protocol state */ -struct nfs3_state { +typedef struct nfs3_state {          /* The NFS xlator pointer. The NFS xlator can be running           * multiple versions of the NFS protocol. @@ -133,13 +134,30 @@ struct nfs3_state {          struct list_head        fdlru;          gf_lock_t               fdlrulock;          int                     fdcount; -}; +} nfs3_state_t;  typedef enum nfs3_lookup_type {          GF_NFS3_REVALIDATE = 1,          GF_NFS3_FRESH,  } nfs3_lookup_type_t; +typedef union args_ { +        nlm4_stat nlm4_stat; +        nlm4_holder nlm4_holder; +        nlm4_lock nlm4_lock; +        nlm4_share nlm4_share; +        nlm4_testrply nlm4_testrply; +        nlm4_testres nlm4_testres; +        nlm4_testargs nlm4_testargs; +        nlm4_res nlm4_res; +        nlm4_lockargs nlm4_lockargs; +        nlm4_cancargs nlm4_cancargs; +        nlm4_unlockargs nlm4_unlockargs; +        nlm4_shareargs nlm4_shareargs; +        nlm4_shareres nlm4_shareres; +} args; + +  typedef int (*nfs3_resume_fn_t) (void *cs);  /* Structure used to communicate state between a fop and its callback.   * Not all members are used at all times. Usage is fop and NFS request @@ -208,6 +226,13 @@ struct nfs3_local {          gf_dirent_t             *hashmatch;          gf_dirent_t             *entrymatch;          off_t                   lastentryoffset; +        struct flock            flock; +        args                    args; +        nlm4_lkowner_t          lkowner; +        char                    cookiebytes[1024]; +        struct nfs3_fh          lockfh; +        rpc_transport_t         *trans; +        call_frame_t            *frame;  };  #define nfs3_is_revalidate_lookup(cst) ((cst)->lookuptype == GF_NFS3_REVALIDATE) diff --git a/xlators/nfs/server/src/nlm4.c b/xlators/nfs/server/src/nlm4.c new file mode 100644 index 00000000000..6e8494ce0ad --- /dev/null +++ b/xlators/nfs/server/src/nlm4.c @@ -0,0 +1,1760 @@ +/* +  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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "defaults.h" +#include "rpcsvc.h" +#include "dict.h" +#include "xlator.h" +#include "nfs.h" +#include "mem-pool.h" +#include "logging.h" +#include "nfs-fops.h" +#include "inode.h" +#include "mount3.h" +#include "nfs3.h" +#include "nfs-mem-types.h" +#include "nfs3-helpers.h" +#include "nfs3-fh.h" +#include "nlm4.h" +#include "nlm4-xdr.h" +#include "msg-nfs3.h" +#include "nfs-generics.h" +#include "rpc-clnt.h" +#include "nsm-xdr.h" +#include "nlmcbk-xdr.h" +#include <unistd.h> +#include <rpc/pmap_clnt.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> + +/* TODO: + * 1) 2 opens racing .. creating an fd leak. + * 2) use mempool for nlmclnt - destroy if no fd exists, create during 1st call + */ + +typedef ssize_t (*nlm4_serializer) (struct iovec outmsg, void *args); + +extern void nfs3_call_state_wipe (nfs3_call_state_t *cs); + +struct list_head nlm_client_list; +gf_lock_t nlm_client_list_lk; + +/* race on this is harmless */ +int nlm_grace_period = 50; + +#define nlm4_validate_nfs3_state(request, state, status, label, retval) \ +        do      {                                                       \ +                state = rpcsvc_request_program_private (request);       \ +                if (!state) {                                           \ +                        gf_log (GF_NLM, GF_LOG_ERROR, "NFSv3 state "    \ +                                "missing from RPC request");            \ +                        rpcsvc_request_seterr (req, SYSTEM_ERR);        \ +                        status = nlm4_failed;                           \ +                        goto label;                                     \ +                }                                                       \ +        } while (0);                                                    \ + +nfs3_call_state_t * +nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v); + +#define nlm4_handle_call_state_init(nfs3state, calls, rq, opstat, errlabel)\ +        do {                                                            \ +                calls = nlm4_call_state_init ((nfs3state), (rq));       \ +                if (!calls) {                                           \ +                        gf_log (GF_NLM, GF_LOG_ERROR, "Failed to "      \ +                                "init call state");                     \ +                        opstat = nlm4_failed;                           \ +                        rpcsvc_request_seterr (req, SYSTEM_ERR);        \ +                        goto errlabel;                                  \ +                }                                                       \ +        } while (0)                                                     \ + +#define nlm4_validate_gluster_fh(handle, status, errlabel)              \ +        do {                                                            \ +                if (!nfs3_fh_validate (handle)) {                       \ +                        status = nlm4_stale_fh;                         \ +                        goto errlabel;                                  \ +                }                                                       \ +        } while (0)                                                     \ + +xlator_t * +nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh); + +#define nlm4_map_fh_to_volume(nfs3state, handle, rqst, volume, status, label) \ +        do {                                                            \ +                volume = nfs3_fh_to_xlator ((nfs3state), handle);       \ +                if (!volume) {                                          \ +                        gf_log (GF_NLM, GF_LOG_ERROR, "Failed to map "  \ +                                "FH to vol");                           \ +                        status = nlm4_stale_fh;                         \ +                        goto label;                                     \ +                } else {                                                \ +                        gf_log (GF_NLM, GF_LOG_TRACE, "FH to Volume: %s"\ +                                ,volume->name);                         \ +                        rpcsvc_request_set_private (req, volume);       \ +                }                                                       \ +        } while (0);                                                    \ + +#define nlm4_volume_started_check(nfs3state, vlm, rtval, erlbl)         \ +        do {                                                            \ +              if ((!nfs_subvolume_started (nfs_state (nfs3state->nfsx), vlm))){\ +                      gf_log (GF_NLM, GF_LOG_ERROR, "Volume is disabled: %s",\ +                              vlm->name);                               \ +                      rtval = RPCSVC_ACTOR_IGNORE;                      \ +                      goto erlbl;                                       \ +              }                                                         \ +        } while (0)                                                     \ + +#define nlm4_check_fh_resolve_status(cst, _stat, erlabl)               \ +        do {                                                            \ +                if ((cst)->resolve_ret < 0) {                           \ +                        _stat = nlm4_errno_to_nlm4stat (cst->resolve_errno);\ +                        goto erlabl;                                    \ +                }                                                       \ +        } while (0)                                                     \ + + +void +nlm4_prep_nlm4_testargs (nlm4_testargs *args, struct nfs3_fh *fh, +                         nlm4_lkowner_t *oh, char *cookiebytes) +{ +        memset (args, 0, sizeof (*args)); +        args->alock.fh.n_bytes = (void *)fh; +        args->alock.oh.n_bytes = (void *)oh; +        args->cookie.n_bytes = (void *)cookiebytes; +} + +void +nlm4_prep_nlm4_lockargs (nlm4_lockargs *args, struct nfs3_fh *fh, +                         nlm4_lkowner_t *oh, char *cookiebytes) +{ +        memset (args, 0, sizeof (*args)); +        args->alock.fh.n_bytes = (void *)fh; +        args->alock.oh.n_bytes = (void *)oh; +        args->cookie.n_bytes = (void *)cookiebytes; +} + +void +nlm4_prep_nlm4_cancargs (nlm4_cancargs *args, struct nfs3_fh *fh, +                           nlm4_lkowner_t *oh, char *cookiebytes) +{ +        memset (args, 0, sizeof (*args)); +        args->alock.fh.n_bytes = (void *)fh; +        args->alock.oh.n_bytes = (void *)oh; +        args->cookie.n_bytes = (void *)cookiebytes; +} + +void +nlm4_prep_nlm4_unlockargs (nlm4_unlockargs *args, struct nfs3_fh *fh, +                           nlm4_lkowner_t *oh, char *cookiebytes) +{ +        memset (args, 0, sizeof (*args)); +        args->alock.fh.n_bytes = (void *)fh; +        args->alock.oh.n_bytes = (void *)oh; +        args->cookie.n_bytes = (void *)cookiebytes; +} + +void +nlm_copy_lkowner (gf_lkowner_t *dst, netobj *src) +{ +        dst->len = src->n_len; +        memcpy (dst->data, src->n_bytes, dst->len); +} + + +nfsstat3 +nlm4_errno_to_nlm4stat (int errnum) +{ +        nlm4_stats        stat = nlm4_denied; + +        switch (errnum) { +        case 0: +                stat = nlm4_granted; +                break; +        case EROFS: +                stat = nlm4_rofs; +                break; +        case ESTALE: +                stat = nlm4_stale_fh; +                break; +        case ENOLCK: +                stat = nlm4_failed; +                break; +        default: +                stat = nlm4_denied; +                break; +        } + +        return stat; +} + +nfs3_call_state_t * +nlm4_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req) +{ +        nfs3_call_state_t       *cs = NULL; + +        if ((!s) || (!req)) +                return NULL; + +        cs = (nfs3_call_state_t *) mem_get (s->localpool); +        if (!cs) +                return NULL; + +        memset (cs, 0, sizeof (*cs)); +        INIT_LIST_HEAD (&cs->entries.list); +        INIT_LIST_HEAD (&cs->openwait_q); +        cs->operrno = EINVAL; +        cs->req = req; +        cs->nfsx = s->nfsx; +        cs->nfs3state = s; + +        return cs; +} + +rpc_clnt_t * +nlm_get_rpc_clnt (char *caller_name) +{ +        nlm_client_t *nlmclnt = NULL; +        int nlmclnt_found = 0; +        rpc_clnt_t *rpc_clnt = NULL; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) { +                if (!strcmp(caller_name, nlmclnt->caller_name)) { +                        nlmclnt_found = 1; +                        break; +                } +        } +        if (!nlmclnt_found) +                goto ret; +        if (nlmclnt->rpc_clnt) +                rpc_clnt = rpc_clnt_ref (nlmclnt->rpc_clnt); +ret: +        UNLOCK (&nlm_client_list_lk); +        return rpc_clnt; +} + +int +nlm_set_rpc_clnt (rpc_clnt_t *rpc_clnt, char *caller_name) +{ +        nlm_client_t *nlmclnt = NULL; +        int nlmclnt_found = 0; +        int ret = -1; +        rpc_clnt_t *rpc_clnt_old = NULL; +        char *old_name = NULL; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) { +                if (!strcmp(caller_name, nlmclnt->caller_name)) { +                        nlmclnt_found = 1; +                        break; +                } +        } +        if (!nlmclnt_found) { +                nlmclnt = GF_CALLOC (1, sizeof(*nlmclnt), +                                     gf_nfs_mt_nlm4_nlmclnt); +                if (nlmclnt == NULL) { +                        gf_log (GF_NLM, GF_LOG_DEBUG, "malloc error"); +                        goto ret; +                } + +                INIT_LIST_HEAD(&nlmclnt->fdes); +                INIT_LIST_HEAD(&nlmclnt->nlm_clients); + +                list_add (&nlmclnt->nlm_clients, &nlm_client_list); +        } +        rpc_clnt_old = nlmclnt->rpc_clnt; +        old_name = nlmclnt->caller_name; +        if (rpc_clnt) +                nlmclnt->rpc_clnt = rpc_clnt_ref (rpc_clnt); +        nlmclnt->caller_name = gf_strdup (caller_name); + +        ret = 0; +ret: +        UNLOCK (&nlm_client_list_lk); +        if (rpc_clnt_old) +                rpc_clnt_unref (rpc_clnt_old); +        if (old_name) +                GF_FREE (old_name); +        return ret; +} + +int +nlm_unset_rpc_clnt (rpc_clnt_t *rpc) +{ +        nlm_client_t *nlmclnt = NULL; +        rpc_clnt_t *rpc_clnt = NULL; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) { +                if (rpc == nlmclnt->rpc_clnt) { +                        rpc_clnt = nlmclnt->rpc_clnt; +                        nlmclnt->rpc_clnt = NULL; +                        break; +                } +        } +        UNLOCK (&nlm_client_list_lk); +        if (rpc_clnt == NULL) { +                return -1; +        } +        if (rpc_clnt) +                rpc_clnt_unref (rpc_clnt); +        return 0; +} + +int +nlm_add_nlmclnt (char *caller_name) +{ +        nlm_client_t *nlmclnt = NULL; +        int nlmclnt_found = 0; +        int ret = -1; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) { +                if (!strcmp(caller_name, nlmclnt->caller_name)) { +                        nlmclnt_found = 1; +                        break; +                } +        } +        if (!nlmclnt_found) { +                nlmclnt = GF_CALLOC (1, sizeof(*nlmclnt), +                                     gf_nfs_mt_nlm4_nlmclnt); +                if (nlmclnt == NULL) { +                        gf_log (GF_NLM, GF_LOG_DEBUG, "malloc error"); +                        goto ret; +                } + +                INIT_LIST_HEAD(&nlmclnt->fdes); +                INIT_LIST_HEAD(&nlmclnt->nlm_clients); + +                list_add (&nlmclnt->nlm_clients, &nlm_client_list); +                nlmclnt->caller_name = gf_strdup (caller_name); +        } +        ret = 0; +ret: +        UNLOCK (&nlm_client_list_lk); +        return 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 iobref           *iobref = NULL; + +        if (!req) +                return -1; + +        nfs3 = (struct nfs3_state *)rpcsvc_request_program_private (req); +        if (!nfs3) { +                gf_log (GF_NLM, GF_LOG_ERROR, "mount state not found"); +                goto ret; +        } + +        /* First, get the io buffer into which the reply in arg will +         * be serialized. +         */ +        iob = iobuf_get (nfs3->iobpool); +        if (!iob) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Failed to get iobuf"); +                goto ret; +        } + +        iobuf_to_iovec (iob, &outmsg); +        /* 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); + +        iobref = iobref_new (); +        if (iobref == NULL) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Failed to get iobref"); +                goto ret; +        } + +        iobref_add (iobref, iob); + +        /* Then, submit the message for transmission. */ +        ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref); +        iobuf_unref (iob); +        iobref_unref (iobref); +        if (ret == -1) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Reply submission failed"); +                goto ret; +        } + +        ret = 0; +ret: +        return ret; +} + +typedef int (*nlm4_resume_fn_t) (void *cs); + +int32_t +nlm4_file_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, fd_t *fd) +{ +        nfs3_call_state_t *cs = frame->local; + +        if (op_ret == 0) +                fd_bind (cs->fd); +        cs->resolve_ret = op_ret; +        cs->resume_fn (cs); +        frame->local = NULL; +        STACK_DESTROY (frame->root); +        return 0; +} + +int nsm_monitor(char *host) +{ +        CLIENT *clnt = NULL; +        enum clnt_stat ret; +        struct mon nsm_mon; +        struct sm_stat_res res; +        struct timeval tout = { 5, 0 }; +        int retstat = -1; + +        nsm_mon.mon_id.mon_name = strdup(host); +        nsm_mon.mon_id.my_id.my_name = strdup("localhost"); +        nsm_mon.mon_id.my_id.my_prog = NLMCBK_PROGRAM; +        nsm_mon.mon_id.my_id.my_vers = NLMCBK_V1; +        nsm_mon.mon_id.my_id.my_proc = NLMCBK_SM_NOTIFY; +        /* nothing to put in the private data */ +#define SM_PROG 100024 +#define SM_VERS 1 +#define SM_MON 2 + +        /* create a connection to nsm on the localhost */ +        clnt = clnt_create("localhost", SM_PROG, SM_VERS, "tcp"); +        if(!clnt) +        { +                gf_log (GF_NLM, GF_LOG_ERROR, "Clnt_create()"); +                goto out; +        } + +        ret = clnt_call(clnt, SM_MON, +                        (xdrproc_t) xdr_mon, (caddr_t) & nsm_mon, +                        (xdrproc_t) xdr_sm_stat_res, (caddr_t) & res, tout); +        if(ret != RPC_SUCCESS) +        { +                gf_log (GF_NLM, GF_LOG_ERROR, "clnt_call(): %s", +                        clnt_sperrno(ret)); +                goto out; +        } +        if(res.res_stat != STAT_SUCC) +        { +                gf_log (GF_NLM, GF_LOG_ERROR, "clnt_call(): %s", +                        clnt_sperrno(ret)); +                goto out; +        } +        retstat = 0; +out: +        free(nsm_mon.mon_id.mon_name); +        free(nsm_mon.mon_id.my_id.my_name); +        clnt_destroy(clnt); +        return retstat; +} + +nlm_client_t * +nlm_get_uniq (char *caller_name) +{ +        nlm_client_t *nlmclnt = NULL; +        int nlmclnt_found = 0; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) { +                if (!strcmp(caller_name, nlmclnt->caller_name)) { +                        nlmclnt_found = 1; +                        break; +                } +        } +        UNLOCK (&nlm_client_list_lk); +        if (nlmclnt_found) +                return nlmclnt; +        else +                return NULL; +} + + +int +nlm4_file_open_and_resume(nfs3_call_state_t *cs, nlm4_resume_fn_t resume) +{ +        fd_t *fd = NULL; +        int ret = -1; +        nlm_client_t *nlmclnt = NULL; +        call_frame_t *frame = NULL; + +        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"); +                cs->resolve_ret = -1; +                cs->resume_fn(cs); +                ret = -1; +                goto err; +        } +        cs->resume_fn = resume; +        fd = fd_lookup_uint64 (cs->resolvedloc.inode, (uint64_t)nlmclnt); +        if (fd) { +                cs->fd = fd; +                cs->resolve_ret = 0; +                cs->resume_fn(cs); +                ret = 0; +                goto err; +        } + +        fd = fd_create_uint64 (cs->resolvedloc.inode, (uint64_t)nlmclnt); +        if (fd == NULL) { +                gf_log (GF_NLM, GF_LOG_ERROR, "fd_create_uint64() returned NULL"); +                cs->resolve_ret = -1; +                cs->resume_fn(cs); +                ret = -1; +                goto err; +        } + +        cs->fd = fd; + +        frame = create_frame (cs->nfsx, cs->nfsx->ctx->pool); +        frame->root->pid = NFS_PID; +        frame->root->uid = 0; +        frame->root->gid = 0; +        frame->local = cs; +        STACK_WIND_COOKIE(frame, nlm4_file_open_cbk, cs->nfsx, cs->nfsx, +                          cs->nfsx->fops->open, &cs->resolvedloc, O_RDWR, +                          cs->fd, GF_OPEN_NOWB); +        ret = 0; +err: +        return ret; +} + +int +nlm4_generic_reply (rpcsvc_request_t *req, netobj cookie, nlm4_stats stat) +{ +        nlm4_res res; + +        memset (&res, 0, sizeof (res)); +        res.cookie = cookie; +        res.stat.stat = stat; + +        nlm4svc_submit_reply (req, (void *)&res, +                              (nlm4_serializer)xdr_serialize_nlm4_res); +        return 0; +} + +int +nlm4svc_null (rpcsvc_request_t *req) +{ +        struct iovec    dummyvec = {0, }; + +        if (!req) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Got NULL request!"); +                return 0; +        } +        rpcsvc_submit_generic (req, &dummyvec, 1,  NULL, 0, NULL); +        return 0; +} + +int +nlm4_gf_flock_to_holder (nlm4_holder *holder, struct gf_flock *flock) +{ +        switch (flock->l_type) { +        case GF_LK_F_WRLCK: +                holder->exclusive = 1; +                break; +        } + +        holder->svid = flock->l_pid; +        holder->l_offset = flock->l_start; +        holder->l_len = flock->l_len; +        return 0; +} + +int +nlm4_lock_to_gf_flock (struct gf_flock *flock, nlm4_lock *lock, int excl) +{ +        flock->l_pid = lock->svid; +        flock->l_start = lock->l_offset; +        flock->l_len = lock->l_len; +        if (excl) +                flock->l_type = F_WRLCK; +        else +                flock->l_type = F_RDLCK; +        flock->l_whence = SEEK_SET; +        nlm_copy_lkowner (&flock->l_owner, &lock->oh); +        return 0; +} + +rpc_clnt_procedure_t nlm4_clnt_actors[NLM4_PROC_COUNT] = { +        [NLM4_NULL] = {"NULL", NULL}, +        [NLM4_GRANTED] = {"GRANTED", NULL}, +}; + +char *nlm4_clnt_names[NLM4_PROC_COUNT] = { +        [NLM4_NULL] = "NULL", +        [NLM4_GRANTED] = "GRANTED", +}; + +rpc_clnt_prog_t nlm4clntprog = { +        .progname = "NLMv4", +        .prognum = NLM_PROGRAM, +        .progver = NLM_V4, +        .numproc = NLM4_PROC_COUNT, +        .proctable = nlm4_clnt_actors, +        .procnames = nlm4_clnt_names, +}; + +int +nlm4_test_reply (nfs3_call_state_t *cs, nlm4_stats stat, struct gf_flock *flock) +{ +        nlm4_testres res; + +        memset (&res, 0, sizeof (res)); +        res.cookie = cs->args.nlm4_testargs.cookie; +        res.stat.stat = stat; +        if (stat == nlm4_denied) +                nlm4_gf_flock_to_holder (&res.stat.nlm4_testrply_u.holder, +                                         flock); + +        nlm4svc_submit_reply (cs->req, (void *)&res, +                              (nlm4_serializer)xdr_serialize_nlm4_testres); +        return 0; +} + +int +nlm4svc_test_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                  int32_t op_ret, int32_t op_errno, struct gf_flock *flock) +{ +        nlm4_stats                      stat = nlm4_denied; +        nfs3_call_state_t              *cs = NULL; + +        cs = frame->local; +        if (op_ret == -1) { +                stat = nlm4_errno_to_nlm4stat (op_errno); +                goto err; +        } else if (flock->l_type == F_UNLCK) +                stat = nlm4_granted; + +err: +        nlm4_test_reply (cs, stat, flock); +        nfs3_call_state_wipe (cs); +        return 0; +} + +int +nlm4_test_fd_resume (void *carg) +{ +        nlm4_stats                      stat = nlm4_denied; +        int                             ret = -EFAULT; +        nfs_user_t                      nfu = {0, }; +        nfs3_call_state_t               *cs = NULL; +        struct gf_flock                 flock = {0, }; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        nlm4_check_fh_resolve_status (cs, stat, nlm4err); +        nfs_request_user_init (&nfu, cs->req); +        nlm4_lock_to_gf_flock (&flock, &cs->args.nlm4_testargs.alock, +                               cs->args.nlm4_testargs.exclusive); +        nlm_copy_lkowner (&nfu.lk_owner, &cs->args.nlm4_testargs.alock.oh); +        ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_GETLK, &flock, +                      nlm4svc_test_cbk, cs); +        if (ret < 0) +                stat = nlm4_errno_to_nlm4stat (-ret); +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Unable to call lk()"); +                nlm4_test_reply (cs, stat, &flock); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + + +int +nlm4_test_resume (void *carg) +{ +        nlm4_stats                      stat = nlm4_failed; +        int                             ret = -1; +        nfs3_call_state_t               *cs = NULL; +        fd_t                            *fd = NULL; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        nlm4_check_fh_resolve_status (cs, stat, nlm4err); +        fd = fd_anonymous (cs->resolvedloc.inode); +        cs->fd = fd; +        ret = nlm4_test_fd_resume (cs); +        if (ret < 0) +                stat = nlm4_errno_to_nlm4stat (-ret); + +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to open_and_resume"); +                nlm4_test_reply (cs, stat, NULL); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + +int +nlm4svc_test (rpcsvc_request_t *req) +{ +        xlator_t                        *vol = NULL; +        nlm4_stats                      stat = nlm4_failed; +        struct nfs_state               *nfs = NULL; +        nfs3_state_t                   *nfs3 = NULL; +        nfs3_call_state_t               *cs = NULL; +        int                             ret = RPCSVC_ACTOR_ERROR; +        struct nfs3_fh                  fh = {{0}, }; + +        if (!req) +                return ret; + +        nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); +        nfs = nfs_state (nfs3->nfsx); +        nlm4_handle_call_state_init (nfs->nfs3state, cs, req, +                                     stat, rpcerr); + +        nlm4_prep_nlm4_testargs (&cs->args.nlm4_testargs, &fh, &cs->lkowner, +                                 cs->cookiebytes); +        if (xdr_to_nlm4_testargs(req->msg[0], &cs->args.nlm4_testargs) <= 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto rpcerr; +        } + +        nlm4_validate_gluster_fh (&fh, stat, nlm4err); +        nlm4_map_fh_to_volume (cs->nfs3state, &fh, req, vol, stat, nlm4err); + +        if (nlm_grace_period) { +                gf_log (GF_NLM, GF_LOG_WARNING, "NLM in grace period"); +                stat = nlm4_denied_grace_period; +                nlm4_test_reply (cs, stat, NULL); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +        cs->vol = vol; +        nlm4_volume_started_check (nfs3, vol, ret, rpcerr); + +        ret = nfs3_fh_resolve_and_resume (cs, &fh, +                                          NULL, nlm4_test_resume); + +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to resolve and resume"); +                nlm4_test_reply (cs, stat, NULL); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +rpcerr: +        if (ret < 0) { +                nfs3_call_state_wipe (cs); +        } +        return ret; +} + +int +nlm4svc_send_granted_cbk (struct rpc_req *req, struct iovec *iov, int count, +                          void *myframe) +{ +        STACK_DESTROY (((call_frame_t*)myframe)->root); +        return 0; +} + +int nlm_rpcclnt_notify (struct rpc_clnt *rpc, void *mydata, +                        rpc_clnt_event_t fn, void *data) +{ +        nlm_condmutex_t *cm = NULL; +        int ret; +        cm = mydata; +        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)); +                break; +        case RPC_CLNT_MSG: +                break; +        case RPC_CLNT_DISCONNECT: +                nlm_unset_rpc_clnt(rpc); +                break; +        } +        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; + +        cs = (nfs3_call_state_t *) csarg; + +        caller_name = cs->args.nlm4_lockargs.alock.caller_name; +        nsm_monitor (caller_name); + +        rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sa, sizeof (sa)); +        sockaddr = (struct sockaddr*) &sa; +        switch (sockaddr->sa_family) { +        case AF_INET6: +                inet_ntop (AF_INET6, +                           &((struct sockaddr_in6 *)sockaddr)->sin6_addr, +                           peerip, INET6_ADDRSTRLEN+1); +                break; +        case AF_INET: +                inet_ntop (AF_INET, +                           &((struct sockaddr_in *)sockaddr)->sin_addr, +                           peerip, INET6_ADDRSTRLEN+1); +        default: +                break; +                /* FIXME: handle the error */ +        } + +        /* looks like libc rpc supports only ipv4 */ +        port = pmap_getport ((struct sockaddr_in*)sockaddr, NLM_PROGRAM, +                             NLM_V4, IPPROTO_TCP); + +        options = dict_new(); +        ret = dict_set_str (options, "transport-type", "socket"); +        if (ret == -1) { +                gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error"); +                goto err; +        } + +        ret = dict_set_dynstr (options, "remote-host", strdup (peerip)); +        if (ret == -1) { +                gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error"); +                goto err; +        } + +        ret = gf_asprintf (&portstr, "%d", port); +        if (ret == -1) +                goto err; + +        ret = dict_set_dynstr (options, "remote-port", +                               portstr); +        if (ret == -1) { +                gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_dynstr error"); +                goto err; +        } +        ret = dict_set_str (options, "auth-null", "on"); +        if (ret == -1) { +                gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_dynstr error"); +                goto err; +        } + +        rpc_clnt = rpc_clnt_new (options, cs->nfsx->ctx, "NLM-client"); +        if (rpc_clnt == NULL) { +                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); +        if (ret == -1) { +                gf_log (GF_NLM, GF_LOG_ERROR,"rpc_clnt_register_connect error"); +                goto err; +        } +        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); +err: +        rpc_clnt_unref (rpc_clnt); +        return NULL; +} + +void +nlm4svc_send_granted (nfs3_call_state_t *cs) +{ +        int ret = -1; +        rpc_clnt_t *rpc_clnt = NULL; +        struct iovec            outmsg = {0, }; +        nlm4_testargs testargs; +        struct iobuf *iobuf = NULL; +        struct iobref *iobref = NULL; +        struct nfs_state *nfs = NULL; +        char peerip[INET6_ADDRSTRLEN+1]; +        pthread_t thr; +        struct sockaddr_storage sa; +        struct sockaddr *sockaddr = NULL; + +        nfs = cs->nfsx->private; + +        rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sa, sizeof (sa)); +        sockaddr = (struct sockaddr*) &sa; +        switch (sockaddr->sa_family) { +        case AF_INET6: +                inet_ntop (AF_INET6, +                           &((struct sockaddr_in6 *)sockaddr)->sin6_addr, +                           peerip, INET6_ADDRSTRLEN+1); +                break; +        case AF_INET: +                inet_ntop (AF_INET, +                           &((struct sockaddr_in *)sockaddr)->sin_addr, +                           peerip, INET6_ADDRSTRLEN+1); +        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; +        testargs.exclusive = cs->args.nlm4_lockargs.exclusive; +        testargs.alock = cs->args.nlm4_lockargs.alock; + +        iobuf = iobuf_get (cs->nfs3state->iobpool); +        if (!iobuf) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Failed to get iobuf"); +                goto ret; +        } + +        iobuf_to_iovec (iobuf, &outmsg); +        /* 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 = xdr_serialize_nlm4_testargs (outmsg, &testargs); + +        iobref = iobref_new (); +        if (iobref == NULL) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Failed to get iobref"); +                goto ret; +        } + +        iobref_add (iobref, iobuf); + +        ret = rpc_clnt_submit (rpc_clnt, &nlm4clntprog, NLM4_GRANTED, +                               nlm4svc_send_granted_cbk, +                               &outmsg, 1, +                               NULL, +                               0, iobref, cs->frame, NULL, 0, +                               NULL, 0, NULL); + +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "rpc_clnt_submit error"); +                goto ret; +        } +ret: +        rpc_clnt_unref (rpc_clnt); +        nfs3_call_state_wipe (cs); +        return; +} + +int +nlm_cleanup_fds (char *caller_name) +{ +        int nlmclnt_found = 0; +        nlm_fde_t *fde = NULL, *tmp = NULL; +        nlm_client_t *nlmclnt = NULL; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, +                             &nlm_client_list, nlm_clients) { +                if (!strcmp(caller_name, nlmclnt->caller_name)) { +                        nlmclnt_found = 1; +                        break; +                } +        } + +        if (!nlmclnt_found) +                goto ret; + +        if (list_empty (&nlmclnt->fdes)) +                goto ret; + +        list_for_each_entry_safe (fde, tmp, &nlmclnt->fdes, fde_list) { +                fd_unref (fde->fd); +                list_del (&fde->fde_list); +                GF_FREE (fde); +        } + +ret: +        UNLOCK (&nlm_client_list_lk); +        return 0; +} + +void +nlm_search_and_delete (fd_t *fd, char *caller_name) +{ +        nlm_fde_t *fde = NULL; +        nlm_client_t *nlmclnt = NULL; +        int nlmclnt_found = 0; +        int fde_found = 0; +        int transit_cnt = 0; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, +                             &nlm_client_list, nlm_clients) { +                if (!strcmp(caller_name, nlmclnt->caller_name)) { +                        nlmclnt_found = 1; +                        break; +                } +        } + +        if (!nlmclnt_found) +                goto ret; + +        list_for_each_entry (fde, &nlmclnt->fdes, fde_list) { +                if (fde->fd == fd) { +                        fde_found = 1; +                        break; +                } +        } + +        if (!fde_found) +                goto ret; +        transit_cnt = fde->transit_cnt; +        if (transit_cnt) +                goto ret; +        list_del (&fde->fde_list); + +ret: +        UNLOCK (&nlm_client_list_lk); + +        if (fde_found && !transit_cnt) { +                fd_unref (fde->fd); +                GF_FREE (fde); +        } +        return; +} + +int +nlm_dec_transit_count (fd_t *fd, char *caller_name) +{ +        nlm_fde_t *fde = NULL; +        nlm_client_t *nlmclnt = NULL; +        int nlmclnt_found = 0; +        int fde_found = 0; +        int transit_cnt = -1; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, +                             &nlm_client_list, nlm_clients) { +                if (!strcmp(caller_name, nlmclnt->caller_name)) { +                        nlmclnt_found = 1; +                        break; +                } +        } + +        if (!nlmclnt_found) { +                gf_log (GF_NLM, GF_LOG_ERROR, "nlmclnt not found"); +                nlmclnt = NULL; +                goto ret; +        } + +        list_for_each_entry (fde, &nlmclnt->fdes, fde_list) { +                if (fde->fd == fd) { +                        fde_found = 1; +                        break; +                } +        } + +        if (fde_found) { +                transit_cnt = --fde->transit_cnt; +                goto ret; +        } +ret: + +        UNLOCK (&nlm_client_list_lk); +        return transit_cnt; +} + + +nlm_client_t * +nlm_search_and_add (fd_t *fd, char *caller_name) +{ +        nlm_fde_t *fde = NULL; +        nlm_client_t *nlmclnt = NULL; +        int nlmclnt_found = 0; +        int fde_found = 0; + +        LOCK (&nlm_client_list_lk); +        list_for_each_entry (nlmclnt, +                             &nlm_client_list, nlm_clients) { +                if (!strcmp(caller_name, nlmclnt->caller_name)) { +                        nlmclnt_found = 1; +                        break; +                } +        } + +        if (!nlmclnt_found) { +                gf_log (GF_NLM, GF_LOG_ERROR, "nlmclnt not found"); +                nlmclnt = NULL; +                goto ret; +        } + +        list_for_each_entry (fde, &nlmclnt->fdes, fde_list) { +                if (fde->fd == fd) { +                        fde_found = 1; +                        break; +                } +        } + +        if (fde_found) +                goto ret; + +        fde = GF_CALLOC (1, sizeof (*fde), gf_nfs_mt_nlm4_fde); + +        fde->fd = fd_ref (fd); +        list_add (&fde->fde_list, &nlmclnt->fdes); +ret: +        if (nlmclnt_found && fde) +                fde->transit_cnt++; +        UNLOCK (&nlm_client_list_lk); +        return nlmclnt; +} + +int +nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                  int32_t op_ret, int32_t op_errno, struct gf_flock *flock) +{ +        nlm4_stats                      stat = nlm4_denied; +        nfs3_call_state_t              *cs = NULL; +        int                             transit_cnt = -1; + +        cs = frame->local; + +        transit_cnt = nlm_dec_transit_count (cs->fd, +                                             cs->args.nlm4_lockargs.alock.caller_name); +        if (op_ret == -1) { +                if (transit_cnt == 0) +                        nlm_search_and_delete (cs->fd, +                                               cs->args.nlm4_lockargs.alock.caller_name); +                stat = nlm4_errno_to_nlm4stat (op_errno); +                goto err; +        } else +                stat = nlm4_granted; + +err: +        if (cs->args.nlm4_lockargs.block) { +                cs->frame = copy_frame (frame); +                nlm4svc_send_granted (cs); +        } else { +                nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie, +                                    stat); +                nfs3_call_state_wipe (cs); +        } +        return 0; +} + +int +nlm4_lock_fd_resume (void *carg) +{ +        nlm4_stats                      stat = nlm4_denied; +        int                             ret = -EFAULT; +        nfs_user_t                      nfu = {0, }; +        nfs3_call_state_t               *cs = NULL; +        struct gf_flock                 flock = {0, }; +        nlm_client_t                    *nlmclnt = NULL; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        nlm4_check_fh_resolve_status (cs, stat, nlm4err); + +        nlmclnt = nlm_search_and_add (cs->fd, +                                      cs->args.nlm4_lockargs.alock.caller_name); +        nfs_request_user_init (&nfu, cs->req); +        nlm4_lock_to_gf_flock (&flock, &cs->args.nlm4_lockargs.alock, +                               cs->args.nlm4_lockargs.exclusive); +        nlm_copy_lkowner (&nfu.lk_owner, &cs->args.nlm4_lockargs.alock.oh); +        if (cs->args.nlm4_lockargs.block) { +                nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie, +                                    nlm4_blocked); +                ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_SETLKW, +                              &flock, nlm4svc_lock_cbk, cs); +        } else +                ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_SETLK, +                              &flock, nlm4svc_lock_cbk, cs); + +        if (ret < 0) +                stat = nlm4_errno_to_nlm4stat (-ret); +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to call lk()"); +                nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie, +                                    stat); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + + +int +nlm4_lock_resume (void *carg) +{ +        nlm4_stats                      stat = nlm4_failed; +        int                             ret = -1; +        nfs3_call_state_t               *cs = NULL; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        nlm4_check_fh_resolve_status (cs, stat, nlm4err); +        ret = nlm4_file_open_and_resume (cs, nlm4_lock_fd_resume); +        if (ret < 0) +                stat = nlm4_errno_to_nlm4stat (-ret); + +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to open and resume"); +                nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie, +                                    stat); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + + +int +nlm4svc_lock (rpcsvc_request_t *req) +{ +        xlator_t                        *vol = NULL; +        nlm4_stats                      stat = nlm4_failed; +        struct nfs_state               *nfs = NULL; +        nfs3_state_t                   *nfs3 = NULL; +        nfs3_call_state_t               *cs = NULL; +        int                             ret = RPCSVC_ACTOR_ERROR; +        struct nfs3_fh                  fh = {{0}, }; + +        if (!req) +                return ret; + +        nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); +        nfs = nfs_state (nfs3->nfsx); +        nlm4_handle_call_state_init (nfs->nfs3state, cs, req, +                                     stat, rpcerr); + +        nlm4_prep_nlm4_lockargs (&cs->args.nlm4_lockargs, &cs->lockfh, +                                 &cs->lkowner, cs->cookiebytes); +        if (xdr_to_nlm4_lockargs(req->msg[0], &cs->args.nlm4_lockargs) <= 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto rpcerr; +        } +        fh = cs->lockfh; +        nlm4_validate_gluster_fh (&fh, stat, nlm4err); +        nlm4_map_fh_to_volume (cs->nfs3state, &fh, req, vol, stat, nlm4err); + +        if (nlm_grace_period && !cs->args.nlm4_lockargs.reclaim) { +                gf_log (GF_NLM, GF_LOG_WARNING, "NLM in grace period"); +                stat = nlm4_denied_grace_period; +                nlm4_generic_reply (req, cs->args.nlm4_unlockargs.cookie, stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +        cs->vol = vol; +        cs->trans = rpcsvc_request_transport_ref(req); +        nlm4_volume_started_check (nfs3, vol, ret, rpcerr); + +        ret = nlm_add_nlmclnt (cs->args.nlm4_lockargs.alock.caller_name); + +        ret = nfs3_fh_resolve_and_resume (cs, &fh, +                                          NULL, nlm4_lock_resume); + +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to resolve and resume"); +                nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie, +                                    stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +rpcerr: +        if (ret < 0) { +                nfs3_call_state_wipe (cs); +        } +        return ret; +} + +int +nlm4svc_cancel_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                    int32_t op_ret, int32_t op_errno, struct gf_flock *flock) +{ +        nlm4_stats                      stat = nlm4_denied; +        nfs3_call_state_t              *cs = NULL; + +        cs = frame->local; +        if (op_ret == -1) { +                stat = nlm4_errno_to_nlm4stat (op_errno); +                goto err; +        } else +                stat = nlm4_granted; + +err: +        nlm4_generic_reply (cs->req, cs->args.nlm4_cancargs.cookie, +                            stat); +        nfs3_call_state_wipe (cs); +        return 0; +} + +int +nlm4_cancel_fd_resume (void *carg) +{ +        nlm4_stats                      stat = nlm4_denied; +        int                             ret = -EFAULT; +        nfs_user_t                      nfu = {0, }; +        nfs3_call_state_t               *cs = NULL; +        struct gf_flock                 flock = {0, }; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        nlm4_check_fh_resolve_status (cs, stat, nlm4err); +        nfs_request_user_init (&nfu, cs->req); +        nlm4_lock_to_gf_flock (&flock, &cs->args.nlm4_cancargs.alock, +                               cs->args.nlm4_cancargs.exclusive); +        nlm_copy_lkowner (&nfu.lk_owner, &cs->args.nlm4_cancargs.alock.oh); +        flock.l_type = F_UNLCK; +        ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_SETLK, +                      &flock, nlm4svc_cancel_cbk, cs); + +        if (ret < 0) +                stat = nlm4_errno_to_nlm4stat (-ret); +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to call lk()"); +                nlm4_generic_reply (cs->req, cs->args.nlm4_cancargs.cookie, +                                    stat); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + +int +nlm4svc_unlock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                    int32_t op_ret, int32_t op_errno, struct gf_flock *flock) +{ +        nlm4_stats                      stat = nlm4_denied; +        nfs3_call_state_t              *cs = NULL; + +        cs = frame->local; +        if (op_ret == -1) { +                stat = nlm4_errno_to_nlm4stat (op_errno); +                goto err; +        } else { +                stat = nlm4_granted; +                if (flock->l_type == F_UNLCK) +                        nlm_search_and_delete (cs->fd, +                                               cs->args.nlm4_unlockargs.alock.caller_name); +        } + +err: +        nlm4_generic_reply (cs->req, cs->args.nlm4_unlockargs.cookie, stat); +        nfs3_call_state_wipe (cs); +        return 0; +} + +int +nlm4_unlock_fd_resume (void *carg) +{ +        nlm4_stats                      stat = nlm4_denied; +        int                             ret = -EFAULT; +        nfs_user_t                      nfu = {0, }; +        nfs3_call_state_t               *cs = NULL; +        struct gf_flock                 flock = {0, }; + +        if (!carg) +                return ret; +        cs = (nfs3_call_state_t *)carg; +        nlm4_check_fh_resolve_status (cs, stat, nlm4err); +        nfs_request_user_init (&nfu, cs->req); +        nlm4_lock_to_gf_flock (&flock, &cs->args.nlm4_unlockargs.alock, 0); +        nlm_copy_lkowner (&nfu.lk_owner, &cs->args.nlm4_unlockargs.alock.oh); +        flock.l_type = F_UNLCK; +        ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_SETLK, +                      &flock, nlm4svc_unlock_cbk, cs); + +        if (ret < 0) +                stat = nlm4_errno_to_nlm4stat (-ret); +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to call lk()"); +                nlm4_generic_reply (cs->req, cs->args.nlm4_unlockargs.cookie, +                                    stat); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + +int +nlm4_cancel_resume (void *carg) +{ +        nlm4_stats                      stat = nlm4_failed; +        int                             ret = -1; +        nfs3_call_state_t               *cs = NULL; +        nlm_client_t                    *nlmclnt = NULL; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        nlm4_check_fh_resolve_status (cs, stat, nlm4err); + +        nlmclnt = nlm_get_uniq (cs->args.nlm4_cancargs.alock.caller_name); +        if (nlmclnt == NULL) { +                gf_log (GF_NLM, GF_LOG_ERROR, "nlm_get_uniq() returned NULL"); +                goto nlm4err; +        } +        cs->fd = fd_lookup_uint64 (cs->resolvedloc.inode, (uint64_t)nlmclnt); +        if (cs->fd == NULL) { +                gf_log (GF_NLM, GF_LOG_ERROR, "nlm_get_uniq() returned NULL"); +                goto nlm4err; +        } +        ret = nlm4_unlock_fd_resume (cs); + +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to unlock_fd_resume()"); +                nlm4_generic_reply (cs->req, cs->args.nlm4_cancargs.cookie, +                                    stat); +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + +int +nlm4svc_cancel (rpcsvc_request_t *req) +{ +        xlator_t                        *vol = NULL; +        nlm4_stats                      stat = nlm4_failed; +        struct nfs_state               *nfs = NULL; +        nfs3_state_t                   *nfs3 = NULL; +        nfs3_call_state_t               *cs = NULL; +        int                             ret = RPCSVC_ACTOR_ERROR; +        struct nfs3_fh                  fh = {{0}, }; + +        if (!req) +                return ret; + +        nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); +        nfs = nfs_state (nfs3->nfsx); +        nlm4_handle_call_state_init (nfs->nfs3state, cs, req, +                                     stat, rpcerr); + +        nlm4_prep_nlm4_cancargs (&cs->args.nlm4_cancargs, &fh, &cs->lkowner, +                                 cs->cookiebytes); +        if (xdr_to_nlm4_cancelargs(req->msg[0], &cs->args.nlm4_cancargs) <= 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto rpcerr; +        } + +        nlm4_validate_gluster_fh (&fh, stat, nlm4err); +        nlm4_map_fh_to_volume (cs->nfs3state, &fh, req, vol, stat, nlm4err); + +        if (nlm_grace_period) { +                gf_log (GF_NLM, GF_LOG_WARNING, "NLM in grace period"); +                stat = nlm4_denied_grace_period; +                nlm4_generic_reply (req, cs->args.nlm4_unlockargs.cookie, stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +        cs->vol = vol; +        nlm4_volume_started_check (nfs3, vol, ret, rpcerr); + +        ret = nfs3_fh_resolve_and_resume (cs, &fh, +                                          NULL, nlm4_cancel_resume); + +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to resolve and resume"); +                nlm4_generic_reply (cs->req, cs->args.nlm4_cancargs.cookie, +                                    stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +rpcerr: +        if (ret < 0) { +                nfs3_call_state_wipe (cs); +        } +        return ret; +} + +int +nlm4_unlock_resume (void *carg) +{ +        nlm4_stats                      stat = nlm4_failed; +        int                             ret = -1; +        nfs3_call_state_t               *cs = NULL; +        nlm_client_t                    *nlmclnt = NULL; + +        if (!carg) +                return ret; + +        cs = (nfs3_call_state_t *)carg; +        nlm4_check_fh_resolve_status (cs, stat, nlm4err); + +        nlmclnt = nlm_get_uniq (cs->args.nlm4_unlockargs.alock.caller_name); +        if (nlmclnt == NULL) { +                gf_log (GF_NLM, GF_LOG_ERROR, "nlm_get_uniq() returned NULL"); +                goto nlm4err; +        } +        cs->fd = fd_lookup_uint64 (cs->resolvedloc.inode, (uint64_t)nlmclnt); +        if (cs->fd == NULL) { +                gf_log (GF_NLM, GF_LOG_ERROR, "fd_lookup_uint64() returned NULL"); +                goto nlm4err; +        } +        ret = nlm4_unlock_fd_resume (cs); + +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to unlock_fd_resume"); +                nlm4_generic_reply (cs->req, cs->args.nlm4_unlockargs.cookie, +                                    stat); + +                nfs3_call_state_wipe (cs); +        } + +        return ret; +} + +int +nlm4svc_unlock (rpcsvc_request_t *req) +{ +        xlator_t                        *vol = NULL; +        nlm4_stats                      stat = nlm4_failed; +        struct nfs_state               *nfs = NULL; +        nfs3_state_t                   *nfs3 = NULL; +        nfs3_call_state_t               *cs = NULL; +        int                             ret = RPCSVC_ACTOR_ERROR; +        struct nfs3_fh                  fh = {{0}, }; + +        if (!req) +                return ret; + +        nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); +        nfs = nfs_state (nfs3->nfsx); +        nlm4_handle_call_state_init (nfs->nfs3state, cs, req, +                                     stat, rpcerr); + +        nlm4_prep_nlm4_unlockargs (&cs->args.nlm4_unlockargs, &fh, &cs->lkowner, +                                   cs->cookiebytes); +        if (xdr_to_nlm4_unlockargs(req->msg[0], &cs->args.nlm4_unlockargs) <= 0) +        { +                gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding args"); +                rpcsvc_request_seterr (req, GARBAGE_ARGS); +                goto rpcerr; +        } + +        nlm4_validate_gluster_fh (&fh, stat, nlm4err); +        nlm4_map_fh_to_volume (cs->nfs3state, &fh, req, vol, stat, nlm4err); + +        if (nlm_grace_period) { +                gf_log (GF_NLM, GF_LOG_WARNING, "NLM in grace period"); +                stat = nlm4_denied_grace_period; +                nlm4_generic_reply (req, cs->args.nlm4_unlockargs.cookie, stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +        cs->vol = vol; +        cs->trans = rpcsvc_request_transport_ref(req); +        nlm4_volume_started_check (nfs3, vol, ret, rpcerr); + +        ret = nfs3_fh_resolve_and_resume (cs, &fh, +                                          NULL, nlm4_unlock_resume); + +nlm4err: +        if (ret < 0) { +                gf_log (GF_NLM, GF_LOG_ERROR, "unable to resolve and resume"); +                nlm4_generic_reply (req, cs->args.nlm4_unlockargs.cookie, stat); +                nfs3_call_state_wipe (cs); +                return 0; +        } + +rpcerr: +        if (ret < 0) { +                nfs3_call_state_wipe (cs); +        } +        return ret; +} + +void +nlm4svc_sm_notify (struct nlm_sm_status *status) +{ +        gf_log (GF_NLM, GF_LOG_INFO, "sm_notify: %s, state: %d", +                status->mon_name, +                status->state); +        nlm_cleanup_fds (status->mon_name); +} + +rpcsvc_actor_t  nlm4svc_actors[NLM4_PROC_COUNT] = { +        {"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}, +        {"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_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_RES, NULL, NULL, NULL}, +        {"SM_NOTIFY", NLM4_SM_NOTIFY, NULL, NULL, NULL}, +}; + +rpcsvc_program_t        nlm4prog = { +        .progname       = "NLM4", +        .prognum        = NLM_PROGRAM, +        .progver        = NLM_V4, +        .progport       = GF_NLM4_PORT, +        .actors         = nlm4svc_actors, +        .numactors      = NLM4_PROC_COUNT, +        .min_auth       = AUTH_NULL, +}; + + +int +nlm4_init_state (xlator_t *nfsx) +{ +        return 0; +} + +extern void *nsm_thread (void *argv); + +void nlm_grace_period_over(void *arg) +{ +        nlm_grace_period = 0; +} + +rpcsvc_program_t * +nlm4svc_init(xlator_t *nfsx) +{ +        struct nfs3_state *ns = NULL; +        struct nfs_state *nfs = NULL; +        dict_t *options = NULL; +        int ret = -1; +        char *portstr = NULL; +        pthread_t thr; +        struct timeval timeout = {0,}; + +        nfs = (struct nfs_state*)nfsx->private; + +        ns = nfs->nfs3state; +        if (!ns) { +                gf_log (GF_NLM, GF_LOG_ERROR, "NLM4 init failed"); +                goto err; +        } +        nlm4prog.private = ns; + +        options = dict_new (); + +        ret = gf_asprintf (&portstr, "%d", GF_NLM4_PORT); +        if (ret == -1) +                goto err; + +        ret = dict_set_dynstr (options, "transport.socket.listen-port", +                               portstr); +        if (ret == -1) +                goto err; +        ret = dict_set_str (options, "transport-type", "socket"); +        if (ret == -1) { +                gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error"); +                goto err; +        } + +        if (nfs->allow_insecure) { +                ret = dict_set_str (options, "rpc-auth-allow-insecure", "on"); +                if (ret == -1) { +                        gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error"); +                        goto err; +                } +                ret = dict_set_str (options, "rpc-auth.ports.insecure", "on"); +                if (ret == -1) { +                        gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error"); +                        goto err; +                } +        } + +        rpcsvc_create_listeners (nfs->rpcsvc, options, "NLM"); +        if (ret == -1) { +                gf_log (GF_NLM, GF_LOG_ERROR, "Unable to create listeners"); +                dict_unref (options); +                goto err; +        } +        INIT_LIST_HEAD(&nlm_client_list); +        LOCK_INIT (&nlm_client_list_lk); + +        pthread_create (&thr, NULL, nsm_thread, (void*)NULL); + +        timeout.tv_sec = nlm_grace_period; +        gf_timer_call_after (nfsx->ctx, timeout, nlm_grace_period_over, NULL); +        return &nlm4prog; +err: +        return NULL; +} diff --git a/xlators/nfs/server/src/nlm4.h b/xlators/nfs/server/src/nlm4.h new file mode 100644 index 00000000000..3c00186d971 --- /dev/null +++ b/xlators/nfs/server/src/nlm4.h @@ -0,0 +1,78 @@ +/* +  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/>. +*/ + +#ifndef _NLM4_H_ +#define _NLM4_H_ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "rpcsvc.h" +#include "dict.h" +#include "xlator.h" +#include "iobuf.h" +#include "nfs.h" +#include "list.h" +#include "xdr-nfs3.h" +#include "locking.h" +#include "nfs3-fh.h" +#include "uuid.h" +#include "nlm4-xdr.h" +#include "lkowner.h" + +/* Registered with portmap */ +#define GF_NLM4_PORT            38468 +#define GF_NLM                  GF_NFS"-NLM" + +extern rpcsvc_program_t * +nlm4svc_init (xlator_t *nfsx); + +extern int +nlm4_init_state (xlator_t *nfsx); + +#define NLM_PROGRAM 100021 +#define NLM_V4 4 + +typedef struct nlm4_lwowner { +        char temp[1024]; +} nlm4_lkowner_t; + +typedef struct nlm_client { +        struct sockaddr_storage sa; +        pid_t uniq; +        struct list_head nlm_clients; +        struct list_head fdes; +        struct rpc_clnt *rpc_clnt; +        char *caller_name; +} nlm_client_t; + +typedef struct nlm_fde { +        struct list_head fde_list; +        fd_t *fd; +        int transit_cnt; +} nlm_fde_t; + +typedef struct { +        pthread_cond_t cond; +        pthread_mutex_t mutex; +} nlm_condmutex_t; + +#endif diff --git a/xlators/nfs/server/src/nlmcbk_svc.c b/xlators/nfs/server/src/nlmcbk_svc.c new file mode 100644 index 00000000000..5401dc39b96 --- /dev/null +++ b/xlators/nfs/server/src/nlmcbk_svc.c @@ -0,0 +1,122 @@ +/* +  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/>. +*/ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "nlmcbk-xdr.h" +#include "nlm4.h" +#include "logging.h" +#include <stdio.h> +#include <stdlib.h> +#include <rpc/pmap_clnt.h> +#include <string.h> +#include <memory.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#ifndef SIG_PF +#define SIG_PF void(*)(int) +#endif + +void +nlm4svc_sm_notify (struct nlm_sm_status *status); + +void *nlmcbk_sm_notify_0_svc(struct nlm_sm_status *status, struct svc_req *req) +{ +        nlm4svc_sm_notify (status); +        return NULL; +} + +static void +nlmcbk_program_0(struct svc_req *rqstp, register SVCXPRT *transp) +{ +	union { +		struct nlm_sm_status nlmcbk_sm_notify_0_arg; +	} argument; +	char *result; +	xdrproc_t _xdr_argument, _xdr_result; +	char *(*local)(char *, struct svc_req *); + +	switch (rqstp->rq_proc) { +	case NULLPROC: +		(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); +		return; + +	case NLMCBK_SM_NOTIFY: +		_xdr_argument = (xdrproc_t) xdr_nlm_sm_status; +		_xdr_result = (xdrproc_t) xdr_void; +		local = (char *(*)(char *, struct svc_req *)) nlmcbk_sm_notify_0_svc; +		break; + +	default: +		svcerr_noproc (transp); +		return; +	} +	memset ((char *)&argument, 0, sizeof (argument)); +	if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { +		svcerr_decode (transp); +		return; +	} +	result = (*local)((char *)&argument, rqstp); +	if (!svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) { +		svcerr_systemerr (transp); +	} + +	if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { +		gf_log (GF_NLM, GF_LOG_ERROR, "unable to free arguments"); +                return; +	} +	return; +} + +void * +nsm_thread (void *argv) +{ +	register SVCXPRT *transp; + +	pmap_unset (NLMCBK_PROGRAM, NLMCBK_V1); + +	transp = svcudp_create(RPC_ANYSOCK); +	if (transp == NULL) { +		gf_log (GF_NLM, GF_LOG_ERROR, "cannot create udp service."); +                return NULL; +	} +	if (!svc_register(transp, NLMCBK_PROGRAM, NLMCBK_V1, nlmcbk_program_0, IPPROTO_UDP)) { +		gf_log (GF_NLM, GF_LOG_ERROR, "unable to register (NLMCBK_PROGRAM, NLMCBK_V0, udp)."); +                return NULL; +	} + +	transp = svctcp_create(RPC_ANYSOCK, 0, 0); +	if (transp == NULL) { +		gf_log (GF_NLM, GF_LOG_ERROR, "cannot create tcp service."); +                return NULL; +	} +	if (!svc_register(transp, NLMCBK_PROGRAM, NLMCBK_V1, nlmcbk_program_0, IPPROTO_TCP)) { +		gf_log (GF_NLM, GF_LOG_ERROR, "unable to register (NLMCBK_PROGRAM, NLMCBK_V0, tcp)."); +                return NULL; +	} + +	svc_run (); +	gf_log (GF_NLM, GF_LOG_ERROR, "svc_run returned"); +        return NULL; +	/* NOTREACHED */ +}  | 
