/*
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;
|