]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
NFSv4: Add support for the RELEASE_LOCKOWNER operation
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 1 Jul 2010 16:49:01 +0000 (12:49 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 30 Jul 2010 18:46:10 +0000 (14:46 -0400)
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>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
include/linux/nfs4.h
include/linux/nfs_xdr.h

index cee871471e8dd758039ddca2993623eedb3f3f76..deaf37f5a7a962daa5235fbc4adaabcdafb90d26 100644 (file)
@@ -236,6 +236,7 @@ extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nam
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
                struct nfs4_fs_locations *fs_locations, struct page *page);
+extern void nfs4_release_lockowner(const struct nfs4_lock_state *);
 
 #if defined(CONFIG_NFS_V4_1)
 static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server)
index de9ff1505a24d7e3cddc15b0b2773555bca0ae12..5d3e8a2db99fe1cdec5101348bcc0bf133325593 100644 (file)
@@ -4414,6 +4414,34 @@ out:
        return err;
 }
 
+static void nfs4_release_lockowner_release(void *calldata)
+{
+       kfree(calldata);
+}
+
+const struct rpc_call_ops nfs4_release_lockowner_ops = {
+       .rpc_release = nfs4_release_lockowner_release,
+};
+
+void nfs4_release_lockowner(const struct nfs4_lock_state *lsp)
+{
+       struct nfs_server *server = lsp->ls_state->owner->so_server;
+       struct nfs_release_lockowner_args *args;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER],
+       };
+
+       if (server->nfs_client->cl_mvops->minor_version != 0)
+               return;
+       args = kmalloc(sizeof(*args), GFP_NOFS);
+       if (!args)
+               return;
+       args->lock_owner.clientid = server->nfs_client->cl_clientid;
+       args->lock_owner.id = lsp->ls_id.id;
+       msg.rpc_argp = args;
+       rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, args);
+}
+
 #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
 
 int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
index 13e17e32e3e42798c80a3b3be7c22e78b1e7df99..13a4f27e72719f7bdf438ce2b7fc6e95bb2c5860 100644 (file)
@@ -701,6 +701,8 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
        if (list_empty(&state->lock_states))
                clear_bit(LK_STATE_IN_USE, &state->flags);
        spin_unlock(&state->state_lock);
+       if (lsp->ls_flags & NFS_LOCK_INITIALIZED)
+               nfs4_release_lockowner(lsp);
        nfs4_free_lock_state(lsp);
 }
 
index 49df05afdc646583e568ad6162ba388c62242d4e..15185c2abd1102de7f010b0208c86adede45fac3 100644 (file)
@@ -220,6 +220,11 @@ static int nfs4_stat_to_errno(int);
                                 4)
 #define decode_locku_maxsz     (op_decode_hdr_maxsz + \
                                 decode_stateid_maxsz)
+#define encode_release_lockowner_maxsz \
+                               (op_encode_hdr_maxsz + \
+                                encode_lockowner_maxsz)
+#define decode_release_lockowner_maxsz \
+                               (op_decode_hdr_maxsz)
 #define encode_access_maxsz    (op_encode_hdr_maxsz + 1)
 #define decode_access_maxsz    (op_decode_hdr_maxsz + 2)
 #define encode_symlink_maxsz   (op_encode_hdr_maxsz + \
@@ -474,6 +479,12 @@ static int nfs4_stat_to_errno(int);
                                decode_sequence_maxsz + \
                                decode_putfh_maxsz + \
                                decode_locku_maxsz)
+#define NFS4_enc_release_lockowner_sz \
+                               (compound_encode_hdr_maxsz + \
+                                encode_lockowner_maxsz)
+#define NFS4_dec_release_lockowner_sz \
+                               (compound_decode_hdr_maxsz + \
+                                decode_lockowner_maxsz)
 #define NFS4_enc_access_sz     (compound_encode_hdr_maxsz + \
                                encode_sequence_maxsz + \
                                encode_putfh_maxsz + \
@@ -1116,6 +1127,17 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar
        hdr->replen += decode_locku_maxsz;
 }
 
+static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr)
+{
+       __be32 *p;
+
+       p = reserve_space(xdr, 4);
+       *p = cpu_to_be32(OP_RELEASE_LOCKOWNER);
+       encode_lockowner(xdr, lowner);
+       hdr->nops++;
+       hdr->replen += decode_release_lockowner_maxsz;
+}
+
 static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
 {
        int len = name->len;
@@ -2056,6 +2078,20 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_
        return 0;
 }
 
+static int nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, __be32 *p, struct nfs_release_lockowner_args *args)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr = {
+               .minorversion = 0,
+       };
+
+       xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+       encode_compound_hdr(&xdr, req, &hdr);
+       encode_release_lockowner(&xdr, &args->lock_owner, &hdr);
+       encode_nops(&hdr);
+       return 0;
+}
+
 /*
  * Encode a READLINK request
  */
@@ -3981,6 +4017,11 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
        return status;
 }
 
+static int decode_release_lockowner(struct xdr_stream *xdr)
+{
+       return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER);
+}
+
 static int decode_lookup(struct xdr_stream *xdr)
 {
        return decode_op_hdr(xdr, OP_LOOKUP);
@@ -5267,6 +5308,19 @@ out:
        return status;
 }
 
+static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr;
+       int status;
+
+       xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+       status = decode_compound_hdr(&xdr, &hdr);
+       if (!status)
+               status = decode_release_lockowner(&xdr);
+       return status;
+}
+
 /*
  * Decode READLINK response
  */
@@ -5874,6 +5928,7 @@ struct rpc_procinfo       nfs4_procedures[] = {
   PROC(GETACL,         enc_getacl,     dec_getacl),
   PROC(SETACL,         enc_setacl,     dec_setacl),
   PROC(FS_LOCATIONS,   enc_fs_locations, dec_fs_locations),
+  PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
 #if defined(CONFIG_NFS_V4_1)
   PROC(EXCHANGE_ID,    enc_exchange_id,        dec_exchange_id),
   PROC(CREATE_SESSION, enc_create_session,     dec_create_session),
index 9b8299af3741be370af6a3443dc5b73d3ba05b11..07e40c62597211c58d50ce4d61fca14a8021c34f 100644 (file)
@@ -523,6 +523,7 @@ enum {
        NFSPROC4_CLNT_GETACL,
        NFSPROC4_CLNT_SETACL,
        NFSPROC4_CLNT_FS_LOCATIONS,
+       NFSPROC4_CLNT_RELEASE_LOCKOWNER,
 
        /* nfs41 */
        NFSPROC4_CLNT_EXCHANGE_ID,
index 87202c7026e3436f7fae6c63d5c60bca5c1ccd46..fc461926c412e58d91d717aa7a9cbd48d407ea01 100644 (file)
@@ -315,6 +315,10 @@ struct nfs_lockt_res {
        struct nfs4_sequence_res        seq_res;
 };
 
+struct nfs_release_lockowner_args {
+       struct nfs_lowner       lock_owner;
+};
+
 struct nfs4_delegreturnargs {
        const struct nfs_fh *fhandle;
        const nfs4_stateid *stateid;