[PATCHES] Issue fsync for SMB2 FLUSH asynchronously

Christof Schmitt cs at samba.org
Wed Nov 11 22:32:59 UTC 2015


On Wed, Nov 11, 2015 at 01:27:50PM -0800, Jeremy Allison wrote:
> On Wed, Nov 11, 2015 at 01:36:32PM -0700, Christof Schmitt wrote:
> > 
> > From 4762b67740770f1ba43e78349c8d1f48857b55dd Mon Sep 17 00:00:00 2001
> > From: Christof Schmitt <cs at samba.org>
> > Date: Wed, 11 Nov 2015 13:31:15 -0700
> > Subject: [PATCH 2/2] smbd: Issue fsync for SMB2 FLUSH asynchronously
> > 
> > SMB2 FLUSH mainly calls fsync and there is already code in place to
> > handle fsync asynchronously, so use the asynchronous code path for SMB2
> > FLUSH. This avoids a SMB2 FLUSH stalling other requests processing.
> 
> This code isn't quite right I'm afraid.
> 
> It would end up calling tevent_req_done()
> twice, once in at the end of smbd_smb2_flush_send()
> and then again in smbd_smb2_flush_done() when
> when the subreq completes.

Yes, sorry. I meant to handle this correctly, but then forgot again.

> 
> The correct thing to do in the:
> 
>      if (lp_strict_sync(SNUM(smbreq->conn))) {
> 
> block is to add a cancellation function
> to the outstanding req using tevent_req_set_cancel_fn()
> (see smbd_smb2_write_send() for details) to allow
> the client to send a cancel on this outstanding request,
> then add the req to the pending aio queue
> using aio_add_req_to_fsp() (see smbd_smb2_setinfo_send()
> for details) to ensure that if the file gets
> closed whilst this flush request is outstanding
> then when the flush completes it doesn't
> crash smbd.
> 
> I'll code this up for you if you like as
> it is a little trickier than it looks.

Looking at smbd_smb2_write_cancel this does not seem to be too
difficult. Let me try to add this.

> Thanks a *LOT* for doing this though !
> It's something we've needed for a while.

Agreed, it is needed. When looking through the code, i started wondering
why this has not been done before, given that there is already an async
FSYNC available.

Christof

> 
> Jeremy.
> 
> 
> 
> > Signed-off-by: Christof Schmitt <cs at samba.org>
> > ---
> >  source3/smbd/smb2_flush.c |   39 +++++++++++++++++++++++++++++++--------
> >  1 files changed, 31 insertions(+), 8 deletions(-)
> > 
> > diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c
> > index 04a8710..7af6aab 100644
> > --- a/source3/smbd/smb2_flush.c
> > +++ b/source3/smbd/smb2_flush.c
> > @@ -110,14 +110,15 @@ struct smbd_smb2_flush_state {
> >  	struct smbd_smb2_request *smb2req;
> >  };
> >  
> > +static void smbd_smb2_flush_done(struct tevent_req *subreq);
> > +
> >  static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx,
> >  					       struct tevent_context *ev,
> >  					       struct smbd_smb2_request *smb2req,
> >  					       struct files_struct *fsp)
> >  {
> > -	struct tevent_req *req;
> > +	struct tevent_req *req, *subreq;
> >  	struct smbd_smb2_flush_state *state;
> > -	NTSTATUS status;
> >  	struct smb_request *smbreq;
> >  
> >  	req = tevent_req_create(mem_ctx, &state,
> > @@ -145,18 +146,40 @@ static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx,
> >  		return tevent_req_post(req, ev);
> >  	}
> >  
> > -	status = sync_file(smbreq->conn, fsp, true);
> > -	if (!NT_STATUS_IS_OK(status)) {
> > -		DEBUG(5,("smbd_smb2_flush: sync_file for %s returned %s\n",
> > -			 fsp_str_dbg(fsp), nt_errstr(status)));
> > -		tevent_req_nterror(req, status);
> > -		return tevent_req_post(req, ev);
> > +	if (lp_strict_sync(SNUM(smbreq->conn))) {
> > +		int ret = flush_write_cache(fsp, SAMBA_SYNC_FLUSH);
> > +		if (ret == -1) {
> > +			tevent_req_nterror(req,  map_nt_error_from_unix(errno));
> > +			return tevent_req_post(req, ev);
> > +		}
> > +
> > +		subreq = SMB_VFS_FSYNC_SEND(state, ev, fsp);
> > +		if (tevent_req_nomem(subreq, req)) {
> > +			return tevent_req_post(req, ev);
> > +		}
> > +
> > +		tevent_req_set_callback(subreq, smbd_smb2_flush_done, req);
> >  	}
> >  
> >  	tevent_req_done(req);
> >  	return tevent_req_post(req, ev);
> >  }
> >  
> > +static void smbd_smb2_flush_done(struct tevent_req *subreq)
> > +{
> > +	struct tevent_req *req = tevent_req_callback_data(
> > +		subreq, struct tevent_req);
> > +	int ret, err;
> > +
> > +	ret = SMB_VFS_FSYNC_RECV(subreq, &err);
> > +	TALLOC_FREE(subreq);
> > +	if (ret == -1) {
> > +		tevent_req_error(req, err);
> > +		return;
> > +	}
> > +	tevent_req_done(req);
> > +}
> > +
> >  static NTSTATUS smbd_smb2_flush_recv(struct tevent_req *req)
> >  {
> >  	NTSTATUS status;
> > -- 
> > 1.7.1
> > 



More information about the samba-technical mailing list