summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/ntvfs/posix/pvfs_lock.c6
-rw-r--r--source4/ntvfs/posix/pvfs_open.c10
-rw-r--r--source4/ntvfs/posix/pvfs_wait.c19
-rw-r--r--source4/ntvfs/posix/vfs_posix.h13
-rw-r--r--source4/torture/raw/mux.c47
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: