summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh Amaravathi <rajesh@redhat.com>2012-04-12 14:49:44 +0530
committerVijay Bellur <vijay@gluster.com>2012-05-17 02:12:49 -0700
commitcbcf82aa58058fe05dbd9a8d8879ca0364e5df95 (patch)
tree83c7dc8da592fb0442d5626eac6779c813d61655
parentd8ede99e6f429d3a63b794c495f99fc8f76e9651 (diff)
nfs/nlm: procedures for PC clients
* This change introduces four NLMv4 procedures: NM_LOCK, SHARE, UNSHARE and FREE_ALL. These are used by PC clients (windows/dos) to control access to files. 1. NM_LOCK: this lock is not monitored by statd. 2. SHARE: A share reservation is a lock on the whole file that is taken whenever a file is opened on windows clients. This has ACCESS (N, R, W, RW) and DENY MODE (N, R, W, RW). ACCESS: mode of access requested by the client; DENY MODE: what the requesting client wants to deny other clients. 3. UNSHARE: remove a share reservation obtained by SHARE. Called while closing a file. 4. FREE_ALL: remove all share reservations and locks, both monitored and unmonitored, of the calling client. * lock and nm_lock use a common function with only a flag conveying whether or not to monitor a lock. * NOTES: 1. SHARE reservations are not STACK_WIND'd to subsequent xlators. These are maintained in-memory in the nfs xlator. 2. Consequently, for SHARE reservations to work effectively, all PC clients *must* mount from the same gNfs server. Not doing so will result in different servers maintaining separate SHARE reservations which will not be enforced for obvious reasons. Change-Id: Id4f22670a94ed58691a6a7f4c80aa8c11421a277 BUG: 800287 Signed-off-by: Rajesh Amaravathi <rajesh@redhat.com> Reviewed-on: http://review.gluster.com/3212 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Krishna Srinivas <krishna@gluster.com>
-rw-r--r--rpc/xdr/src/msg-nfs3.c20
-rw-r--r--rpc/xdr/src/msg-nfs3.h9
-rw-r--r--rpc/xdr/src/nlm4-xdr.c11
-rw-r--r--rpc/xdr/src/nlm4-xdr.h9
-rw-r--r--rpc/xdr/src/nlm4.x9
-rw-r--r--xlators/nfs/server/src/nfs-mem-types.h1
-rw-r--r--xlators/nfs/server/src/nfs.c9
-rw-r--r--xlators/nfs/server/src/nfs3.h2
-rw-r--r--xlators/nfs/server/src/nlm4.c618
-rw-r--r--xlators/nfs/server/src/nlm4.h10
10 files changed, 661 insertions, 37 deletions
diff --git a/rpc/xdr/src/msg-nfs3.c b/rpc/xdr/src/msg-nfs3.c
index f800b3128fa..8078f23f097 100644
--- a/rpc/xdr/src/msg-nfs3.c
+++ b/rpc/xdr/src/msg-nfs3.c
@@ -517,6 +517,20 @@ xdr_to_nlm4_unlockargs (struct iovec inmsg, nlm4_unlockargs *args)
}
ssize_t
+xdr_to_nlm4_shareargs (struct iovec inmsg, nlm4_shareargs *args)
+{
+ return xdr_to_generic (inmsg, (void*)args,
+ (xdrproc_t)xdr_nlm4_shareargs);
+}
+
+ssize_t
+xdr_serialize_nlm4_shareres (struct iovec outmsg, nlm4_shareres *res)
+{
+ return xdr_serialize_generic (outmsg, (void *)res,
+ (xdrproc_t)xdr_nlm4_shareres);
+}
+
+ssize_t
xdr_serialize_nlm4_testargs (struct iovec outmsg, nlm4_testargs *args)
{
return xdr_serialize_generic (outmsg, (void*)args,
@@ -530,3 +544,9 @@ xdr_to_nlm4_res (struct iovec inmsg, nlm4_res *args)
(xdrproc_t)xdr_nlm4_res);
}
+ssize_t
+xdr_to_nlm4_freeallargs (struct iovec inmsg, nlm4_freeallargs *args)
+{
+ return xdr_to_generic (inmsg, (void*)args,
+ (xdrproc_t)xdr_nlm4_freeallargs);
+}
diff --git a/rpc/xdr/src/msg-nfs3.h b/rpc/xdr/src/msg-nfs3.h
index 1310e02f897..701df300a6e 100644
--- a/rpc/xdr/src/msg-nfs3.h
+++ b/rpc/xdr/src/msg-nfs3.h
@@ -203,9 +203,18 @@ extern ssize_t
xdr_to_nlm4_unlockargs (struct iovec inmsg, nlm4_unlockargs *args);
extern ssize_t
+xdr_to_nlm4_shareargs (struct iovec inmsg, nlm4_shareargs *args);
+
+extern ssize_t
+xdr_serialize_nlm4_shareres (struct iovec outmsg, nlm4_shareres *res);
+
+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);
+extern ssize_t
+xdr_to_nlm4_freeallargs (struct iovec inmsg, nlm4_freeallargs *args);
+
#endif
diff --git a/rpc/xdr/src/nlm4-xdr.c b/rpc/xdr/src/nlm4-xdr.c
index b41fbb15cac..4cf6a51e8fd 100644
--- a/rpc/xdr/src/nlm4-xdr.c
+++ b/rpc/xdr/src/nlm4-xdr.c
@@ -228,6 +228,17 @@ xdr_nlm4_shareres (XDR *xdrs, nlm4_shareres *objp)
return TRUE;
}
+bool_t
+xdr_nlm4_freeallargs (XDR *xdrs, nlm4_freeallargs *objp)
+{
+ if (!xdr_string (xdrs, &objp->name, LM_MAXSTRLEN))
+ return FALSE;
+ if (!xdr_uint32_t (xdrs, &objp->state))
+ return FALSE;
+ return TRUE;
+}
+
+
/*
bool_t
xdr_nlm_sm_status (XDR *xdrs, nlm_sm_status *objp)
diff --git a/rpc/xdr/src/nlm4-xdr.h b/rpc/xdr/src/nlm4-xdr.h
index d95a6ad6e58..3799f6b1d98 100644
--- a/rpc/xdr/src/nlm4-xdr.h
+++ b/rpc/xdr/src/nlm4-xdr.h
@@ -183,6 +183,13 @@ struct nlm4_shareres {
};
typedef struct nlm4_shareres nlm4_shareres;
+struct nlm4_freeallargs {
+ char *name;
+ u_int32_t state;
+};
+typedef struct nlm4_freeallargs nlm4_freeallargs;
+
+
#define NLM4_NULL 0
#define NLM4_TEST 1
#define NLM4_LOCK 2
@@ -229,6 +236,7 @@ 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*);
+extern bool_t xdr_nlm4_freeallargs (XDR *, nlm4_freeallargs*);
#else /* K&R C */
extern bool_t xdr_netobj ();
@@ -248,6 +256,7 @@ extern bool_t xdr_nlm4_cancargs ();
extern bool_t xdr_nlm4_unlockargs ();
extern bool_t xdr_nlm4_shareargs ();
extern bool_t xdr_nlm4_shareres ();
+extern bool_t xdr_nlm4_freeallargs ();
#endif /* K&R C */
diff --git a/rpc/xdr/src/nlm4.x b/rpc/xdr/src/nlm4.x
index d738b27770d..a6de6f32bf4 100644
--- a/rpc/xdr/src/nlm4.x
+++ b/rpc/xdr/src/nlm4.x
@@ -74,7 +74,7 @@ struct nlm4_holder {
};
struct nlm4_lock {
- string caller_name<MAXNAMELEN>;
+ string caller_name<LM_MAXSTRLEN>;
netobj fh;
netobj oh;
u_int32_t svid;
@@ -83,7 +83,7 @@ struct nlm4_lock {
};
struct nlm4_share {
- string caller_name<MAXNAMELEN>;
+ string caller_name<LM_MAXSTRLEN>;
netobj fh;
netobj oh;
fsh_mode mode;
@@ -146,6 +146,11 @@ struct nlm4_shareres {
int sequence;
};
+struct nlm4_freeallargs {
+ string name<LM_MAXSTRLEN>; /* client hostname */
+ uint32 state; /* unused */
+};
+
/*
* argument for the procedure called by rpc.statd when a monitored host
* status change.
diff --git a/xlators/nfs/server/src/nfs-mem-types.h b/xlators/nfs/server/src/nfs-mem-types.h
index e2dae4a3403..1a3b25281ba 100644
--- a/xlators/nfs/server/src/nfs-mem-types.h
+++ b/xlators/nfs/server/src/nfs-mem-types.h
@@ -47,6 +47,7 @@ enum gf_nfs_mem_types_ {
gf_nfs_mt_nlm4_cm,
gf_nfs_mt_nlm4_fde,
gf_nfs_mt_nlm4_nlmclnt,
+ gf_nfs_mt_nlm4_share,
gf_nfs_mt_end
};
#endif
diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c
index 42edc95f6d1..a48e114999a 100644
--- a/xlators/nfs/server/src/nfs.c
+++ b/xlators/nfs/server/src/nfs.c
@@ -849,6 +849,15 @@ fini (xlator_t *this)
int32_t
nfs_forget (xlator_t *this, inode_t *inode)
{
+ uint64_t ctx = 0;
+ struct list_head *head = NULL;
+
+ if (inode_ctx_del (inode, this, &ctx))
+ return -1;
+
+ head = (struct list_head *)ctx;
+ GF_FREE (head);
+
return 0;
}
diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h
index e6b9edee5ca..78eb01b60b9 100644
--- a/xlators/nfs/server/src/nfs3.h
+++ b/xlators/nfs/server/src/nfs3.h
@@ -154,6 +154,7 @@ typedef union args_ {
nlm4_unlockargs nlm4_unlockargs;
nlm4_shareargs nlm4_shareargs;
nlm4_shareres nlm4_shareres;
+ nlm4_freeallargs nlm4_freeallargs;
} args;
@@ -230,6 +231,7 @@ struct nfs3_local {
nlm4_lkowner_t lkowner;
char cookiebytes[1024];
struct nfs3_fh lockfh;
+ int monitor;
rpc_transport_t *trans;
call_frame_t *frame;
};
diff --git a/xlators/nfs/server/src/nlm4.c b/xlators/nfs/server/src/nlm4.c
index 4f9a1c4fcef..72f71609a51 100644
--- a/xlators/nfs/server/src/nlm4.c
+++ b/xlators/nfs/server/src/nlm4.c
@@ -199,12 +199,40 @@ nlm4_prep_nlm4_unlockargs (nlm4_unlockargs *args, struct nfs3_fh *fh,
}
void
+nlm4_prep_shareargs (nlm4_shareargs *args, struct nfs3_fh *fh,
+ nlm4_lkowner_t *oh, char *cookiebytes)
+{
+ memset (args, 0, sizeof (*args));
+ args->share.fh.n_bytes = (void *)fh;
+ args->share.oh.n_bytes = (void *)oh;
+ args->cookie.n_bytes = (void *)cookiebytes;
+}
+
+void
+nlm4_prep_freeallargs (nlm4_freeallargs *args, nlm4_lkowner_t *oh)
+{
+ memset (args, 0, sizeof (*args));
+ args->name = (void *)oh;
+}
+
+void
nlm_copy_lkowner (gf_lkowner_t *dst, netobj *src)
{
dst->len = src->n_len;
memcpy (dst->data, src->n_bytes, dst->len);
}
+int
+nlm_is_oh_same_lkowner (gf_lkowner_t *a, netobj *b)
+{
+ if (!a || !b) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "invalid args");
+ return -1;
+ }
+
+ return (a->len == b->n_len &&
+ !memcmp (a->data, b->n_bytes, a->len));
+}
nfsstat3
nlm4_errno_to_nlm4stat (int errnum)
@@ -251,6 +279,7 @@ nlm4_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req)
cs->req = req;
cs->nfsx = s->nfsx;
cs->nfs3state = s;
+ cs->monitor = 1;
return cs;
}
@@ -270,9 +299,11 @@ nlm_monitor (char *caller_name)
}
}
UNLOCK (&nlm_client_list_lk);
- if (monitor == -1) {
- gf_log (GF_NLM, GF_LOG_ERROR, "%s was not found in the nlmclnt list", caller_name);
- }
+
+ if (monitor == -1)
+ gf_log (GF_NLM, GF_LOG_ERROR, "%s was not found in "
+ "the nlmclnt list", caller_name);
+
return monitor;
}
@@ -401,6 +432,7 @@ nlm_add_nlmclnt (char *caller_name)
INIT_LIST_HEAD(&nlmclnt->fdes);
INIT_LIST_HEAD(&nlmclnt->nlm_clients);
+ INIT_LIST_HEAD(&nlmclnt->shares);
list_add (&nlmclnt->nlm_clients, &nlm_client_list);
nlmclnt->caller_name = gf_strdup (caller_name);
@@ -541,23 +573,31 @@ out:
}
nlm_client_t *
-nlm_get_uniq (char *caller_name)
+__nlm_get_uniq (char *caller_name)
{
nlm_client_t *nlmclnt = NULL;
- int nlmclnt_found = 0;
- LOCK (&nlm_client_list_lk);
+ if (!caller_name)
+ return NULL;
+
list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) {
- if (!strcmp(caller_name, nlmclnt->caller_name)) {
- nlmclnt_found = 1;
- break;
- }
+ if (!strcmp(caller_name, nlmclnt->caller_name))
+ return nlmclnt;
}
+
+ return NULL;
+}
+
+nlm_client_t *
+nlm_get_uniq (char *caller_name)
+{
+ nlm_client_t *nlmclnt = NULL;
+
+ LOCK (&nlm_client_list_lk);
+ nlmclnt = __nlm_get_uniq (caller_name);
UNLOCK (&nlm_client_list_lk);
- if (nlmclnt_found)
- return nlmclnt;
- else
- return NULL;
+
+ return nlmclnt;
}
@@ -1247,11 +1287,11 @@ nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct gf_flock *flock,
dict_t *xdata)
{
- nlm4_stats stat = nlm4_denied;
- nfs3_call_state_t *cs = NULL;
- int transit_cnt = -1;
+ nlm4_stats stat = nlm4_denied;
+ int transit_cnt = -1;
char *caller_name = NULL;
- pthread_t thr;
+ nfs3_call_state_t *cs = NULL;
+ pthread_t thr;
cs = frame->local;
caller_name = cs->args.nlm4_lockargs.alock.caller_name;
@@ -1265,7 +1305,7 @@ nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
goto err;
} else {
stat = nlm4_granted;
- if (!nlm_monitor (caller_name)) {
+ if (cs->monitor && !nlm_monitor (caller_name)) {
/* FIXME: handle nsm_monitor failure */
pthread_create (&thr, NULL, nsm_monitor, (void*)caller_name);
}
@@ -1331,8 +1371,8 @@ int
nlm4_lock_resume (void *carg)
{
nlm4_stats stat = nlm4_failed;
- int ret = -1;
- nfs3_call_state_t *cs = NULL;
+ int ret = -1;
+ nfs3_call_state_t *cs = NULL;
if (!carg)
return ret;
@@ -1354,17 +1394,16 @@ nlm4err:
return ret;
}
-
int
-nlm4svc_lock (rpcsvc_request_t *req)
+nlm4svc_lock_common (rpcsvc_request_t *req, int mon)
{
- 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}, };
+ int ret = RPCSVC_ACTOR_ERROR;
+ nlm4_stats stat = nlm4_failed;
+ struct nfs3_fh fh = {{0}, };
+ xlator_t *vol = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
if (!req)
return ret;
@@ -1381,7 +1420,9 @@ nlm4svc_lock (rpcsvc_request_t *req)
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
+
fh = cs->lockfh;
+ cs->monitor = mon;
nlm4_validate_gluster_fh (&fh, stat, nlm4err);
nlm4_map_fh_to_volume (cs->nfs3state, fh, req, vol, stat, nlm4err);
@@ -1415,10 +1456,23 @@ rpcerr:
if (ret < 0) {
nfs3_call_state_wipe (cs);
}
+
return ret;
}
int
+nlm4svc_lock (rpcsvc_request_t *req)
+{
+ return nlm4svc_lock_common (req, 1);
+}
+
+int
+nlm4svc_nm_lock (rpcsvc_request_t *req)
+{
+ return nlm4svc_lock_common (req, 0);
+}
+
+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,
dict_t *xdata)
@@ -1729,6 +1783,500 @@ rpcerr:
return ret;
}
+int
+nlm4_share_reply (nfs3_call_state_t *cs, nlm4_stats stat)
+{
+ nlm4_shareres res = {{0}, 0, 0};
+
+ if (!cs)
+ return -1;
+
+ res.cookie = cs->args.nlm4_shareargs.cookie;
+ res.stat = stat;
+ res.sequence = 0;
+
+ nlm4svc_submit_reply (cs->req, (void *)&res,
+ (nlm4_serializer)xdr_serialize_nlm4_shareres);
+ return 0;
+}
+
+nlm_share_t *
+nlm4_share_new ()
+{
+ nlm_share_t *share = NULL;
+
+ share = GF_CALLOC (1, sizeof (nlm_share_t),
+ gf_nfs_mt_nlm4_share);
+ if (!share)
+ goto out;
+
+ INIT_LIST_HEAD (&share->client_list);
+ INIT_LIST_HEAD (&share->inode_list);
+ out:
+ return share;
+}
+
+int
+nlm4_add_share_to_inode (nlm_share_t *share)
+{
+ int ret = -1;
+ uint64_t ctx = 0;
+ struct list_head *head = NULL;
+ xlator_t *this = NULL;
+ inode_t *inode = NULL;
+
+ this = THIS;
+ inode = share->inode;
+ ret = inode_ctx_get (inode, this, &ctx);
+
+ head = (struct list_head *)ctx;
+
+ if (ret || !head) {
+ head = GF_CALLOC (1, sizeof (struct list_head),
+ gf_common_mt_list_head);
+ if (!head ) {
+ ret = -1;
+ goto out;
+ }
+
+ INIT_LIST_HEAD (head);
+ ret = inode_ctx_put (inode, this, (uint64_t)head);
+ if (ret)
+ goto out;
+ }
+
+ list_add (&share->inode_list, head);
+
+ out:
+ if (ret && head)
+ GF_FREE (head);
+
+ return ret;
+}
+
+int
+nlm4_approve_share_reservation (nfs3_call_state_t *cs)
+{
+ int ret = -1;
+ uint64_t ctx = 0;
+ fsh_mode req_mode = 0;
+ fsh_access req_access = 0;
+ inode_t *inode = NULL;
+ nlm_share_t *share = NULL;
+ struct list_head *head = NULL;
+
+ if (!cs)
+ goto out;
+
+ inode = cs->resolvedloc.inode;
+
+ ret = inode_ctx_get (inode, THIS, &ctx);
+ if (ret) {
+ ret = 0;
+ goto out;
+ }
+
+ head = (struct list_head *)ctx;
+ if (!head || list_empty (head))
+ goto out;
+
+ req_mode = cs->args.nlm4_shareargs.share.mode;
+ req_access = cs->args.nlm4_shareargs.share.access;
+
+ list_for_each_entry (share, head, inode_list) {
+ ret = (((req_mode & share->access) == 0) &&
+ ((req_access & share->mode) == 0));
+ if (!ret) {
+ ret = -1;
+ goto out;
+ }
+ }
+ ret = 0;
+
+ out:
+ return ret;
+}
+
+int
+nlm4_create_share_reservation (nfs3_call_state_t *cs)
+{
+ int ret = -1;
+ nlm_share_t *share = NULL;
+ nlm_client_t *client = NULL;
+ inode_t *inode = NULL;
+
+ LOCK (&nlm_client_list_lk);
+
+ inode = inode_ref (cs->resolvedloc.inode);
+ if (!inode) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "inode not found");
+ goto out;
+ }
+
+ client = __nlm_get_uniq (cs->args.nlm4_shareargs.share.caller_name);
+ if (!client) {
+ /* DO NOT add client. the client is supposed
+ to be here, since nlm4svc_share adds it */
+ gf_log (GF_NLM, GF_LOG_ERROR, "client not found");
+ goto out;
+ }
+
+ ret = nlm4_approve_share_reservation (cs);
+ if (ret)
+ goto out;
+
+ share = nlm4_share_new ();
+ if (!share) {
+ ret = -1;
+ goto out;
+ }
+
+ share->inode = inode;
+ share->mode = cs->args.nlm4_shareargs.share.mode;
+ share->access = cs->args.nlm4_shareargs.share.access;
+ nlm_copy_lkowner (&share->lkowner,
+ &cs->args.nlm4_shareargs.share.oh);
+
+ ret = nlm4_add_share_to_inode (share);
+ if (ret)
+ goto out;
+
+ list_add (&share->client_list, &client->shares);
+
+ out:
+ if (ret && inode) {
+ inode_unref (inode);
+ if (share)
+ GF_FREE (share);
+ }
+
+ UNLOCK (&nlm_client_list_lk);
+ return ret;
+}
+
+/*
+ SHARE and UNSHARE calls DO NOT perform STACK_WIND,
+ the (non-monitored) share reservations are maintained
+ at *nfs xlator level only*, in memory
+*/
+int
+nlm4_share_resume (void *call_state)
+{
+ int ret = -1;
+ nlm4_stats stat = nlm4_failed;
+ nfs3_call_state_t *cs = NULL;
+
+ if (!call_state)
+ return ret;
+
+ cs = (nfs3_call_state_t *)call_state;
+ nlm4_check_fh_resolve_status (cs, stat, out);
+
+ ret = nlm4_create_share_reservation (cs);
+ if (!ret)
+ stat = nlm4_granted;
+
+ out:
+ nlm4_share_reply (cs, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+int
+nlm4svc_share (rpcsvc_request_t *req)
+{
+ nlm4_stats stat = nlm4_failed;
+ xlator_t *vol = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
+ struct nfs3_fh fh = {{0}, };
+ int ret = RPCSVC_ACTOR_ERROR;
+
+ 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_shareargs (&cs->args.nlm4_shareargs, &cs->lockfh,
+ &cs->lkowner, cs->cookiebytes);
+
+ if (xdr_to_nlm4_shareargs (req->msg[0],
+ &cs->args.nlm4_shareargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding SHARE 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_shareargs.reclaim) {
+ gf_log (GF_NLM, GF_LOG_DEBUG, "NLM in grace period");
+ stat = nlm4_denied_grace_period;
+ nlm4_share_reply (cs, 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_shareargs.share.caller_name);
+
+ ret = nfs3_fh_resolve_and_resume (cs, &fh, NULL, nlm4_share_resume);
+
+ nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "SHARE call failed");
+ nlm4_share_reply (cs, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+ rpcerr:
+ if (ret < 0)
+ nfs3_call_state_wipe (cs);
+
+ return ret;
+}
+
+int
+nlm4_remove_share_reservation (nfs3_call_state_t *cs)
+{
+ int ret = -1;
+ uint64_t ctx = 0;
+ fsh_mode req_mode = 0;
+ fsh_access req_access = 0;
+ nlm_share_t *share = NULL;
+ nlm_share_t *tmp = NULL;
+ nlm_client_t *client = NULL;
+ char *caller = NULL;
+ inode_t *inode = NULL;
+ xlator_t *this = NULL;
+ struct list_head *head = NULL;
+ nlm4_shareargs *args = NULL;
+
+ LOCK (&nlm_client_list_lk);
+
+ args = &cs->args.nlm4_shareargs;
+ caller = args->share.caller_name;
+
+ client = __nlm_get_uniq (caller);
+ if (!client) {
+ gf_log (GF_NLM, GF_LOG_ERROR,
+ "client not found: %s", caller);
+ goto out;
+ }
+
+ inode = cs->resolvedloc.inode;
+ if (!inode) {
+ gf_log (GF_NLM, GF_LOG_ERROR,
+ "inode not found: client: %s", caller);
+ goto out;
+ }
+
+ this = THIS;
+ ret = inode_ctx_get (inode, this, &ctx);
+ if (ret) {
+ gf_log (GF_NLM, GF_LOG_ERROR,
+ "no shares found for inode:"
+ "gfid: %s; client: %s",
+ inode->gfid, caller);
+ goto out;
+ }
+
+ head = (struct list_head *)ctx;
+ if (list_empty (head)) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+ req_mode = args->share.mode;
+ req_access = args->share.access;
+
+ list_for_each_entry_safe (share, tmp, head, inode_list) {
+ ret = ((req_mode == share->mode) &&
+ (req_access == share->access) &&
+ nlm_is_oh_same_lkowner (&share->lkowner, &args->share.oh));
+ if (ret) {
+ list_del (&share->client_list);
+ list_del (&share->inode_list);
+ inode_unref (share->inode);
+ GF_FREE (share);
+ break;
+ }
+ }
+
+ ret = 0;
+ out:
+ UNLOCK (&nlm_client_list_lk);
+ return ret;
+
+}
+
+int
+nlm4_unshare_resume (void *call_state)
+{
+ int ret = -1;
+ nlm4_stats stat = nlm4_failed;
+ nfs3_call_state_t *cs = NULL;
+
+ if (!call_state)
+ return ret;
+
+ cs = (nfs3_call_state_t *)call_state;
+
+ nlm4_check_fh_resolve_status (cs, stat, out);
+ ret = nlm4_remove_share_reservation (cs);
+ if (!ret)
+ stat = nlm4_granted;
+
+ out:
+ nlm4_share_reply (cs, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+int
+nlm4svc_unshare (rpcsvc_request_t *req)
+{
+ nlm4_stats stat = nlm4_failed;
+ xlator_t *vol = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
+ struct nfs3_fh fh = {{0}, };
+ int ret = RPCSVC_ACTOR_ERROR;
+
+ 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_shareargs (&cs->args.nlm4_shareargs, &cs->lockfh,
+ &cs->lkowner, cs->cookiebytes);
+
+ if (xdr_to_nlm4_shareargs (req->msg[0],
+ &cs->args.nlm4_shareargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding UNSHARE 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_shareargs.reclaim) {
+ gf_log (GF_NLM, GF_LOG_DEBUG, "NLM in grace period");
+ stat = nlm4_denied_grace_period;
+ nlm4_share_reply (cs, 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_unshare_resume);
+
+ nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "UNSHARE call failed");
+ nlm4_share_reply (cs, stat);
+ ret = 0;
+ return 0;
+ }
+
+ rpcerr:
+ if (ret < 0)
+ nfs3_call_state_wipe (cs);
+
+ return ret;
+}
+
+int
+nlm4_free_all_shares (char *caller_name)
+{
+ nlm_share_t *share = NULL;
+ nlm_share_t *tmp = NULL;
+ nlm_client_t *client = NULL;
+
+ LOCK (&nlm_client_list_lk);
+
+ client = __nlm_get_uniq (caller_name);
+ if (!client) {
+ gf_log (GF_NLM, GF_LOG_DEBUG,
+ "client not found: %s", caller_name);
+ goto out;
+ }
+
+ list_for_each_entry_safe (share, tmp, &client->shares, client_list) {
+ list_del (&share->inode_list);
+ list_del (&share->client_list);
+ inode_unref (share->inode);
+ GF_FREE (share);
+ }
+ out:
+ UNLOCK (&nlm_client_list_lk);
+ return 0;
+}
+
+int
+nlm4svc_free_all (rpcsvc_request_t *req)
+{
+ int ret = RPCSVC_ACTOR_ERROR;
+ nlm4_stats stat = nlm4_failed;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
+
+ nlm4_validate_nfs3_state (req, nfs3, stat, err, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ nlm4_handle_call_state_init (nfs->nfs3state, cs,
+ req, stat, err);
+
+ nlm4_prep_freeallargs (&cs->args.nlm4_freeallargs,
+ &cs->lkowner);
+
+ if (xdr_to_nlm4_freeallargs (req->msg[0],
+ &cs->args.nlm4_freeallargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding FREE_ALL args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto err;
+ }
+
+ ret = nlm4_free_all_shares (cs->args.nlm4_freeallargs.name);
+ if (ret)
+ goto err;
+
+ ret = nlm_cleanup_fds (cs->args.nlm4_freeallargs.name);
+ if (ret)
+ goto err;
+
+ err:
+ nfs3_call_state_wipe (cs);
+ if (ret)
+ gf_log (GF_NLM, GF_LOG_DEBUG,
+ "error in free all; stat: %d", stat);
+ return ret;
+
+}
+
void
nlm4svc_sm_notify (struct nlm_sm_status *status)
{
@@ -1757,17 +2305,17 @@ rpcsvc_actor_t nlm4svc_actors[NLM4_PROC_COUNT] = {
{"LOCK", NLM4_LOCK_RES, NULL, NULL, NULL},
{"CANCEL", NLM4_CANCEL_RES, NULL, NULL, NULL},
{"UNLOCK", NLM4_UNLOCK_RES, NULL, NULL, NULL},
- /* 15 ; 17,18,19 are dummy actors */
+ /* 15 ; procedures 17,18,19 are not defined by nlm */
{"GRANTED", NLM4_GRANTED_RES, NULL, NULL, NULL},
{"SM_NOTIFY", NLM4_SM_NOTIFY, NULL, NULL, NULL},
{"SEVENTEEN", NLM4_SEVENTEEN, NULL, NULL, NULL},
{"EIGHTEEN", NLM4_EIGHTEEN, NULL, NULL, NULL},
{"NINETEEN", NLM4_NINETEEN, NULL, NULL, NULL},
/* 20 */
- {"SHARE", NLM4_SHARE, NULL, NULL, NULL},
- {"UNSHARE", NLM4_UNSHARE, NULL, NULL, NULL},
- {"NM_LOCK", NLM4_NM_LOCK, NULL, NULL, NULL},
- {"FREE_ALL", NLM4_FREE_ALL, nlm4svc_null, NULL, NULL},
+ {"SHARE", NLM4_SHARE, nlm4svc_share, NULL, NULL},
+ {"UNSHARE", NLM4_UNSHARE, nlm4svc_unshare, NULL, NULL},
+ {"NM_LOCK", NLM4_NM_LOCK, nlm4svc_nm_lock, NULL, NULL},
+ {"FREE_ALL", NLM4_FREE_ALL, nlm4svc_free_all, NULL, NULL},
};
rpcsvc_program_t nlm4prog = {
diff --git a/xlators/nfs/server/src/nlm4.h b/xlators/nfs/server/src/nlm4.h
index db5874387f4..bcc7ae57343 100644
--- a/xlators/nfs/server/src/nlm4.h
+++ b/xlators/nfs/server/src/nlm4.h
@@ -60,11 +60,21 @@ typedef struct nlm_client {
pid_t uniq;
struct list_head nlm_clients;
struct list_head fdes;
+ struct list_head shares;
struct rpc_clnt *rpc_clnt;
char *caller_name;
int nsm_monitor;
} nlm_client_t;
+typedef struct nlm_share {
+ struct list_head client_list;
+ struct list_head inode_list;
+ gf_lkowner_t lkowner;
+ inode_t *inode;
+ fsh_mode mode;
+ fsh_access access;
+} nlm_share_t;
+
typedef struct nlm_fde {
struct list_head fde_list;
fd_t *fd;