diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-11-05 02:22:07 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:05:30 -0500 |
commit | 1d97e7b9d8a8e716cd50bb42065687a65d542b2d (patch) | |
tree | 4cb4743b53cbb51dd2f01bf032cd53cba2006b61 /source4 | |
parent | 80eef3ea6647a9f8600466b2b468d38bd2eb0664 (diff) | |
download | samba-1d97e7b9d8a8e716cd50bb42065687a65d542b2d.tar.gz samba-1d97e7b9d8a8e716cd50bb42065687a65d542b2d.tar.bz2 samba-1d97e7b9d8a8e716cd50bb42065687a65d542b2d.zip |
r3540: added testing of SMBntcancel in the open/open/close mux
testing. Interestingly, w2k3 does not allow the cancel of an
outstanding async open request, whereas it does allow the cancel of an
outstanding async lock request. To support this I have changed the
pvfs_wait interface to provide a enum on why the event is happening,
so the callback can decide what to do.
(This used to be commit f23d6a28008a13588cde24b5012ec21e488ac47a)
Diffstat (limited to 'source4')
-rw-r--r-- | source4/ntvfs/posix/pvfs_lock.c | 6 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_open.c | 10 | ||||
-rw-r--r-- | source4/ntvfs/posix/pvfs_wait.c | 19 | ||||
-rw-r--r-- | source4/ntvfs/posix/vfs_posix.h | 13 | ||||
-rw-r--r-- | source4/torture/raw/mux.c | 47 |
5 files changed, 69 insertions, 26 deletions
diff --git a/source4/ntvfs/posix/pvfs_lock.c b/source4/ntvfs/posix/pvfs_lock.c index 82ac9ebad5..f778b59d95 100644 --- a/source4/ntvfs/posix/pvfs_lock.c +++ b/source4/ntvfs/posix/pvfs_lock.c @@ -91,7 +91,7 @@ static void pvfs_lock_async_failed(struct pvfs_state *pvfs, range, so we should try the lock again. Note that on timeout we do retry the lock, giving it a last chance. */ -static void pvfs_pending_lock_continue(void *private, BOOL timed_out) +static void pvfs_pending_lock_continue(void *private, enum pvfs_wait_notice reason) { struct pvfs_pending_lock *pending = private; struct pvfs_state *pvfs = pending->pvfs; @@ -102,6 +102,10 @@ static void pvfs_pending_lock_continue(void *private, BOOL timed_out) enum brl_type rw; NTSTATUS status; int i; + BOOL timed_out; + + /* we consider a cancel to be a timeout */ + timed_out = (reason != PVFS_WAIT_EVENT); locks = lck->lockx.in.locks + lck->lockx.in.ulock_cnt; diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 73b1949acb..c8f96849ec 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -430,7 +430,7 @@ static int pvfs_retry_destructor(void *ptr) /* retry an open */ -static void pvfs_open_retry(void *private, BOOL timed_out) +static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) { struct pvfs_open_retry *r = private; struct ntvfs_module_context *ntvfs = r->ntvfs; @@ -438,9 +438,15 @@ static void pvfs_open_retry(void *private, BOOL timed_out) union smb_open *io = r->io; NTSTATUS status; + /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably + just a bug in their server, but we better do the same */ + if (reason == PVFS_WAIT_CANCEL) { + return; + } + talloc_free(r->wait_handle); - if (timed_out) { + if (reason == PVFS_WAIT_TIMEOUT) { /* if it timed out, then give the failure immediately */ talloc_free(r); diff --git a/source4/ntvfs/posix/pvfs_wait.c b/source4/ntvfs/posix/pvfs_wait.c index df7f045e00..dd7afaf653 100644 --- a/source4/ntvfs/posix/pvfs_wait.c +++ b/source4/ntvfs/posix/pvfs_wait.c @@ -29,14 +29,14 @@ struct pvfs_wait { struct pvfs_wait *next, *prev; struct pvfs_state *pvfs; - void (*handler)(void *, BOOL); + void (*handler)(void *, enum pvfs_wait_notice); void *private; struct timed_event *te; int msg_type; struct messaging_context *msg_ctx; struct event_context *ev; struct smbsrv_request *req; - BOOL timed_out; + enum pvfs_wait_notice reason; }; /* @@ -48,7 +48,7 @@ NTSTATUS pvfs_async_setup(struct ntvfs_module_context *ntvfs, struct smbsrv_request *req, void *private) { struct pvfs_wait *pwait = private; - pwait->handler(pwait->private, pwait->timed_out); + pwait->handler(pwait->private, pwait->reason); return NT_STATUS_OK; } @@ -68,7 +68,7 @@ static void pvfs_wait_dispatch(struct messaging_context *msg, void *private, uin *(void **)data->data != pwait->private) { return; } - pwait->timed_out = False; + pwait->reason = PVFS_WAIT_EVENT; req = pwait->req; /* the extra reference here is to ensure that the req @@ -90,7 +90,7 @@ static void pvfs_wait_timeout(struct event_context *ev, struct pvfs_wait *pwait = te->private; struct smbsrv_request *req = pwait->req; - pwait->timed_out = True; + pwait->reason = PVFS_WAIT_TIMEOUT; talloc_increase_ref_count(req); ntvfs_async_setup(pwait->req, pwait); @@ -117,11 +117,11 @@ static int pvfs_wait_destructor(void *ptr) the return value is a handle. To stop waiting talloc_free this handle. */ -void *pvfs_wait_message(struct pvfs_state *pvfs, + void *pvfs_wait_message(struct pvfs_state *pvfs, struct smbsrv_request *req, int msg_type, struct timeval end_time, - void (*fn)(void *, BOOL), + void (*fn)(void *, enum pvfs_wait_notice), void *private) { struct timed_event te; @@ -180,8 +180,9 @@ NTSTATUS pvfs_cancel(struct ntvfs_module_context *ntvfs, struct smbsrv_request * for (pwait=pvfs->wait_list;pwait;pwait=pwait->next) { if (SVAL(req->in.hdr, HDR_MID) == SVAL(pwait->req->in.hdr, HDR_MID) && req->smbpid == pwait->req->smbpid) { - /* trigger an early timeout */ - pvfs_wait_timeout(pwait->ev, pwait->te, timeval_current()); + /* trigger a cancel on the request */ + pwait->reason = PVFS_WAIT_CANCEL; + ntvfs_async_setup(pwait->req, pwait); return NT_STATUS_OK; } } diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h index e0d8e7fe37..4ee06723ac 100644 --- a/source4/ntvfs/posix/vfs_posix.h +++ b/source4/ntvfs/posix/vfs_posix.h @@ -165,4 +165,17 @@ struct pvfs_mangle_context { /* forward declare some anonymous structures */ struct pvfs_dir; +/* types of notification for pvfs wait events */ +enum pvfs_wait_notice {PVFS_WAIT_EVENT, PVFS_WAIT_TIMEOUT, PVFS_WAIT_CANCEL}; + + +/* putting this prototype here avoids us having to expose this whole header in the + rest of Samba */ +void *pvfs_wait_message(struct pvfs_state *pvfs, + struct smbsrv_request *req, + int msg_type, + struct timeval end_time, + void (*fn)(void *, enum pvfs_wait_notice), + void *private); + #endif /* _VFS_POSIX_H_ */ diff --git a/source4/torture/raw/mux.c b/source4/torture/raw/mux.c index 6f9426490e..39eb5c1d5e 100644 --- a/source4/torture/raw/mux.c +++ b/source4/torture/raw/mux.c @@ -41,15 +41,13 @@ static BOOL test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) NTSTATUS status; int fnum1, fnum2; BOOL ret = True; - struct smbcli_request *req; + struct smbcli_request *req1, *req2; struct timeval tv; double d; printf("testing multiplexed open/open/close\n"); - /* - file open with no share access - */ + printf("send first open\n"); io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.root_fid = 0; io.ntcreatex.in.flags = 0; @@ -66,7 +64,7 @@ static BOOL test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) CHECK_STATUS(status, NT_STATUS_OK); fnum1 = io.ntcreatex.out.fnum; - /* and a 2nd open, this will not conflict */ + printf("send 2nd open, non-conflicting\n"); io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); @@ -74,7 +72,7 @@ static BOOL test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) tv = timeval_current(); - /* send an open that will conflict */ + printf("send 3rd open, conflicting\n"); io.ntcreatex.in.share_access = 0; status = smb_raw_open(cli->tree, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); @@ -87,20 +85,31 @@ static BOOL test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) printf("open delay %.2f\n", d); } - /* - same request, but async - */ + printf("send async open, conflicting\n"); + tv = timeval_current(); + req1 = smb_raw_open_send(cli->tree, &io); + + printf("send 2nd async open, conflicting\n"); tv = timeval_current(); - req = smb_raw_open_send(cli->tree, &io); + req2 = smb_raw_open_send(cli->tree, &io); - /* and close the first file */ + printf("close first sync open\n"); smbcli_close(cli->tree, fnum1); - /* then the 2nd file */ + printf("cancel 2nd async open (should be ignored)\n"); + smb_raw_ntcancel(req2); + + d = timeval_elapsed(&tv); + if (d > 0.25) { + printf("bad timeout after cancel - %.2f should be <0.25\n", d); + ret = False; + } + + printf("close the 2nd sync open\n"); smbcli_close(cli->tree, fnum2); - /* see if the async open succeeded */ - status = smb_raw_open_recv(req, mem_ctx, &io); + printf("see if the 1st async open now succeeded\n"); + status = smb_raw_open_recv(req1, mem_ctx, &io); CHECK_STATUS(status, NT_STATUS_OK); d = timeval_elapsed(&tv); @@ -111,6 +120,16 @@ static BOOL test_mux_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) printf("async open delay %.2f\n", d); } + printf("2nd async open should have timed out\n"); + status = smb_raw_open_recv(req2, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION); + d = timeval_elapsed(&tv); + if (d < 0.8) { + printf("bad timeout for async conflict - %.2f should be 1.0\n", d); + ret = False; + } + + printf("close the 1st async open\n"); smbcli_close(cli->tree, io.ntcreatex.out.fnum); done: |