diff mbox

NFSD: Don't give out read delegations on exclusive creates

Message ID 20130521202541.GA13725@fieldses.org (mailing list archive)
State New, archived
Headers show

Commit Message

J. Bruce Fields May 21, 2013, 8:25 p.m. UTC
On Tue, May 21, 2013 at 03:23:38PM -0400, bfields wrote:
> On Wed, May 15, 2013 at 02:51:49PM -0400, Steve Dickson wrote:
> > When an exclusive create is done with the mode bits
> > set (aka open(testfile, O_CREAT | O_EXCL, 0777)) this
> 
> so implicitly O_RDONLY.  Is that common?  Maybe so, OK.
> 
> > causes a OPEN op followed by a SETATTR op. When a
> > read delegation is given in the OPEN, it causes
> > the SETATTR to delay with EAGAIN until the
> > delegation is recalled.
> > 
> > This patch caused exclusive creates to give out
> > a write delegation (which turn into no delegation)
> > which allows the SETATTR seamlessly succeed.
> 
> OK.  May as well make it apply to all creates, though, I think?
> Any create flag seems like a sign the file's likely to be modified soon,
> hence isn't a good candidate for a read delegation.

That would look like the following.

--b.

commit 3f47b6220ca6b08a7ab86baaaab87389707a3308
Author: Steve Dickson <steved@redhat.com>
Date:   Wed May 15 14:51:49 2013 -0400

    NFSD: Don't give out read delegations on exclusive creates
    
    When an exclusive create is done with the mode bits
    set (aka open(testfile, O_CREAT | O_EXCL, 0777)) this
    causes a OPEN op followed by a SETATTR op. When a
    read delegation is given in the OPEN, it causes
    the SETATTR to delay with EAGAIN until the
    delegation is recalled.
    
    This patch caused exclusive creates to give out
    a write delegation (which turn into no delegation)
    which allows the SETATTR seamlessly succeed.
    
    Signed-off-by: Steve Dickson <steved@redhat.com>
    [bfields: do this for any CREATE, not just exclusive; comment]
    Signed-off-by: J. Bruce Fields <bfields@redhat.com>

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

J. Bruce Fields May 22, 2013, 4:20 p.m. UTC | #1
On Tue, May 21, 2013 at 04:25:41PM -0400, J. Bruce Fields wrote:
> On Tue, May 21, 2013 at 03:23:38PM -0400, bfields wrote:
> > On Wed, May 15, 2013 at 02:51:49PM -0400, Steve Dickson wrote:
> > > When an exclusive create is done with the mode bits
> > > set (aka open(testfile, O_CREAT | O_EXCL, 0777)) this
> > 
> > so implicitly O_RDONLY.  Is that common?  Maybe so, OK.
> > 
> > > causes a OPEN op followed by a SETATTR op. When a
> > > read delegation is given in the OPEN, it causes
> > > the SETATTR to delay with EAGAIN until the
> > > delegation is recalled.
> > > 
> > > This patch caused exclusive creates to give out
> > > a write delegation (which turn into no delegation)
> > > which allows the SETATTR seamlessly succeed.
> > 
> > OK.  May as well make it apply to all creates, though, I think?
> > Any create flag seems like a sign the file's likely to be modified soon,
> > hence isn't a good candidate for a read delegation.
> 
> That would look like the following.

Note some 4.1 pynfs delegation tests depend on read-only create opens to
get delegations.

I've pushed out a pynfs change to

	git://linux-nfs.org/~bfields/linux.git

to make pynfs reopen if it doesn't get a delegation on the create.  Of
course there's no way pynfs can force the server to give the client a
delegation, so we just make our best effort.

For knfsd arguably the better solution would be to teach it not to break
a client's own read delegations.  But I haven't looked into how to do
that.  (And I'd need to review what the spec says in this case.  And it
might not work for 4.0 if that SETATTR isn't being done with a stateid.)

--b.

> 
> --b.
> 
> commit 3f47b6220ca6b08a7ab86baaaab87389707a3308
> Author: Steve Dickson <steved@redhat.com>
> Date:   Wed May 15 14:51:49 2013 -0400
> 
>     NFSD: Don't give out read delegations on exclusive creates
>     
>     When an exclusive create is done with the mode bits
>     set (aka open(testfile, O_CREAT | O_EXCL, 0777)) this
>     causes a OPEN op followed by a SETATTR op. When a
>     read delegation is given in the OPEN, it causes
>     the SETATTR to delay with EAGAIN until the
>     delegation is recalled.
>     
>     This patch caused exclusive creates to give out
>     a write delegation (which turn into no delegation)
>     which allows the SETATTR seamlessly succeed.
>     
>     Signed-off-by: Steve Dickson <steved@redhat.com>
>     [bfields: do this for any CREATE, not just exclusive; comment]
>     Signed-off-by: J. Bruce Fields <bfields@redhat.com>
> 
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index c4f6339..44dcea9 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -3113,8 +3113,17 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
>  				goto out;
>  			if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
>  				goto out;
> +			/*
> +			 * Also, if the file was opened for write or
> +			 * create, there's a good chance the client's
> +			 * about to write to it, resulting in an
> +			 * immediate recall (since we don't support
> +			 * write delegations):
> +			 */
>  			if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
>  				flag = NFS4_OPEN_DELEGATE_WRITE;
> +			else if (open->op_create == NFS4_OPEN_CREATE)
> +				flag = NFS4_OPEN_DELEGATE_WRITE;
>  			else
>  				flag = NFS4_OPEN_DELEGATE_READ;
>  			break;
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index c4f6339..44dcea9 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3113,8 +3113,17 @@  nfs4_open_delegation(struct net *net, struct svc_fh *fh,
 				goto out;
 			if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
 				goto out;
+			/*
+			 * Also, if the file was opened for write or
+			 * create, there's a good chance the client's
+			 * about to write to it, resulting in an
+			 * immediate recall (since we don't support
+			 * write delegations):
+			 */
 			if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
 				flag = NFS4_OPEN_DELEGATE_WRITE;
+			else if (open->op_create == NFS4_OPEN_CREATE)
+				flag = NFS4_OPEN_DELEGATE_WRITE;
 			else
 				flag = NFS4_OPEN_DELEGATE_READ;
 			break;