The branch, master has been updated via 31cd1fb s3:smbd/aio: handle_aio_completed() should do nothing if aio_ex->fsp is NULL via 21eb145 s3:smbd/aio: pass ECANCELED to the smb2 aio handlers via 483b79c s3:smb2_read: make it possible to cancel aio reads via 3fbf322 s3:smb2_write: make it possible to cancel aio writes via 2802be7 s3:smbd/aio: add cancel_smb2_aio() via 0cd6769 s3:smb2_ioctl: STATUS_PENDING is defered by 1 millisecond for SMB2_IOCTL via 05246ae s3:smb2_create: defer STATUS_PENDING for 2 seconds as before via 88dd90d s3:smb2_server: pass explicit defer_times to smbd_smb2_request_pending_queue() via 693cb77 s3:smb2_server: always send STATUS_PENDING responses, but delayed by 0.5 milliseconds from 10b285c s3-winbind: Don't fail on users without a uid.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 31cd1fbd2b1c2d1635662688e979bb5baa992855 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Nov 14 09:54:05 2011 +0100 s3:smbd/aio: handle_aio_completed() should do nothing if aio_ex->fsp is NULL metze Autobuild-User: Stefan Metzmacher <me...@samba.org> Autobuild-Date: Tue Nov 15 18:47:55 CET 2011 on sn-devel-104 commit 21eb1450cc2541e23dedf1a0dec24e3313ab8739 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Nov 14 09:53:25 2011 +0100 s3:smbd/aio: pass ECANCELED to the smb2 aio handlers metze commit 483b79cfc4af4dd48089b12b279d174f54132e9d Author: Stefan Metzmacher <me...@samba.org> Date: Mon Nov 14 09:33:22 2011 +0100 s3:smb2_read: make it possible to cancel aio reads metze commit 3fbf32213a9523ecab4bc201018d94f38b561b0b Author: Stefan Metzmacher <me...@samba.org> Date: Mon Nov 14 09:33:22 2011 +0100 s3:smb2_write: make it possible to cancel aio writes metze commit 2802be75e38d5ae64ad5ec36e46d0799c77eec30 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Nov 14 09:52:47 2011 +0100 s3:smbd/aio: add cancel_smb2_aio() metze commit 0cd67698ca69d82936da29658103ce449d797c25 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Nov 14 15:29:37 2011 +0100 s3:smb2_ioctl: STATUS_PENDING is defered by 1 millisecond for SMB2_IOCTL metze commit 05246ae6238483eff759897d8a6aa9be7f49529f Author: Stefan Metzmacher <me...@samba.org> Date: Mon Nov 14 15:50:47 2011 +0100 s3:smb2_create: defer STATUS_PENDING for 2 seconds as before metze commit 88dd90d9288e49c33f4e8d528bf109a40fc997d8 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Nov 14 15:42:55 2011 +0100 s3:smb2_server: pass explicit defer_times to smbd_smb2_request_pending_queue() metze commit 693cb77b2fdb96205ab83bb2c22b67fe91de61b0 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Nov 9 11:47:33 2011 +0100 s3:smb2_server: always send STATUS_PENDING responses, but delayed by 0.5 milliseconds In future we'll pass the delay from the caller. metze ----------------------------------------------------------------------- Summary of changes: source3/smbd/aio.c | 48 +++++++++- source3/smbd/globals.h | 5 +- source3/smbd/proto.h | 1 + source3/smbd/smb2_break.c | 2 +- source3/smbd/smb2_create.c | 42 ++------ source3/smbd/smb2_find.c | 2 +- source3/smbd/smb2_flush.c | 2 +- source3/smbd/smb2_getinfo.c | 2 +- source3/smbd/smb2_ioctl.c | 2 +- source3/smbd/smb2_lock.c | 2 +- source3/smbd/smb2_notify.c | 2 +- source3/smbd/smb2_read.c | 25 +++-- source3/smbd/smb2_server.c | 227 +++++++++++++++++++++++-------------------- source3/smbd/smb2_setinfo.c | 2 +- source3/smbd/smb2_write.c | 25 +++-- 15 files changed, 223 insertions(+), 166 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 98a35ed..d367826 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -49,6 +49,7 @@ struct aio_extra { DATA_BLOB outbuf; struct lock_struct lock; bool write_through; + bool pass_cancel; int (*handle_completion)(struct aio_extra *ex, int errcode); }; @@ -380,6 +381,37 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn, return NT_STATUS_OK; } +bool cancel_smb2_aio(struct smb_request *smbreq) +{ + struct smbd_smb2_request *smb2req = smbreq->smb2req; + struct aio_extra *aio_ex = NULL; + int ret; + + if (smbreq) { + smb2req = smbreq->smb2req; + } + + if (smb2req) { + aio_ex = talloc_get_type(smbreq->async_priv, + struct aio_extra); + } + + if (aio_ex == NULL) { + return false; + } + + if (aio_ex->fsp == NULL) { + return false; + } + + ret = SMB_VFS_AIO_CANCEL(aio_ex->fsp, &aio_ex->acb); + if (ret != AIO_CANCELED) { + return false; + } + + return true; +} + /**************************************************************************** Set up an aio request from a SMB2 read call. *****************************************************************************/ @@ -440,6 +472,7 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn, return NT_STATUS_NO_MEMORY; } aio_ex->handle_completion = handle_aio_smb2_read_complete; + aio_ex->pass_cancel = true; init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid, (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK, @@ -476,6 +509,7 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn, /* We don't need talloc_move here as both aio_ex and * smbreq are children of smbreq->smb2req. */ aio_ex->smbreq = smbreq; + smbreq->async_priv = aio_ex; DEBUG(10,("smb2: scheduled aio_read for file %s, " "offset %.0f, len = %u (mid = %u)\n", @@ -540,6 +574,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn, aio_ex->handle_completion = handle_aio_smb2_write_complete; aio_ex->write_through = write_through; + aio_ex->pass_cancel = true; init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid, in_offset, (uint64_t)in_data.length, WRITE_LOCK, @@ -576,6 +611,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn, /* We don't need talloc_move here as both aio_ex and * smbreq are children of smbreq->smb2req. */ aio_ex->smbreq = smbreq; + smbreq->async_priv = aio_ex; /* This should actually be improved to span the write. */ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE); @@ -835,6 +871,11 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) return false; } + if (!aio_ex->fsp) { + DEBUG(3, ("handle_aio_completed: aio_ex->fsp == NULL\n")); + return false; + } + fsp = aio_ex->fsp; /* Ensure the operation has really completed. */ @@ -850,7 +891,7 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) /* Unlock now we're done. */ SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock); - if (err == ECANCELED) { + if (!aio_ex->pass_cancel && err == ECANCELED) { /* If error is ECANCELED then don't return anything to the * client. */ DEBUG(10,( "handle_aio_completed: operation mid %llu" @@ -1039,6 +1080,11 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn, return NT_STATUS_RETRY; } +bool cancel_smb2_aio(struct smb_request *smbreq) +{ + return false; +} + NTSTATUS schedule_smb2_aio_read(connection_struct *conn, struct smb_request *smbreq, files_struct *fsp, diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 2e94b55..a02988a 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -259,7 +259,8 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn, uint8_t oplock_level); NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, - struct tevent_req *subreq); + struct tevent_req *subreq, + uint32_t defer_time); struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req); void remove_smb2_chained_fsp(files_struct *fsp); @@ -347,7 +348,7 @@ struct smbd_smb2_request { int current_idx; bool do_signing; - bool async; + struct tevent_timer *async_te; bool cancelled; bool compound_related; diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 0a68a6c..fe90766 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -86,6 +86,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn, uint64_t in_offset, DATA_BLOB in_data, bool write_through); +bool cancel_smb2_aio(struct smb_request *smbreq); int wait_for_aio_completion(files_struct *fsp); void cancel_aio_by_fsp(files_struct *fsp); void smbd_aio_complete_aio_ex(struct aio_extra *aio_ex); diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c index ce583ac..9899d92 100644 --- a/source3/smbd/smb2_break.c +++ b/source3/smbd/smb2_break.c @@ -78,7 +78,7 @@ NTSTATUS smbd_smb2_request_process_break(struct smbd_smb2_request *req) } tevent_req_set_callback(subreq, smbd_smb2_request_oplock_break_done, req); - return smbd_smb2_request_pending_queue(req, subreq); + return smbd_smb2_request_pending_queue(req, subreq, 500); } static void smbd_smb2_request_oplock_break_done(struct tevent_req *subreq) diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 29696dc..6d7d4ac 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -244,7 +244,13 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req) } tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req); - return smbd_smb2_request_pending_queue(smb2req, tsubreq); + /* + * For now we keep the logic that we do not send STATUS_PENDING + * for sharing violations, so we just wait 2 seconds. + * + * TODO: we need more tests for this. + */ + return smbd_smb2_request_pending_queue(smb2req, tsubreq, 2000000); } static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req) @@ -437,7 +443,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, } - if (!smb2req->async) { + if (smb2req->subreq == NULL) { /* New create call. */ req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_create_state); @@ -445,7 +451,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, return NULL; } state->smb2req = smb2req; - smb2req->subreq = req; /* So we can find this when going async. */ smb1req = smbd_smb2_fake_smb_request(smb2req); if (tevent_req_nomem(smb1req, req)) { @@ -892,7 +897,7 @@ bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req, if (!smb2req) { return false; } - if (!smb2req->async) { + if (smb2req->subreq == NULL) { return false; } req = smb2req->subreq; @@ -1201,35 +1206,6 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req, return false; } -#if 1 - /* Boo - turns out this isn't what W2K8R2 - does. It actually sends the STATUS_PENDING - message followed by the STATUS_SHARING_VIOLATION - message. Surely this means that all open - calls (even on directories) will potentially - fail in a chain.... ? And I've seen directory - opens as the start of a chain. JRA. - - Update: 19th May 2010. Talking with Microsoft - engineers at the plugfest this is a bug in - Windows. Re-enable this code. - */ - /* - * More subtlety. To match W2K8R2 don't - * send a "gone async" message if it's simply - * a STATUS_SHARING_VIOLATION (short) wait, not - * an oplock break wait. We do this by prematurely - * setting smb2req->async flag. - */ - if (timeout.tv_sec < 2) { - DEBUG(10,("push_deferred_open_message_smb2: " - "short timer wait (usec = %u). " - "Don't send async message.\n", - (unsigned int)timeout.tv_usec )); - smb2req->async = true; - } -#endif - /* Re-schedule us to retry on timer expiry. */ end_time = timeval_sum(&request_time, &timeout); diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c index 6369e7f..9b1179f 100644 --- a/source3/smbd/smb2_find.c +++ b/source3/smbd/smb2_find.c @@ -135,7 +135,7 @@ NTSTATUS smbd_smb2_request_process_find(struct smbd_smb2_request *req) } tevent_req_set_callback(subreq, smbd_smb2_request_find_done, req); - return smbd_smb2_request_pending_queue(req, subreq); + return smbd_smb2_request_pending_queue(req, subreq, 500); } static void smbd_smb2_request_find_done(struct tevent_req *subreq) diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c index 5f3c42a..3464c58 100644 --- a/source3/smbd/smb2_flush.c +++ b/source3/smbd/smb2_flush.c @@ -64,7 +64,7 @@ NTSTATUS smbd_smb2_request_process_flush(struct smbd_smb2_request *req) } tevent_req_set_callback(subreq, smbd_smb2_request_flush_done, req); - return smbd_smb2_request_pending_queue(req, subreq); + return smbd_smb2_request_pending_queue(req, subreq, 500); } static void smbd_smb2_request_flush_done(struct tevent_req *subreq) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index c5d2d62..81d781a 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -118,7 +118,7 @@ NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req) } tevent_req_set_callback(subreq, smbd_smb2_request_getinfo_done, req); - return smbd_smb2_request_pending_queue(req, subreq); + return smbd_smb2_request_pending_queue(req, subreq, 500); } static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq) diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c index 5a766e1..b7b4592 100644 --- a/source3/smbd/smb2_ioctl.c +++ b/source3/smbd/smb2_ioctl.c @@ -110,7 +110,7 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req) } tevent_req_set_callback(subreq, smbd_smb2_request_ioctl_done, req); - return smbd_smb2_request_pending_queue(req, subreq); + return smbd_smb2_request_pending_queue(req, subreq, 1000); } static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index ed1d688..4f88bb8 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -133,7 +133,7 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req) } tevent_req_set_callback(subreq, smbd_smb2_request_lock_done, req); - return smbd_smb2_request_pending_queue(req, subreq); + return smbd_smb2_request_pending_queue(req, subreq, 500); } static void smbd_smb2_request_lock_done(struct tevent_req *subreq) diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index 49c6a54..5375e21 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -95,7 +95,7 @@ NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req) } tevent_req_set_callback(subreq, smbd_smb2_request_notify_done, req); - return smbd_smb2_request_pending_queue(req, subreq); + return smbd_smb2_request_pending_queue(req, subreq, 500); } static void smbd_smb2_request_notify_done(struct tevent_req *subreq) diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index 405e82d..0862209 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -100,7 +100,7 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req) } tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req); - return smbd_smb2_request_pending_queue(req, subreq); + return smbd_smb2_request_pending_queue(req, subreq, 500); } static void smbd_smb2_request_read_done(struct tevent_req *subreq) @@ -169,6 +169,7 @@ static void smbd_smb2_request_read_done(struct tevent_req *subreq) struct smbd_smb2_read_state { struct smbd_smb2_request *smb2req; + struct smb_request *smbreq; files_struct *fsp; uint64_t in_file_id_volatile; uint32_t in_length; @@ -364,6 +365,17 @@ NTSTATUS smb2_read_complete(struct tevent_req *req, ssize_t nread, int err) return NT_STATUS_OK; } +static bool smbd_smb2_read_cancel(struct tevent_req *req) +{ + struct smbd_smb2_read_state *state = + tevent_req_data(req, + struct smbd_smb2_read_state); + + state->smb2req->cancelled = true; + + return cancel_smb2_aio(state->smbreq); +} + static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_smb2_request *smb2req, @@ -403,6 +415,7 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, if (tevent_req_nomem(smbreq, req)) { return tevent_req_post(req, ev); } + state->smbreq = smbreq; fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile); if (fsp == NULL) { @@ -466,14 +479,10 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, if (NT_STATUS_IS_OK(status)) { /* - * Doing an async read. Don't - * send a "gone async" message - * as we expect this to be less - * than the client timeout period. - * JRA. FIXME for offline files.. - * FIXME. Add cancel code.. + * Doing an async read, allow this + * request to be canceled */ - smb2req->async = true; + tevent_req_set_cancel_fn(req, smbd_smb2_read_cancel); return req; } diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 33e95ad..dbb0089 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -711,15 +711,6 @@ static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *re newreq->session = req->session; newreq->do_signing = req->do_signing; newreq->current_idx = req->current_idx; - newreq->async = false; - newreq->cancelled = false; - /* Note we are leaving: - ->tcon - ->smb1req - ->compat_chain_fsp - uninitialized as NULL here as - they're not used in the interim - response code. JRA. */ outvec = talloc_zero_array(newreq, struct iovec, count); if (!outvec) { @@ -844,19 +835,20 @@ static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq) TALLOC_FREE(state); } +static void smbd_smb2_request_pending_timer(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data); + NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, - struct tevent_req *subreq) + struct tevent_req *subreq, + uint32_t defer_time) { NTSTATUS status; - struct smbd_smb2_request_pending_state *state = NULL; int i = req->current_idx; - uint8_t *reqhdr = NULL; - uint8_t *hdr = NULL; - uint8_t *body = NULL; - uint32_t flags = 0; - uint64_t message_id = 0; - uint64_t async_id = 0; - struct iovec *outvec = NULL; + struct timeval defer_endtime; + uint8_t *outhdr = NULL; + uint32_t flags; if (!tevent_req_is_in_progress(subreq)) { return NT_STATUS_OK; @@ -865,7 +857,14 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, req->subreq = subreq; subreq = NULL; - if (req->async) { + if (req->async_te) { + /* We're already async. */ + return NT_STATUS_OK; + } + + outhdr = (uint8_t *)req->out.vector[i].iov_base; + flags = IVAL(outhdr, SMB2_HDR_FLAGS); + if (flags & SMB2_HDR_FLAG_ASYNC) { /* We're already async. */ return NT_STATUS_OK; } @@ -888,6 +887,8 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, } if (req->out.vector_count > 4) { + struct iovec *outvec = NULL; + /* This is a compound reply. We * must do an interim response * followed by the async response @@ -911,18 +912,94 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, */ req->compound_related = false; req->sconn->smb2.compound_related_in_progress = false; + + /* Re-arrange the in.vectors. */ + req->in.vector[1] = req->in.vector[i]; + req->in.vector[2] = req->in.vector[i+1]; + req->in.vector[3] = req->in.vector[i+2]; + req->in.vector_count = 4; + + /* Reset the new in size. */ + smb2_setup_nbt_length(req->in.vector, 4); + + /* Now recreate the out.vectors. */ + outvec = talloc_zero_array(req, struct iovec, 4); + if (!outvec) { + return NT_STATUS_NO_MEMORY; + } + + /* 0 is always boilerplate and must + * be of size 4 for the length field. */ + + outvec[0].iov_base = req->out.nbt_hdr; + outvec[0].iov_len = 4; + SIVAL(req->out.nbt_hdr, 0, 0); + + if (!dup_smb2_vec3(outvec, &outvec[1], &req->out.vector[i])) { + return NT_STATUS_NO_MEMORY; + } + + TALLOC_FREE(req->out.vector); + + req->out.vector = outvec; + + req->current_idx = 1; + req->out.vector_count = 4; + -- Samba Shared Repository