aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-01 12:49:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-07-30 14:46:10 -0400
commitd3c7b7ccc199ee564177ee914c04771d6bc00295 (patch)
treeed5bda669f6ede2ac454bf853577e3c3f818642b
parentdaccbded7f153ec84a3baf3136052e41d0eab555 (diff)
NFSv4: Add support for the RELEASE_LOCKOWNER operation
This is needed by NFSv4.0 servers in order to keep the number of locking stateids at a manageable level. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4proc.c28
-rw-r--r--fs/nfs/nfs4state.c2
-rw-r--r--fs/nfs/nfs4xdr.c55
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs_xdr.h4
6 files changed, 91 insertions, 0 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index cee871471e8d..deaf37f5a7a9 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -236,6 +236,7 @@ extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nam
236extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); 236extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
237extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, 237extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
238 struct nfs4_fs_locations *fs_locations, struct page *page); 238 struct nfs4_fs_locations *fs_locations, struct page *page);
239extern void nfs4_release_lockowner(const struct nfs4_lock_state *);
239 240
240#if defined(CONFIG_NFS_V4_1) 241#if defined(CONFIG_NFS_V4_1)
241static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) 242static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index de9ff1505a24..5d3e8a2db99f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4414,6 +4414,34 @@ out:
4414 return err; 4414 return err;
4415} 4415}
4416 4416
4417static void nfs4_release_lockowner_release(void *calldata)
4418{
4419 kfree(calldata);
4420}
4421
4422const struct rpc_call_ops nfs4_release_lockowner_ops = {
4423 .rpc_release = nfs4_release_lockowner_release,
4424};
4425
4426void nfs4_release_lockowner(const struct nfs4_lock_state *lsp)
4427{
4428 struct nfs_server *server = lsp->ls_state->owner->so_server;
4429 struct nfs_release_lockowner_args *args;
4430 struct rpc_message msg = {
4431 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER],
4432 };
4433
4434 if (server->nfs_client->cl_mvops->minor_version != 0)
4435 return;
4436 args = kmalloc(sizeof(*args), GFP_NOFS);
4437 if (!args)
4438 return;
4439 args->lock_owner.clientid = server->nfs_client->cl_clientid;
4440 args->lock_owner.id = lsp->ls_id.id;
4441 msg.rpc_argp = args;
4442 rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, args);
4443}
4444
4417#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" 4445#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
4418 4446
4419int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, 4447int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 13e17e32e3e4..13a4f27e7271 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -701,6 +701,8 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
701 if (list_empty(&state->lock_states)) 701 if (list_empty(&state->lock_states))
702 clear_bit(LK_STATE_IN_USE, &state->flags); 702 clear_bit(LK_STATE_IN_USE, &state->flags);
703 spin_unlock(&state->state_lock); 703 spin_unlock(&state->state_lock);
704 if (lsp->ls_flags & NFS_LOCK_INITIALIZED)
705 nfs4_release_lockowner(lsp);
704 nfs4_free_lock_state(lsp); 706 nfs4_free_lock_state(lsp);
705} 707}
706 708
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 49df05afdc64..15185c2abd11 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -220,6 +220,11 @@ static int nfs4_stat_to_errno(int);
220 4) 220 4)
221#define decode_locku_maxsz (op_decode_hdr_maxsz + \ 221#define decode_locku_maxsz (op_decode_hdr_maxsz + \
222 decode_stateid_maxsz) 222 decode_stateid_maxsz)
223#define encode_release_lockowner_maxsz \
224 (op_encode_hdr_maxsz + \
225 encode_lockowner_maxsz)
226#define decode_release_lockowner_maxsz \
227 (op_decode_hdr_maxsz)
223#define encode_access_maxsz (op_encode_hdr_maxsz + 1) 228#define encode_access_maxsz (op_encode_hdr_maxsz + 1)
224#define decode_access_maxsz (op_decode_hdr_maxsz + 2) 229#define decode_access_maxsz (op_decode_hdr_maxsz + 2)
225#define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 230#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
@@ -474,6 +479,12 @@ static int nfs4_stat_to_errno(int);
474 decode_sequence_maxsz + \ 479 decode_sequence_maxsz + \
475 decode_putfh_maxsz + \ 480 decode_putfh_maxsz + \
476 decode_locku_maxsz) 481 decode_locku_maxsz)
482#define NFS4_enc_release_lockowner_sz \
483 (compound_encode_hdr_maxsz + \
484 encode_lockowner_maxsz)
485#define NFS4_dec_release_lockowner_sz \
486 (compound_decode_hdr_maxsz + \
487 decode_lockowner_maxsz)
477#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ 488#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
478 encode_sequence_maxsz + \ 489 encode_sequence_maxsz + \
479 encode_putfh_maxsz + \ 490 encode_putfh_maxsz + \
@@ -1116,6 +1127,17 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar
1116 hdr->replen += decode_locku_maxsz; 1127 hdr->replen += decode_locku_maxsz;
1117} 1128}
1118 1129
1130static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr)
1131{
1132 __be32 *p;
1133
1134 p = reserve_space(xdr, 4);
1135 *p = cpu_to_be32(OP_RELEASE_LOCKOWNER);
1136 encode_lockowner(xdr, lowner);
1137 hdr->nops++;
1138 hdr->replen += decode_release_lockowner_maxsz;
1139}
1140
1119static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) 1141static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
1120{ 1142{
1121 int len = name->len; 1143 int len = name->len;
@@ -2056,6 +2078,20 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_
2056 return 0; 2078 return 0;
2057} 2079}
2058 2080
2081static int nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, __be32 *p, struct nfs_release_lockowner_args *args)
2082{
2083 struct xdr_stream xdr;
2084 struct compound_hdr hdr = {
2085 .minorversion = 0,
2086 };
2087
2088 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2089 encode_compound_hdr(&xdr, req, &hdr);
2090 encode_release_lockowner(&xdr, &args->lock_owner, &hdr);
2091 encode_nops(&hdr);
2092 return 0;
2093}
2094
2059/* 2095/*
2060 * Encode a READLINK request 2096 * Encode a READLINK request
2061 */ 2097 */
@@ -3981,6 +4017,11 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
3981 return status; 4017 return status;
3982} 4018}
3983 4019
4020static int decode_release_lockowner(struct xdr_stream *xdr)
4021{
4022 return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER);
4023}
4024
3984static int decode_lookup(struct xdr_stream *xdr) 4025static int decode_lookup(struct xdr_stream *xdr)
3985{ 4026{
3986 return decode_op_hdr(xdr, OP_LOOKUP); 4027 return decode_op_hdr(xdr, OP_LOOKUP);
@@ -5267,6 +5308,19 @@ out:
5267 return status; 5308 return status;
5268} 5309}
5269 5310
5311static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
5312{
5313 struct xdr_stream xdr;
5314 struct compound_hdr hdr;
5315 int status;
5316
5317 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5318 status = decode_compound_hdr(&xdr, &hdr);
5319 if (!status)
5320 status = decode_release_lockowner(&xdr);
5321 return status;
5322}
5323
5270/* 5324/*
5271 * Decode READLINK response 5325 * Decode READLINK response
5272 */ 5326 */
@@ -5874,6 +5928,7 @@ struct rpc_procinfo nfs4_procedures[] = {
5874 PROC(GETACL, enc_getacl, dec_getacl), 5928 PROC(GETACL, enc_getacl, dec_getacl),
5875 PROC(SETACL, enc_setacl, dec_setacl), 5929 PROC(SETACL, enc_setacl, dec_setacl),
5876 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), 5930 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
5931 PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
5877#if defined(CONFIG_NFS_V4_1) 5932#if defined(CONFIG_NFS_V4_1)
5878 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), 5933 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
5879 PROC(CREATE_SESSION, enc_create_session, dec_create_session), 5934 PROC(CREATE_SESSION, enc_create_session, dec_create_session),
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 9b8299af3741..07e40c625972 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -523,6 +523,7 @@ enum {
523 NFSPROC4_CLNT_GETACL, 523 NFSPROC4_CLNT_GETACL,
524 NFSPROC4_CLNT_SETACL, 524 NFSPROC4_CLNT_SETACL,
525 NFSPROC4_CLNT_FS_LOCATIONS, 525 NFSPROC4_CLNT_FS_LOCATIONS,
526 NFSPROC4_CLNT_RELEASE_LOCKOWNER,
526 527
527 /* nfs41 */ 528 /* nfs41 */
528 NFSPROC4_CLNT_EXCHANGE_ID, 529 NFSPROC4_CLNT_EXCHANGE_ID,
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 87202c7026e3..fc461926c412 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -315,6 +315,10 @@ struct nfs_lockt_res {
315 struct nfs4_sequence_res seq_res; 315 struct nfs4_sequence_res seq_res;
316}; 316};
317 317
318struct nfs_release_lockowner_args {
319 struct nfs_lowner lock_owner;
320};
321
318struct nfs4_delegreturnargs { 322struct nfs4_delegreturnargs {
319 const struct nfs_fh *fhandle; 323 const struct nfs_fh *fhandle;
320 const nfs4_stateid *stateid; 324 const nfs4_stateid *stateid;