* [PATCH 0/5] NFSv4 Lock owner fixes
@ 2010-06-30 21:25 Trond Myklebust
2010-06-30 21:25 ` [PATCH 1/5] NFSv4: Clean up struct nfs4_state_owner Trond Myklebust
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-06-30 21:25 UTC (permalink / raw)
To: linux-nfs; +Cc: Trond Myklebust
The following patchset fixes up the NFSv4 lock stateid tracking in an
attempt to fix bugzilla entry 14501.
It also adds RELEASE_LOCKOWNER to ensure that NFSv4.0 servers don't run
out of resources when the client is doing a lot of lock/unlock operations
without closing the file.
Cheers
Trond
-------
Trond Myklebust (5):
NFSv4: Clean up struct nfs4_state_owner
NFSv4: Ensure that we track the NFSv4 lock state in read/write
requests.
NFSv4: Clean up for lockowner XDR encoding
NFSv4: Add support for the RELEASE_LOCKOWNER operation
NFSv4: Ensure the lockowners are labelled using the fl_owner and/or
fl_pid
fs/nfs/inode.c | 70 ++++++++++++++++++++++++++++++++--
fs/nfs/nfs4_fs.h | 18 +++++++--
fs/nfs/nfs4proc.c | 32 ++++++++++++++-
fs/nfs/nfs4state.c | 61 +++++++++++++++++++++---------
fs/nfs/nfs4xdr.c | 95 ++++++++++++++++++++++++++++++++++++++--------
fs/nfs/pagelist.c | 8 +++-
fs/nfs/read.c | 1 +
fs/nfs/write.c | 5 ++-
include/linux/nfs4.h | 1 +
include/linux/nfs_fs.h | 13 +++++-
include/linux/nfs_page.h | 1 +
include/linux/nfs_xdr.h | 6 +++
12 files changed, 263 insertions(+), 48 deletions(-)
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] NFSv4: Clean up struct nfs4_state_owner
2010-06-30 21:25 [PATCH 0/5] NFSv4 Lock owner fixes Trond Myklebust
@ 2010-06-30 21:25 ` Trond Myklebust
2010-06-30 21:25 ` [PATCH 2/5] NFSv4: Ensure that we track the NFSv4 lock state in read/write requests Trond Myklebust
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-06-30 21:25 UTC (permalink / raw)
To: linux-nfs; +Cc: Trond Myklebust
The 'so_delegations' list appears to be unused.
Also eliminate so_client. If we already have so_server, we can get to the
nfs_client structure.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/nfs4_fs.h | 2 --
fs/nfs/nfs4proc.c | 2 +-
fs/nfs/nfs4state.c | 14 ++++++--------
3 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index a986f13..cee8714 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -108,7 +108,6 @@ struct nfs_unique_id {
*/
struct nfs4_state_owner {
struct nfs_unique_id so_owner_id;
- struct nfs_client *so_client;
struct nfs_server *so_server;
struct rb_node so_client_node;
@@ -118,7 +117,6 @@ struct nfs4_state_owner {
atomic_t so_count;
unsigned long so_flags;
struct list_head so_states;
- struct list_head so_delegations;
struct nfs_seqid_counter so_seqid;
struct rpc_sequence so_sequence;
};
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 243d6c7..de9ff15 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1350,7 +1350,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
}
/* Update sequence id. */
data->o_arg.id = sp->so_owner_id.id;
- data->o_arg.clientid = sp->so_client->cl_clientid;
+ data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c3c6b8a..13e17e3 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -373,7 +373,6 @@ nfs4_alloc_state_owner(void)
return NULL;
spin_lock_init(&sp->so_lock);
INIT_LIST_HEAD(&sp->so_states);
- INIT_LIST_HEAD(&sp->so_delegations);
rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
sp->so_seqid.sequence = &sp->so_sequence;
spin_lock_init(&sp->so_sequence.lock);
@@ -386,7 +385,7 @@ static void
nfs4_drop_state_owner(struct nfs4_state_owner *sp)
{
if (!RB_EMPTY_NODE(&sp->so_client_node)) {
- struct nfs_client *clp = sp->so_client;
+ struct nfs_client *clp = sp->so_server->nfs_client;
spin_lock(&clp->cl_lock);
rb_erase(&sp->so_client_node, &clp->cl_state_owners);
@@ -408,7 +407,6 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
new = nfs4_alloc_state_owner();
if (new == NULL)
return NULL;
- new->so_client = clp;
new->so_server = server;
new->so_cred = cred;
spin_lock(&clp->cl_lock);
@@ -425,7 +423,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
void nfs4_put_state_owner(struct nfs4_state_owner *sp)
{
- struct nfs_client *clp = sp->so_client;
+ struct nfs_client *clp = sp->so_server->nfs_client;
struct rpc_cred *cred = sp->so_cred;
if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock))
@@ -624,7 +622,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
{
struct nfs4_lock_state *lsp;
- struct nfs_client *clp = state->owner->so_client;
+ struct nfs_client *clp = state->owner->so_server->nfs_client;
lsp = kzalloc(sizeof(*lsp), GFP_NOFS);
if (lsp == NULL)
@@ -645,7 +643,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
{
- struct nfs_client *clp = lsp->ls_state->owner->so_client;
+ struct nfs_client *clp = lsp->ls_state->owner->so_server->nfs_client;
spin_lock(&clp->cl_lock);
nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id);
@@ -1043,11 +1041,11 @@ restart:
case -NFS4ERR_BAD_STATEID:
case -NFS4ERR_RECLAIM_BAD:
case -NFS4ERR_RECLAIM_CONFLICT:
- nfs4_state_mark_reclaim_nograce(sp->so_client, state);
+ nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state);
break;
case -NFS4ERR_EXPIRED:
case -NFS4ERR_NO_GRACE:
- nfs4_state_mark_reclaim_nograce(sp->so_client, state);
+ nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state);
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT:
--
1.7.0.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/5] NFSv4: Ensure that we track the NFSv4 lock state in read/write requests.
2010-06-30 21:25 ` [PATCH 1/5] NFSv4: Clean up struct nfs4_state_owner Trond Myklebust
@ 2010-06-30 21:25 ` Trond Myklebust
2010-06-30 21:25 ` [PATCH 3/5] NFSv4: Clean up for lockowner XDR encoding Trond Myklebust
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-06-30 21:25 UTC (permalink / raw)
To: linux-nfs; +Cc: Trond Myklebust
This patch fixes bugzilla entry 14501:
https://bugzilla.kernel.org/show_bug.cgi?id=14501
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/inode.c | 70 +++++++++++++++++++++++++++++++++++++++++++--
fs/nfs/nfs4xdr.c | 8 ++--
fs/nfs/pagelist.c | 8 ++++-
fs/nfs/read.c | 1 +
fs/nfs/write.c | 5 ++-
include/linux/nfs_fs.h | 13 +++++++-
include/linux/nfs_page.h | 1 +
include/linux/nfs_xdr.h | 2 +
8 files changed, 96 insertions(+), 12 deletions(-)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 099b351..ec7a8f9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -530,6 +530,68 @@ out:
return err;
}
+static void nfs_init_lock_context(struct nfs_lock_context *l_ctx)
+{
+ atomic_set(&l_ctx->count, 1);
+ l_ctx->lockowner = current->files;
+ l_ctx->pid = current->tgid;
+ INIT_LIST_HEAD(&l_ctx->list);
+}
+
+static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx)
+{
+ struct nfs_lock_context *pos;
+
+ list_for_each_entry(pos, &ctx->lock_context.list, list) {
+ if (pos->lockowner != current->files)
+ continue;
+ if (pos->pid != current->tgid)
+ continue;
+ atomic_inc(&pos->count);
+ return pos;
+ }
+ return NULL;
+}
+
+struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx)
+{
+ struct nfs_lock_context *res, *new = NULL;
+ struct inode *inode = ctx->path.dentry->d_inode;
+
+ spin_lock(&inode->i_lock);
+ res = __nfs_find_lock_context(ctx);
+ if (res == NULL) {
+ spin_unlock(&inode->i_lock);
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
+ if (new == NULL)
+ return NULL;
+ nfs_init_lock_context(new);
+ spin_lock(&inode->i_lock);
+ res = __nfs_find_lock_context(ctx);
+ if (res == NULL) {
+ list_add_tail(&new->list, &ctx->lock_context.list);
+ new->open_context = ctx;
+ res = new;
+ new = NULL;
+ }
+ }
+ spin_unlock(&inode->i_lock);
+ kfree(new);
+ return res;
+}
+
+void nfs_put_lock_context(struct nfs_lock_context *l_ctx)
+{
+ struct nfs_open_context *ctx = l_ctx->open_context;
+ struct inode *inode = ctx->path.dentry->d_inode;
+
+ if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock))
+ return;
+ list_del(&l_ctx->list);
+ spin_unlock(&inode->i_lock);
+ kfree(l_ctx);
+}
+
/**
* nfs_close_context - Common close_context() routine NFSv2/v3
* @ctx: pointer to context
@@ -566,11 +628,11 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
path_get(&ctx->path);
ctx->cred = get_rpccred(cred);
ctx->state = NULL;
- ctx->lockowner = current->files;
ctx->flags = 0;
ctx->error = 0;
ctx->dir_cookie = 0;
- atomic_set(&ctx->count, 1);
+ nfs_init_lock_context(&ctx->lock_context);
+ ctx->lock_context.open_context = ctx;
}
return ctx;
}
@@ -578,7 +640,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
{
if (ctx != NULL)
- atomic_inc(&ctx->count);
+ atomic_inc(&ctx->lock_context.count);
return ctx;
}
@@ -586,7 +648,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
{
struct inode *inode = ctx->path.dentry->d_inode;
- if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock))
+ if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
return;
list_del(&ctx->list);
spin_unlock(&inode->i_lock);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1f7781d..873b62f 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1324,14 +1324,14 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
hdr->replen += decode_putrootfh_maxsz;
}
-static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
+static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx)
{
nfs4_stateid stateid;
__be32 *p;
p = reserve_space(xdr, NFS4_STATEID_SIZE);
if (ctx->state != NULL) {
- nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner);
+ nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner);
xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
} else
xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
@@ -1344,7 +1344,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
p = reserve_space(xdr, 4);
*p = cpu_to_be32(OP_READ);
- encode_stateid(xdr, args->context);
+ encode_stateid(xdr, args->context, args->lock_context);
p = reserve_space(xdr, 12);
p = xdr_encode_hyper(p, args->offset);
@@ -1523,7 +1523,7 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg
p = reserve_space(xdr, 4);
*p = cpu_to_be32(OP_WRITE);
- encode_stateid(xdr, args->context);
+ encode_stateid(xdr, args->context, args->lock_context);
p = reserve_space(xdr, 16);
p = xdr_encode_hyper(p, args->offset);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index a3654e5..9194902 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -79,6 +79,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
req->wb_pgbase = offset;
req->wb_bytes = count;
req->wb_context = get_nfs_open_context(ctx);
+ req->wb_lock_context = nfs_get_lock_context(ctx);
kref_init(&req->wb_kref);
return req;
}
@@ -141,11 +142,16 @@ void nfs_clear_request(struct nfs_page *req)
{
struct page *page = req->wb_page;
struct nfs_open_context *ctx = req->wb_context;
+ struct nfs_lock_context *l_ctx = req->wb_lock_context;
if (page != NULL) {
page_cache_release(page);
req->wb_page = NULL;
}
+ if (l_ctx != NULL) {
+ nfs_put_lock_context(l_ctx);
+ req->wb_lock_context = NULL;
+ }
if (ctx != NULL) {
put_nfs_open_context(ctx);
req->wb_context = NULL;
@@ -235,7 +241,7 @@ static int nfs_can_coalesce_requests(struct nfs_page *prev,
{
if (req->wb_context->cred != prev->wb_context->cred)
return 0;
- if (req->wb_context->lockowner != prev->wb_context->lockowner)
+ if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner)
return 0;
if (req->wb_context->state != prev->wb_context->state)
return 0;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 5a33a92..87adc27 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -190,6 +190,7 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
data->args.pages = data->pagevec;
data->args.count = count;
data->args.context = get_nfs_open_context(req->wb_context);
+ data->args.lock_context = req->wb_lock_context;
data->res.fattr = &data->fattr;
data->res.count = count;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 03df228..5eccea1 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -689,7 +689,9 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
req = nfs_page_find_request(page);
if (req == NULL)
return 0;
- do_flush = req->wb_page != page || req->wb_context != ctx;
+ do_flush = req->wb_page != page || req->wb_context != ctx ||
+ req->wb_lock_context->lockowner != current->files ||
+ req->wb_lock_context->pid != current->tgid;
nfs_release_request(req);
if (!do_flush)
return 0;
@@ -813,6 +815,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req,
data->args.pages = data->pagevec;
data->args.count = count;
data->args.context = get_nfs_open_context(req->wb_context);
+ data->args.lock_context = req->wb_lock_context;
data->args.stable = NFS_UNSTABLE;
if (how & FLUSH_STABLE) {
data->args.stable = NFS_DATA_SYNC;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 77c2ae5..a9d8026 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -72,13 +72,20 @@ struct nfs_access_entry {
int mask;
};
+struct nfs_lock_context {
+ atomic_t count;
+ struct list_head list;
+ struct nfs_open_context *open_context;
+ fl_owner_t lockowner;
+ pid_t pid;
+};
+
struct nfs4_state;
struct nfs_open_context {
- atomic_t count;
+ struct nfs_lock_context lock_context;
struct path path;
struct rpc_cred *cred;
struct nfs4_state *state;
- fl_owner_t lockowner;
fmode_t mode;
unsigned long flags;
@@ -353,6 +360,8 @@ extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
extern void put_nfs_open_context(struct nfs_open_context *ctx);
extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
+extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
+extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
extern u64 nfs_compat_user_ino64(u64 fileid);
extern void nfs_fattr_init(struct nfs_fattr *fattr);
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 3c60685..f8b60e7 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -39,6 +39,7 @@ struct nfs_page {
struct list_head wb_list; /* Defines state of page: */
struct page *wb_page; /* page to read in/write out */
struct nfs_open_context *wb_context; /* File state context info */
+ struct nfs_lock_context *wb_lock_context; /* lock context info */
atomic_t wb_complete; /* i/os we're waiting for */
pgoff_t wb_index; /* Offset >> PAGE_CACHE_SHIFT */
unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a319cb9..87202c7 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -334,6 +334,7 @@ struct nfs4_delegreturnres {
struct nfs_readargs {
struct nfs_fh * fh;
struct nfs_open_context *context;
+ struct nfs_lock_context *lock_context;
__u64 offset;
__u32 count;
unsigned int pgbase;
@@ -354,6 +355,7 @@ struct nfs_readres {
struct nfs_writeargs {
struct nfs_fh * fh;
struct nfs_open_context *context;
+ struct nfs_lock_context *lock_context;
__u64 offset;
__u32 count;
enum nfs3_stable_how stable;
--
1.7.0.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/5] NFSv4: Clean up for lockowner XDR encoding
2010-06-30 21:25 ` [PATCH 2/5] NFSv4: Ensure that we track the NFSv4 lock state in read/write requests Trond Myklebust
@ 2010-06-30 21:25 ` Trond Myklebust
2010-06-30 21:25 ` [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation Trond Myklebust
0 siblings, 1 reply; 8+ messages in thread
From: Trond Myklebust @ 2010-06-30 21:25 UTC (permalink / raw)
To: linux-nfs; +Cc: Trond Myklebust
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/nfs4xdr.c | 32 ++++++++++++++++++++------------
1 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 873b62f..49df05a 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -202,14 +202,17 @@ static int nfs4_stat_to_errno(int);
#define encode_link_maxsz (op_encode_hdr_maxsz + \
nfs4_name_maxsz)
#define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
+#define encode_lockowner_maxsz (7)
#define encode_lock_maxsz (op_encode_hdr_maxsz + \
7 + \
- 1 + encode_stateid_maxsz + 8)
+ 1 + encode_stateid_maxsz + 1 + \
+ encode_lockowner_maxsz)
#define decode_lock_denied_maxsz \
(8 + decode_lockowner_maxsz)
#define decode_lock_maxsz (op_decode_hdr_maxsz + \
decode_lock_denied_maxsz)
-#define encode_lockt_maxsz (op_encode_hdr_maxsz + 12)
+#define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \
+ encode_lockowner_maxsz)
#define decode_lockt_maxsz (op_decode_hdr_maxsz + \
decode_lock_denied_maxsz)
#define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \
@@ -1042,6 +1045,17 @@ static inline uint64_t nfs4_lock_length(struct file_lock *fl)
return fl->fl_end - fl->fl_start + 1;
}
+static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner)
+{
+ __be32 *p;
+
+ p = reserve_space(xdr, 28);
+ p = xdr_encode_hyper(p, lowner->clientid);
+ *p++ = cpu_to_be32(16);
+ p = xdr_encode_opaque_fixed(p, "lock id:", 8);
+ xdr_encode_hyper(p, lowner->id);
+}
+
/*
* opcode,type,reclaim,offset,length,new_lock_owner = 32
* open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
@@ -1058,14 +1072,11 @@ static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args
p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
*p = cpu_to_be32(args->new_lock_owner);
if (args->new_lock_owner){
- p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+32);
+ p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4);
*p++ = cpu_to_be32(args->open_seqid->sequence->counter);
p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE);
*p++ = cpu_to_be32(args->lock_seqid->sequence->counter);
- p = xdr_encode_hyper(p, args->lock_owner.clientid);
- *p++ = cpu_to_be32(16);
- p = xdr_encode_opaque_fixed(p, "lock id:", 8);
- xdr_encode_hyper(p, args->lock_owner.id);
+ encode_lockowner(xdr, &args->lock_owner);
}
else {
p = reserve_space(xdr, NFS4_STATEID_SIZE+4);
@@ -1080,15 +1091,12 @@ static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *ar
{
__be32 *p;
- p = reserve_space(xdr, 52);
+ p = reserve_space(xdr, 24);
*p++ = cpu_to_be32(OP_LOCKT);
*p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
p = xdr_encode_hyper(p, args->fl->fl_start);
p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
- p = xdr_encode_hyper(p, args->lock_owner.clientid);
- *p++ = cpu_to_be32(16);
- p = xdr_encode_opaque_fixed(p, "lock id:", 8);
- xdr_encode_hyper(p, args->lock_owner.id);
+ encode_lockowner(xdr, &args->lock_owner);
hdr->nops++;
hdr->replen += decode_lockt_maxsz;
}
--
1.7.0.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation
2010-06-30 21:25 ` [PATCH 3/5] NFSv4: Clean up for lockowner XDR encoding Trond Myklebust
@ 2010-06-30 21:25 ` Trond Myklebust
2010-06-30 21:25 ` [PATCH 5/5] NFSv4: Ensure the lockowners are labelled using the fl_owner and/or fl_pid Trond Myklebust
2010-07-01 16:17 ` [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation Chuck Lever
0 siblings, 2 replies; 8+ messages in thread
From: Trond Myklebust @ 2010-06-30 21:25 UTC (permalink / raw)
To: linux-nfs; +Cc: Trond Myklebust
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 | 1 +
fs/nfs/nfs4proc.c | 28 ++++++++++++++++++++++++
fs/nfs/nfs4state.c | 2 +
fs/nfs/nfs4xdr.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/nfs4.h | 1 +
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 cee8714..deaf37f 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
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)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index de9ff15..5d3e8a2 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -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,
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 13e17e3..13a4f27 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)
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);
}
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 49df05a..b3e9180 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -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),
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 9b8299a..07e40c6 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -523,6 +523,7 @@ enum {
NFSPROC4_CLNT_GETACL,
NFSPROC4_CLNT_SETACL,
NFSPROC4_CLNT_FS_LOCATIONS,
+ NFSPROC4_CLNT_RELEASE_LOCKOWNER,
/* nfs41 */
NFSPROC4_CLNT_EXCHANGE_ID,
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 87202c7..fc46192 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -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;
--
1.7.0.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] NFSv4: Ensure the lockowners are labelled using the fl_owner and/or fl_pid
2010-06-30 21:25 ` [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation Trond Myklebust
@ 2010-06-30 21:25 ` Trond Myklebust
2010-07-01 16:17 ` [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation Chuck Lever
1 sibling, 0 replies; 8+ messages in thread
From: Trond Myklebust @ 2010-06-30 21:25 UTC (permalink / raw)
To: linux-nfs; +Cc: Trond Myklebust
flock locks want to be labelled using the process pid, while posix locks
want to be labelled using the fl_owner.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
fs/nfs/nfs4_fs.h | 15 +++++++++++++--
fs/nfs/nfs4proc.c | 2 +-
fs/nfs/nfs4state.c | 45 +++++++++++++++++++++++++++++++++++----------
fs/nfs/nfs4xdr.c | 2 +-
4 files changed, 50 insertions(+), 14 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index deaf37f..311e15c 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -142,10 +142,20 @@ enum {
* LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
*/
+struct nfs4_lock_owner {
+ unsigned int lo_type;
+#define NFS4_ANY_LOCK_TYPE (0U)
+#define NFS4_FLOCK_LOCK_TYPE (1U << 0)
+#define NFS4_POSIX_LOCK_TYPE (1U << 1)
+ union {
+ fl_owner_t posix_owner;
+ pid_t flock_owner;
+ } lo_u;
+};
+
struct nfs4_lock_state {
struct list_head ls_locks; /* Other lock stateids */
struct nfs4_state * ls_state; /* Pointer to open state */
- fl_owner_t ls_owner; /* POSIX lock owner */
#define NFS_LOCK_INITIALIZED 1
int ls_flags;
struct nfs_seqid_counter ls_seqid;
@@ -153,6 +163,7 @@ struct nfs4_lock_state {
struct nfs_unique_id ls_id;
nfs4_stateid ls_stateid;
atomic_t ls_count;
+ struct nfs4_lock_owner ls_owner;
};
/* bits for nfs4_state->flags */
@@ -310,7 +321,7 @@ extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
extern void nfs41_handle_recall_slot(struct nfs_client *clp);
extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
-extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
+extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t);
extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5d3e8a2..d6413b4 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1767,7 +1767,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
/* Use that stateid */
} else if (state != NULL) {
- nfs4_copy_stateid(&arg.stateid, state, current->files);
+ nfs4_copy_stateid(&arg.stateid, state, current->files, current->tgid);
} else
memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 13a4f27..3e2f19b 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -602,12 +602,21 @@ void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode)
* that is compatible with current->files
*/
static struct nfs4_lock_state *
-__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
+__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type)
{
struct nfs4_lock_state *pos;
list_for_each_entry(pos, &state->lock_states, ls_locks) {
- if (pos->ls_owner != fl_owner)
+ if (type != NFS4_ANY_LOCK_TYPE && pos->ls_owner.lo_type != type)
continue;
+ switch (pos->ls_owner.lo_type) {
+ case NFS4_POSIX_LOCK_TYPE:
+ if (pos->ls_owner.lo_u.posix_owner != fl_owner)
+ continue;
+ break;
+ case NFS4_FLOCK_LOCK_TYPE:
+ if (pos->ls_owner.lo_u.flock_owner != fl_pid)
+ continue;
+ }
atomic_inc(&pos->ls_count);
return pos;
}
@@ -619,7 +628,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
* exists, return an uninitialized one.
*
*/
-static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
+static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type)
{
struct nfs4_lock_state *lsp;
struct nfs_client *clp = state->owner->so_server->nfs_client;
@@ -633,7 +642,18 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
lsp->ls_seqid.sequence = &lsp->ls_sequence;
atomic_set(&lsp->ls_count, 1);
lsp->ls_state = state;
- lsp->ls_owner = fl_owner;
+ lsp->ls_owner.lo_type = type;
+ switch (lsp->ls_owner.lo_type) {
+ case NFS4_FLOCK_LOCK_TYPE:
+ lsp->ls_owner.lo_u.flock_owner = fl_pid;
+ break;
+ case NFS4_POSIX_LOCK_TYPE:
+ lsp->ls_owner.lo_u.posix_owner = fl_owner;
+ break;
+ default:
+ kfree(lsp);
+ return NULL;
+ }
spin_lock(&clp->cl_lock);
nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
spin_unlock(&clp->cl_lock);
@@ -657,13 +677,13 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
* exists, return an uninitialized one.
*
*/
-static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
+static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid, unsigned int type)
{
struct nfs4_lock_state *lsp, *new = NULL;
for(;;) {
spin_lock(&state->state_lock);
- lsp = __nfs4_find_lock_state(state, owner);
+ lsp = __nfs4_find_lock_state(state, owner, pid, type);
if (lsp != NULL)
break;
if (new != NULL) {
@@ -674,7 +694,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
break;
}
spin_unlock(&state->state_lock);
- new = nfs4_alloc_lock_state(state, owner);
+ new = nfs4_alloc_lock_state(state, owner, pid, type);
if (new == NULL)
return NULL;
}
@@ -730,7 +750,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
if (fl->fl_ops != NULL)
return 0;
- lsp = nfs4_get_lock_state(state, fl->fl_owner);
+ if (fl->fl_flags & FL_POSIX)
+ lsp = nfs4_get_lock_state(state, fl->fl_owner, 0, NFS4_POSIX_LOCK_TYPE);
+ else if (fl->fl_flags & FL_FLOCK)
+ lsp = nfs4_get_lock_state(state, 0, fl->fl_pid, NFS4_FLOCK_LOCK_TYPE);
+ else
+ return -EINVAL;
if (lsp == NULL)
return -ENOMEM;
fl->fl_u.nfs4_fl.owner = lsp;
@@ -742,7 +767,7 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
* Byte-range lock aware utility to initialize the stateid of read/write
* requests.
*/
-void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
+void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid)
{
struct nfs4_lock_state *lsp;
int seq;
@@ -755,7 +780,7 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
return;
spin_lock(&state->state_lock);
- lsp = __nfs4_find_lock_state(state, fl_owner);
+ lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE);
if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
spin_unlock(&state->state_lock);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index b3e9180..07bc8f1 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1361,7 +1361,7 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context
p = reserve_space(xdr, NFS4_STATEID_SIZE);
if (ctx->state != NULL) {
- nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner);
+ nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid);
xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
} else
xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
--
1.7.0.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation
2010-06-30 21:25 ` [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation Trond Myklebust
2010-06-30 21:25 ` [PATCH 5/5] NFSv4: Ensure the lockowners are labelled using the fl_owner and/or fl_pid Trond Myklebust
@ 2010-07-01 16:17 ` Chuck Lever
2010-07-01 16:46 ` Trond Myklebust
1 sibling, 1 reply; 8+ messages in thread
From: Chuck Lever @ 2010-07-01 16:17 UTC (permalink / raw)
To: Trond Myklebust; +Cc: linux-nfs
On 06/30/10 05:25 PM, Trond Myklebust wrote:
> 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 | 1 +
> fs/nfs/nfs4proc.c | 28 ++++++++++++++++++++++++
> fs/nfs/nfs4state.c | 2 +
> fs/nfs/nfs4xdr.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/nfs4.h | 1 +
> 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 cee8714..deaf37f 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
> 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)
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index de9ff15..5d3e8a2 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -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,
> diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
> index 13e17e3..13a4f27 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)
> 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);
> }
>
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index 49df05a..b3e9180 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -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);
Nit: *p++ isn't needed here. *p will do.
> + 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),
> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> index 9b8299a..07e40c6 100644
> --- a/include/linux/nfs4.h
> +++ b/include/linux/nfs4.h
> @@ -523,6 +523,7 @@ enum {
> NFSPROC4_CLNT_GETACL,
> NFSPROC4_CLNT_SETACL,
> NFSPROC4_CLNT_FS_LOCATIONS,
> + NFSPROC4_CLNT_RELEASE_LOCKOWNER,
>
> /* nfs41 */
> NFSPROC4_CLNT_EXCHANGE_ID,
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 87202c7..fc46192 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -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;
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation
2010-07-01 16:17 ` [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation Chuck Lever
@ 2010-07-01 16:46 ` Trond Myklebust
0 siblings, 0 replies; 8+ messages in thread
From: Trond Myklebust @ 2010-07-01 16:46 UTC (permalink / raw)
To: Chuck Lever; +Cc: linux-nfs
On Thu, 2010-07-01 at 12:17 -0400, Chuck Lever wrote:
> On 06/30/10 05:25 PM, Trond Myklebust wrote:
> >
> > +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);
>
> Nit: *p++ isn't needed here. *p will do.
True. I'll fix that up.
Thanks!
Trond
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-07-01 16:46 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-30 21:25 [PATCH 0/5] NFSv4 Lock owner fixes Trond Myklebust
2010-06-30 21:25 ` [PATCH 1/5] NFSv4: Clean up struct nfs4_state_owner Trond Myklebust
2010-06-30 21:25 ` [PATCH 2/5] NFSv4: Ensure that we track the NFSv4 lock state in read/write requests Trond Myklebust
2010-06-30 21:25 ` [PATCH 3/5] NFSv4: Clean up for lockowner XDR encoding Trond Myklebust
2010-06-30 21:25 ` [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation Trond Myklebust
2010-06-30 21:25 ` [PATCH 5/5] NFSv4: Ensure the lockowners are labelled using the fl_owner and/or fl_pid Trond Myklebust
2010-07-01 16:17 ` [PATCH 4/5] NFSv4: Add support for the RELEASE_LOCKOWNER operation Chuck Lever
2010-07-01 16:46 ` Trond Myklebust
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.