diff mbox

nfs: Don't return referenced delegations

Message ID 1355380636-10915-1-git-send-email-ycnian@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

ycnian@gmail.com Dec. 13, 2012, 6:37 a.m. UTC
From: Yanchuan Nian <ycnian@gmail.com>

The client returns unreferenced delegations in state management. It scans all
delegations and tests the NFS_DELEGATION_REFERENCED flag. if this flag is not
set, NFS_DELEGATION_RETURN will be set and the delegation will be returned. 
But unfortunately NFS_DELEGATION_REFERENCED is cleared after the testing, so 
delegations which are still being used will be returned in the next state
management.

Signed-off-by: Yanchuan Nian <ycnian@gmail.com>
---
 fs/nfs/delegation.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

Comments

Trond Myklebust Dec. 13, 2012, 2:34 p.m. UTC | #1
On Thu, 2012-12-13 at 14:37 +0800, ycnian@gmail.com wrote:
> From: Yanchuan Nian <ycnian@gmail.com>

> 

> The client returns unreferenced delegations in state management. It scans all

> delegations and tests the NFS_DELEGATION_REFERENCED flag. if this flag is not

> set, NFS_DELEGATION_RETURN will be set and the delegation will be returned. 

> But unfortunately NFS_DELEGATION_REFERENCED is cleared after the testing, so 

> delegations which are still being used will be returned in the next state

> management.

> 

> Signed-off-by: Yanchuan Nian <ycnian@gmail.com>

> ---

>  fs/nfs/delegation.c |    2 +-

>  1 files changed, 1 insertions(+), 1 deletions(-)

> 

> diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c

> index 81c5eec..485e8c0 100644

> --- a/fs/nfs/delegation.c

> +++ b/fs/nfs/delegation.c

> @@ -506,7 +506,7 @@ static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)

>  	struct nfs_delegation *delegation;

>  

>  	list_for_each_entry_rcu(delegation, &server->delegations, super_list) {

> -		if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))

> +		if (test_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))

>  			continue;

>  		nfs_mark_return_delegation(server, delegation);

>  	}


The clearing of the bit here is 100% intentional. This is a variant on
basic mark-and-sweep garbage collection where if the bit hasn't been set
again the next time we scan, then we assume the delegation isn't being
used.

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust@netapp.com
www.netapp.com
Trond Myklebust Dec. 14, 2012, 5:45 p.m. UTC | #2
On Fri, 2012-12-14 at 20:53 +0800, Yanchuan Nian wrote:
> 

> 

> 2012/12/13 Myklebust, Trond <Trond.Myklebust@netapp.com>

>         On Thu, 2012-12-13 at 14:37 +0800, ycnian@gmail.com wrote:

>         > From: Yanchuan Nian <ycnian@gmail.com>

>         >

>         > The client returns unreferenced delegations in state

>         management. It scans all

>         > delegations and tests the NFS_DELEGATION_REFERENCED flag. if

>         this flag is not

>         > set, NFS_DELEGATION_RETURN will be set and the delegation

>         will be returned.

>         > But unfortunately NFS_DELEGATION_REFERENCED is cleared after

>         the testing, so

>         > delegations which are still being used will be returned in

>         the next state

>         > management.

>         >

>         > Signed-off-by: Yanchuan Nian <ycnian@gmail.com>

>         > ---

>         >  fs/nfs/delegation.c |    2 +-

>         >  1 files changed, 1 insertions(+), 1 deletions(-)

>         >

>         > diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c

>         > index 81c5eec..485e8c0 100644

>         > --- a/fs/nfs/delegation.c

>         > +++ b/fs/nfs/delegation.c

>         > @@ -506,7 +506,7 @@ static void

>         nfs_mark_return_unreferenced_delegations(struct nfs_server

>         *server)

>         >       struct nfs_delegation *delegation;

>         >

>         >       list_for_each_entry_rcu(delegation,

>         &server->delegations, super_list) {

>         > -             if

>         (test_and_clear_bit(NFS_DELEGATION_REFERENCED,

>         &delegation->flags))

>         > +             if (test_bit(NFS_DELEGATION_REFERENCED,

>         &delegation->flags))

>         >                       continue;

>         >               nfs_mark_return_delegation(server,

>         delegation);

>         >       }

>         

>         

>         The clearing of the bit here is 100% intentional. This is a

>         variant on

>         basic mark-and-sweep garbage collection where if the bit

>         hasn't been set

>         again the next time we scan, then we assume the delegation

>         isn't being

>         used.

>  

> Oh, now I know. If the client gets an open delegation from the server

> without

> any operations in the following few minutes, the delegation will be

> returned.

> After that, if the client wants to read data from the server, it has

> to

> revalidate local cache first. In this situation, the client can't get

> benefit 

> from delegation. RFC 3530 says The server will recall a delegation

> if there are conflicting operations from another client. So why

> doesn't the

> client hold the delegation until receiving the recall request? Is

> there some 

> special reason? I am new to NFS and sorry to trouble you.


It's about resource management. Both the client and the server need to
keep state in memory for each delegation that is held. What we've seen
is servers running out of state if the client is too greedy about
holding onto delegations that aren't being used. In theory the server
could start recalling those delegations, but how does it know which ones
are still important to the client?

For that reason, we try to be good NFS citizens by returning delegations
that are not being used by processes. The scan is done once every lease
period (so typically once a minute). If a delegation hasn't been used in
that lease period, then it is returned.

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust@netapp.com
www.netapp.com
diff mbox

Patch

diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 81c5eec..485e8c0 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -506,7 +506,7 @@  static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
 	struct nfs_delegation *delegation;
 
 	list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
-		if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
+		if (test_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
 			continue;
 		nfs_mark_return_delegation(server, delegation);
 	}