Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3c7b7cc authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent daccbded
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
		struct nfs4_fs_locations *fs_locations, struct page *page);
		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)
#if defined(CONFIG_NFS_V4_1)
static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server)
static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server)
+28 −0
Original line number Original line Diff line number Diff line
@@ -4414,6 +4414,34 @@ out:
	return err;
	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"
#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"


int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
+2 −0
Original line number Original line Diff line number Diff line
@@ -701,6 +701,8 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
	if (list_empty(&state->lock_states))
	if (list_empty(&state->lock_states))
		clear_bit(LK_STATE_IN_USE, &state->flags);
		clear_bit(LK_STATE_IN_USE, &state->flags);
	spin_unlock(&state->state_lock);
	spin_unlock(&state->state_lock);
	if (lsp->ls_flags & NFS_LOCK_INITIALIZED)
		nfs4_release_lockowner(lsp);
	nfs4_free_lock_state(lsp);
	nfs4_free_lock_state(lsp);
}
}


+55 −0
Original line number Original line Diff line number Diff line
@@ -220,6 +220,11 @@ static int nfs4_stat_to_errno(int);
				 4)
				 4)
#define decode_locku_maxsz	(op_decode_hdr_maxsz + \
#define decode_locku_maxsz	(op_decode_hdr_maxsz + \
				 decode_stateid_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 encode_access_maxsz	(op_encode_hdr_maxsz + 1)
#define decode_access_maxsz	(op_decode_hdr_maxsz + 2)
#define decode_access_maxsz	(op_decode_hdr_maxsz + 2)
#define encode_symlink_maxsz	(op_encode_hdr_maxsz + \
#define encode_symlink_maxsz	(op_encode_hdr_maxsz + \
@@ -474,6 +479,12 @@ static int nfs4_stat_to_errno(int);
				decode_sequence_maxsz + \
				decode_sequence_maxsz + \
				decode_putfh_maxsz + \
				decode_putfh_maxsz + \
				decode_locku_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 + \
#define NFS4_enc_access_sz	(compound_encode_hdr_maxsz + \
				encode_sequence_maxsz + \
				encode_sequence_maxsz + \
				encode_putfh_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;
	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)
static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
{
{
	int len = name->len;
	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;
	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
 * Encode a READLINK request
 */
 */
@@ -3981,6 +4017,11 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
	return status;
	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)
static int decode_lookup(struct xdr_stream *xdr)
{
{
	return decode_op_hdr(xdr, OP_LOOKUP);
	return decode_op_hdr(xdr, OP_LOOKUP);
@@ -5267,6 +5308,19 @@ out:
	return status;
	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
 * Decode READLINK response
 */
 */
@@ -5874,6 +5928,7 @@ struct rpc_procinfo nfs4_procedures[] = {
  PROC(GETACL,		enc_getacl,	dec_getacl),
  PROC(GETACL,		enc_getacl,	dec_getacl),
  PROC(SETACL,		enc_setacl,	dec_setacl),
  PROC(SETACL,		enc_setacl,	dec_setacl),
  PROC(FS_LOCATIONS,	enc_fs_locations, dec_fs_locations),
  PROC(FS_LOCATIONS,	enc_fs_locations, dec_fs_locations),
  PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
#if defined(CONFIG_NFS_V4_1)
#if defined(CONFIG_NFS_V4_1)
  PROC(EXCHANGE_ID,	enc_exchange_id,	dec_exchange_id),
  PROC(EXCHANGE_ID,	enc_exchange_id,	dec_exchange_id),
  PROC(CREATE_SESSION,	enc_create_session,	dec_create_session),
  PROC(CREATE_SESSION,	enc_create_session,	dec_create_session),
+1 −0
Original line number Original line Diff line number Diff line
@@ -523,6 +523,7 @@ enum {
	NFSPROC4_CLNT_GETACL,
	NFSPROC4_CLNT_GETACL,
	NFSPROC4_CLNT_SETACL,
	NFSPROC4_CLNT_SETACL,
	NFSPROC4_CLNT_FS_LOCATIONS,
	NFSPROC4_CLNT_FS_LOCATIONS,
	NFSPROC4_CLNT_RELEASE_LOCKOWNER,


	/* nfs41 */
	/* nfs41 */
	NFSPROC4_CLNT_EXCHANGE_ID,
	NFSPROC4_CLNT_EXCHANGE_ID,
Loading