Commit b757144f authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Be less aggressive about returning delegations for open files

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent db4f2e63
...@@ -389,6 +389,24 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation ...@@ -389,6 +389,24 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
return err; 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 * nfs_client_return_marked_delegations - return previously marked delegations
* @clp: nfs_client to process * @clp: nfs_client to process
...@@ -411,8 +429,7 @@ int nfs_client_return_marked_delegations(struct nfs_client *clp) ...@@ -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(server, &clp->cl_superblocks, client_link) {
list_for_each_entry_rcu(delegation, &server->delegations, list_for_each_entry_rcu(delegation, &server->delegations,
super_list) { super_list) {
if (!test_and_clear_bit(NFS_DELEGATION_RETURN, if (!nfs_delegation_need_return(delegation))
&delegation->flags))
continue; continue;
inode = nfs_delegation_grab_inode(delegation); inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL) if (inode == NULL)
...@@ -471,6 +488,13 @@ int nfs4_inode_return_delegation(struct inode *inode) ...@@ -471,6 +488,13 @@ int nfs4_inode_return_delegation(struct inode *inode)
return err; 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, static void nfs_mark_return_delegation(struct nfs_server *server,
struct nfs_delegation *delegation) struct nfs_delegation *delegation)
{ {
...@@ -574,7 +598,7 @@ static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server) ...@@ -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) { list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags)) if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
continue; continue;
nfs_mark_return_delegation(server, delegation); nfs_mark_return_if_closed_delegation(server, delegation);
} }
} }
......
...@@ -28,6 +28,7 @@ struct nfs_delegation { ...@@ -28,6 +28,7 @@ struct nfs_delegation {
enum { enum {
NFS_DELEGATION_NEED_RECLAIM = 0, NFS_DELEGATION_NEED_RECLAIM = 0,
NFS_DELEGATION_RETURN, NFS_DELEGATION_RETURN,
NFS_DELEGATION_RETURN_IF_CLOSED,
NFS_DELEGATION_REFERENCED, NFS_DELEGATION_REFERENCED,
NFS_DELEGATION_RETURNING, NFS_DELEGATION_RETURNING,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment