* [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.