Skip to content

Commit

Permalink
NFSv4: Be less aggressive about returning delegations for open files
Browse files Browse the repository at this point in the history
Currently, if the application that holds the file open isn't doing
I/O, we may end up returning the delegation. This means that we can
no longer cache the file as aggressively, and often also that we
multiply the state that both the server and the client needs to track.

This patch adds a check for open files to the routine that scans
for delegations that are unreferenced.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Apr 5, 2013
1 parent db4f2e6 commit b757144
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
30 changes: 27 additions & 3 deletions fs/nfs/delegation.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,24 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
return err;
}

static bool nfs_delegation_need_return(struct nfs_delegation *delegation)
{
bool ret = false;

if (test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
ret = true;
if (test_and_clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags) && !ret) {
struct inode *inode;

spin_lock(&delegation->lock);
inode = delegation->inode;
if (inode && list_empty(&NFS_I(inode)->open_files))
ret = true;
spin_unlock(&delegation->lock);
}
return ret;
}

/**
* nfs_client_return_marked_delegations - return previously marked delegations
* @clp: nfs_client to process
Expand All @@ -411,8 +429,7 @@ int nfs_client_return_marked_delegations(struct nfs_client *clp)
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
list_for_each_entry_rcu(delegation, &server->delegations,
super_list) {
if (!test_and_clear_bit(NFS_DELEGATION_RETURN,
&delegation->flags))
if (!nfs_delegation_need_return(delegation))
continue;
inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL)
Expand Down Expand Up @@ -471,6 +488,13 @@ int nfs4_inode_return_delegation(struct inode *inode)
return err;
}

static void nfs_mark_return_if_closed_delegation(struct nfs_server *server,
struct nfs_delegation *delegation)
{
set_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags);
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
}

static void nfs_mark_return_delegation(struct nfs_server *server,
struct nfs_delegation *delegation)
{
Expand Down Expand Up @@ -574,7 +598,7 @@ static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
continue;
nfs_mark_return_delegation(server, delegation);
nfs_mark_return_if_closed_delegation(server, delegation);
}
}

Expand Down
1 change: 1 addition & 0 deletions fs/nfs/delegation.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct nfs_delegation {
enum {
NFS_DELEGATION_NEED_RECLAIM = 0,
NFS_DELEGATION_RETURN,
NFS_DELEGATION_RETURN_IF_CLOSED,
NFS_DELEGATION_REFERENCED,
NFS_DELEGATION_RETURNING,
};
Expand Down

0 comments on commit b757144

Please sign in to comment.