Skip to content

Commit

Permalink
NFSv4.1: Ensure that we free the lock stateid on the server
Browse files Browse the repository at this point in the history
This ensures that the server doesn't need to keep huge numbers of
lock stateids waiting around for the final CLOSE.
See section 8.2.4 in RFC5661.

Signed-off-by: Trond Myklebust <[email protected]>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed May 6, 2013
1 parent 7c1d5fa commit c8b2d0b
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
3 changes: 2 additions & 1 deletion fs/nfs/nfs4_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ struct nfs4_minor_version_ops {
const nfs4_stateid *);
int (*find_root_sec)(struct nfs_server *, struct nfs_fh *,
struct nfs_fsinfo *);
int (*free_lock_state)(struct nfs_server *,
struct nfs4_lock_state *);
const struct nfs4_state_recovery_ops *reboot_recovery_ops;
const struct nfs4_state_recovery_ops *nograce_recovery_ops;
const struct nfs4_state_maintenance_ops *state_renewal_ops;
Expand Down Expand Up @@ -234,7 +236,6 @@ extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struc
extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *,
struct nfs_fh *, struct nfs_fattr *);
extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
extern int nfs4_release_lockowner(struct nfs4_lock_state *);
extern const struct xattr_handler *nfs4_xattr_handlers[];
extern int nfs4_set_rw_stateid(nfs4_stateid *stateid,
const struct nfs_open_context *ctx,
Expand Down
17 changes: 15 additions & 2 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5238,9 +5238,8 @@ static const struct rpc_call_ops nfs4_release_lockowner_ops = {
.rpc_release = nfs4_release_lockowner_release,
};

int nfs4_release_lockowner(struct nfs4_lock_state *lsp)
static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
{
struct nfs_server *server = lsp->ls_state->owner->so_server;
struct nfs_release_lockowner_data *data;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER],
Expand Down Expand Up @@ -6879,6 +6878,18 @@ static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid)
return ret;
}

static int nfs41_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp)
{
struct rpc_task *task;

task = _nfs41_free_stateid(server, &lsp->ls_stateid, false);
nfs4_free_lock_state(server, lsp);
if (IS_ERR(task))
return PTR_ERR(task);
rpc_put_task(task);
return 0;
}

static bool nfs41_match_stateid(const nfs4_stateid *s1,
const nfs4_stateid *s2)
{
Expand Down Expand Up @@ -6968,6 +6979,7 @@ static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
.call_sync = _nfs4_call_sync,
.match_stateid = nfs4_match_stateid,
.find_root_sec = nfs4_find_root_sec,
.free_lock_state = nfs4_release_lockowner,
.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
.state_renewal_ops = &nfs40_state_renewal_ops,
Expand All @@ -6985,6 +6997,7 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
.call_sync = nfs4_call_sync_sequence,
.match_stateid = nfs41_match_stateid,
.find_root_sec = nfs41_find_root_sec,
.free_lock_state = nfs41_free_lock_state,
.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
.state_renewal_ops = &nfs41_state_renewal_ops,
Expand Down
11 changes: 7 additions & 4 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
*/
void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
{
struct nfs_server *server;
struct nfs4_state *state;

if (lsp == NULL)
Expand All @@ -932,11 +933,13 @@ 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);
server = state->owner->so_server;
if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
if (nfs4_release_lockowner(lsp) == 0)
return;
}
nfs4_free_lock_state(lsp->ls_state->owner->so_server, lsp);
struct nfs_client *clp = server->nfs_client;

clp->cl_mvops->free_lock_state(server, lsp);
} else
nfs4_free_lock_state(server, lsp);
}

static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
Expand Down

0 comments on commit c8b2d0b

Please sign in to comment.