diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-01 12:49:01 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-30 14:46:10 -0400 |
commit | d3c7b7ccc199ee564177ee914c04771d6bc00295 (patch) | |
tree | ed5bda669f6ede2ac454bf853577e3c3f818642b | |
parent | daccbded7f153ec84a3baf3136052e41d0eab555 (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.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 28 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 55 | ||||
-rw-r--r-- | include/linux/nfs4.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 4 |
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 | |||
236 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); | 236 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
237 | extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | 237 | extern 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); |
239 | extern 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) |
241 | static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) | 242 | static 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 | ||
4417 | static void nfs4_release_lockowner_release(void *calldata) | ||
4418 | { | ||
4419 | kfree(calldata); | ||
4420 | } | ||
4421 | |||
4422 | const struct rpc_call_ops nfs4_release_lockowner_ops = { | ||
4423 | .rpc_release = nfs4_release_lockowner_release, | ||
4424 | }; | ||
4425 | |||
4426 | void 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 | ||
4419 | int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, | 4447 | int 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 | ||
1130 | static 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 | |||
1119 | static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) | 1141 | static 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 | ||
2081 | static 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 | ||
4020 | static int decode_release_lockowner(struct xdr_stream *xdr) | ||
4021 | { | ||
4022 | return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); | ||
4023 | } | ||
4024 | |||
3984 | static int decode_lookup(struct xdr_stream *xdr) | 4025 | static 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 | ||
5311 | static 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 | ||
318 | struct nfs_release_lockowner_args { | ||
319 | struct nfs_lowner lock_owner; | ||
320 | }; | ||
321 | |||
318 | struct nfs4_delegreturnargs { | 322 | struct nfs4_delegreturnargs { |
319 | const struct nfs_fh *fhandle; | 323 | const struct nfs_fh *fhandle; |
320 | const nfs4_stateid *stateid; | 324 | const nfs4_stateid *stateid; |