r3528: added support for the SMBntcancel() operation, which cancels any
authorAndrew Tridgell <tridge@samba.org>
Thu, 4 Nov 2004 11:28:38 +0000 (11:28 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:05:28 +0000 (13:05 -0500)
outstanding async operation (triggering an immediate timeout).

pvfs now passes the RAW-MUX test
(This used to be commit 3423e2f41461d054067ef168b9b986f62cc8f77c)

16 files changed:
source4/ntvfs/cifs/vfs_cifs.c
source4/ntvfs/common/brlock.c
source4/ntvfs/ipc/vfs_ipc.c
source4/ntvfs/nbench/vfs_nbench.c
source4/ntvfs/ntvfs.h
source4/ntvfs/ntvfs_generic.c
source4/ntvfs/ntvfs_interface.c
source4/ntvfs/posix/pvfs_open.c
source4/ntvfs/posix/pvfs_wait.c
source4/ntvfs/posix/vfs_posix.c
source4/ntvfs/posix/vfs_posix.h
source4/ntvfs/simple/vfs_simple.c
source4/ntvfs/unixuid/vfs_unixuid.c
source4/script/tests/test_posix.sh
source4/smb_server/reply.c
source4/torture/raw/mux.c

index 3e9899cb8ca691864f8f27317394d451b1a41730..ea169b7ee61143f0451c962652d6a79efed89c4f 100644 (file)
@@ -650,6 +650,15 @@ static NTSTATUS cvfs_async_setup(struct ntvfs_module_context *ntvfs,
        return NT_STATUS_OK;
 }
 
+/*
+  cancel an async call
+*/
+static NTSTATUS cvfs_cancel(struct ntvfs_module_context *ntvfs, 
+                           struct smbsrv_request *req)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 /*
   lock a byte range
 */
@@ -855,6 +864,7 @@ NTSTATUS ntvfs_cifs_init(void)
        ops.trans = cvfs_trans;
        ops.logoff = cvfs_logoff;
        ops.async_setup = cvfs_async_setup;
+       ops.cancel = cvfs_cancel;
 
        if (lp_parm_bool(-1, "cifs", "maptrans2", False)) {
                ops.trans2 = cvfs_trans2;
index 6fae7c6e4cf106558074929e8ac2441c64007fbb..2b30270eff518b2f2c154a8589e67768a01cd3be 100644 (file)
@@ -63,7 +63,7 @@ struct brl_context {
        servid_t server;
        uint16_t tid;
        struct messaging_context *messaging_ctx;
-       struct lock_struct last_lock_failure;
+       struct lock_struct last_lock;
 };
 
 
@@ -95,7 +95,7 @@ struct brl_context *brl_init(TALLOC_CTX *mem_ctx, servid_t server, uint16_t tid,
        brl->server = server;
        brl->tid = tid;
        brl->messaging_ctx = messaging_ctx;
-       ZERO_STRUCT(brl->last_lock_failure);
+       ZERO_STRUCT(brl->last_lock);
 
        return brl;
 }
@@ -194,13 +194,14 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck
 */
 static NTSTATUS brl_lock_failed(struct brl_context *brl, struct lock_struct *lock)
 {
-       if (brl_same_context(&lock->context, &brl->last_lock_failure.context) &&
-           lock->fnum == brl->last_lock_failure.fnum &&
-           lock->start == brl->last_lock_failure.start &&
-           lock->size == brl->last_lock_failure.size) {
+       if (lock->context.server == brl->last_lock.context.server &&
+           lock->context.tid == brl->last_lock.context.tid &&
+           lock->fnum == brl->last_lock.fnum &&
+           lock->start == brl->last_lock.start &&
+           lock->size == brl->last_lock.size) {
                return NT_STATUS_FILE_LOCK_CONFLICT;
        }
-       brl->last_lock_failure = *lock;
+       brl->last_lock = *lock;
        if (lock->start >= 0xEF000000 && 
            (lock->start >> 63) == 0) {
                /* amazing the little things you learn with a test
index dc43dff3aa74d89e1e5786e84215e49df49dd4d5..271be09ac32b0256ec495320c0b5797c8eb52589 100644 (file)
@@ -519,6 +519,15 @@ static NTSTATUS ipc_async_setup(struct ntvfs_module_context *ntvfs,
        return NT_STATUS_OK;
 }
 
+/*
+  cancel an async call
+*/
+static NTSTATUS ipc_cancel(struct ntvfs_module_context *ntvfs,
+                          struct smbsrv_request *req)
+{
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
 /*
   lock a byte range
 */
@@ -744,6 +753,7 @@ NTSTATUS ntvfs_ipc_init(void)
        ops.trans = ipc_trans;
        ops.logoff = ipc_logoff;
        ops.async_setup = ipc_async_setup;
+       ops.cancel = ipc_cancel;
 
        /* register ourselves with the NTVFS subsystem. */
        ret = register_backend("ntvfs", &ops);
index ef435c5d75f9a165a48c0ec61205485944bb5f48..1bcfda1371e424f51e9eb2f70e57d91dab1ea5fc 100644 (file)
@@ -643,6 +643,25 @@ static NTSTATUS nbench_async_setup(struct ntvfs_module_context *ntvfs,
        return status;
 }
 
+
+static void nbench_cancel_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_POST(req);
+}
+
+/*
+  cancel an existing async request
+*/
+static NTSTATUS nbench_cancel(struct ntvfs_module_context *ntvfs,
+                             struct smbsrv_request *req)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, cancel, NULL, (ntvfs, req));
+
+       return status;
+}
+
 /*
   lock a byte range
 */
@@ -898,6 +917,7 @@ NTSTATUS ntvfs_nbench_init(void)
        ops.trans = nbench_trans;
        ops.logoff = nbench_logoff;
        ops.async_setup = nbench_async_setup;
+       ops.cancel = nbench_cancel;
 
        /* we don't register a trans2 handler as we want to be able to
           log individual trans2 requests */
index 62a735774cf5703ef7f2e44d417e54701df0cca9..3a6a78c032750b75c744016ee6b6a0d11d13b507 100644 (file)
@@ -117,6 +117,10 @@ struct ntvfs_ops {
        /* async_setup - called when a backend is processing a async request */
        NTSTATUS (*async_setup)(struct ntvfs_module_context *ntvfs, 
                                struct smbsrv_request *req, void *private);
+
+       /* cancel - cancels any pending async request */
+       NTSTATUS (*cancel)(struct ntvfs_module_context *ntvfs, 
+                          struct smbsrv_request *req);
 };
 
 struct ntvfs_module_context {
index 01a1a2dc6068ac736bd3899fbb0a069ba99cce79..885eb9719ea29d35084d5a633f4f58e3ec921f47 100644 (file)
@@ -942,6 +942,9 @@ NTSTATUS ntvfs_map_write(struct smbsrv_request *req, union smb_write *wr,
 
        status = ntvfs_map_async_setup(req, ntvfs, wr, wr2, 
                                       (second_stage_t)ntvfs_map_write_finish);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        wr2->writex.level = RAW_WRITE_GENERIC;
 
index f1ab21753382bb4b809cb9cfbc5c937ccaa36e35..6ab5aad790b8ec68f1f56b9dadc94d26edb28ddb 100644 (file)
@@ -306,6 +306,20 @@ NTSTATUS ntvfs_async_setup(struct smbsrv_request *req, void *private)
        return ntvfs->ops->async_setup(ntvfs, req, private);
 }
 
+
+/*
+  cancel an outstanding async request
+*/
+NTSTATUS ntvfs_cancel(struct smbsrv_request *req)
+{
+       struct ntvfs_module_context *ntvfs = req->tcon->ntvfs_ctx->modules;
+       if (!ntvfs->ops->cancel) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+       return ntvfs->ops->cancel(ntvfs, req);
+}
+
+
 /* initial setup */
 NTSTATUS ntvfs_next_connect(struct ntvfs_module_context *ntvfs, 
                            struct smbsrv_request *req, const char *sharename)
@@ -588,3 +602,13 @@ NTSTATUS ntvfs_next_async_setup(struct ntvfs_module_context *ntvfs,
        }
        return ntvfs->next->ops->async_setup(ntvfs->next, req, private);
 }
+
+/* cancel - called to cancel an outstanding async request */
+NTSTATUS ntvfs_next_cancel(struct ntvfs_module_context *ntvfs, 
+                          struct smbsrv_request *req)
+{
+       if (!ntvfs->next || !ntvfs->next->ops->cancel) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+       return ntvfs->next->ops->cancel(ntvfs->next, req);
+}
index 8ad6ad0389d08daa36421f1560237121cdfdcf5b..2c0f55cf22cfedb57dcc50b39fd69fb927038faa 100644 (file)
@@ -556,7 +556,6 @@ static NTSTATUS pvfs_open_setup_retry(struct smbsrv_request *req,
        }
 
        talloc_free(lck);
-       talloc_steal(pvfs, req);
 
        talloc_set_destructor(r, pvfs_retry_destructor);
 
index 0faab8ef555f2803cf41de6b135b598f8876f518..df7f045e00d33f945aceb06436ed9abf6d985f81 100644 (file)
 
 #include "include/includes.h"
 #include "events.h"
+#include "dlinklist.h"
 #include "vfs_posix.h"
 
 /* the context for a single wait instance */
 struct pvfs_wait {
+       struct pvfs_wait *next, *prev;
+       struct pvfs_state *pvfs;
        void (*handler)(void *, BOOL);
        void *private;
        struct timed_event *te;
@@ -103,6 +106,7 @@ static int pvfs_wait_destructor(void *ptr)
        struct pvfs_wait *pwait = ptr;
        messaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
        event_remove_timed(pwait->ev, pwait->te);
+       DLIST_REMOVE(pwait->pvfs->wait_list, pwait);
        return 0;
 }
 
@@ -134,6 +138,7 @@ void *pvfs_wait_message(struct pvfs_state *pvfs,
        pwait->ev = req->tcon->smb_conn->connection->event.ctx;
        pwait->msg_type = msg_type;
        pwait->req = req;
+       pwait->pvfs = pvfs;
 
        /* setup a timer */
        te.next_event = end_time;
@@ -152,8 +157,34 @@ void *pvfs_wait_message(struct pvfs_state *pvfs,
           asynchronously */
        req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
 
+       DLIST_ADD(pvfs->wait_list, pwait);
+
        /* make sure we cleanup the timer and message handler */
        talloc_set_destructor(pwait, pvfs_wait_destructor);
 
+       /* make sure that on a disconnect the request is not destroyed
+          before pvfs */
+       talloc_steal(pvfs, req);
+
        return pwait;
 }
+
+
+/*
+  cancel an outstanding async request
+*/
+NTSTATUS pvfs_cancel(struct ntvfs_module_context *ntvfs, struct smbsrv_request *req)
+{
+       struct pvfs_state *pvfs = ntvfs->private_data;
+       struct pvfs_wait *pwait;
+       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());
+                       return NT_STATUS_OK;
+               }
+       }
+
+       return NT_STATUS_UNSUCCESSFUL;
+}
index 7ebea2ea9a72d365d94114d18300b2daa6902013..9ad1d3cb35db98f599048c1c325cc7c39afc02cb 100644 (file)
@@ -236,6 +236,7 @@ NTSTATUS ntvfs_posix_init(void)
        ops.trans = pvfs_trans;
        ops.logoff = pvfs_logoff;
        ops.async_setup = pvfs_async_setup;
+       ops.cancel = pvfs_cancel;
 
        /* register ourselves with the NTVFS subsystem. We register
           under the name 'default' as we wish to be the default
index 265649f5a38004f3e2b90314fa31b64966dda2ac..ce6e7ad24d60af6e508dc56d95f7982fb923d17a 100644 (file)
@@ -46,6 +46,10 @@ struct pvfs_state {
 
        /* an id tree mapping open file handle -> struct pvfs_file */
        struct idr_context *idtree_fnum;
+
+       /* a list of pending async requests. Needed to support
+          ntcancel */
+       struct pvfs_wait *wait_list;
 };
 
 
index 97dd8a7d60fd684c9f69d7821548c3c4d2fe004f..807f51a43daa3d34d4a39f8f4db60998be482999 100644 (file)
@@ -608,6 +608,14 @@ static NTSTATUS svfs_async_setup(struct ntvfs_module_context *ntvfs,
        return NT_STATUS_OK;
 }
 
+/*
+  cancel an async call
+*/
+static NTSTATUS svfs_cancel(struct ntvfs_module_context *ntvfs, struct smbsrv_request *req)
+{
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
 /*
   lock a byte range
 */
@@ -668,6 +676,10 @@ static NTSTATUS svfs_setfileinfo(struct ntvfs_module_context *ntvfs,
                        return NT_STATUS_ACCESS_DENIED;
                }
                break;
+       default:
+               DEBUG(2,("svfs_setfileinfo: level %d not implemented\n", 
+                        info->generic.level));
+               return NT_STATUS_NOT_IMPLEMENTED;
        }
        return NT_STATUS_OK;
 }
@@ -986,6 +998,7 @@ NTSTATUS ntvfs_simple_init(void)
        ops.trans = svfs_trans;
        ops.logoff = svfs_logoff;
        ops.async_setup = svfs_async_setup;
+       ops.cancel = svfs_cancel;
 
        /* register ourselves with the NTVFS subsystem. We register
           under names 'simple'
index 9b62c38e13bd1c6e0dbe00be05a002ef5132f6bd..7f8f8acf99848b92db728e1fbb1c8ed7e5991c60 100644 (file)
@@ -640,6 +640,19 @@ static NTSTATUS unixuid_async_setup(struct ntvfs_module_context *ntvfs,
        return status;
 }
 
+/*
+  cancel an async request
+*/
+static NTSTATUS unixuid_cancel(struct ntvfs_module_context *ntvfs,
+                              struct smbsrv_request *req)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, cancel, (ntvfs, req));
+
+       return status;
+}
+
 /*
   lock a byte range
 */
@@ -784,6 +797,7 @@ NTSTATUS ntvfs_unixuid_init(void)
        ops.trans = unixuid_trans;
        ops.logoff = unixuid_logoff;
        ops.async_setup = unixuid_async_setup;
+       ops.cancel = unixuid_cancel;
 
        ops.name = "unixuid";
 
index e2cad843064bbaa9198f0c92c82dfd6e9aacc59a..c31d4b70ea5dd03f8485f5c7c46781a3132d9553 100755 (executable)
@@ -37,12 +37,12 @@ tests="$tests BASE-DELETE BASE-PROPERTIES BASE-MANGLE"
 tests="$tests BASE-CHKPATH BASE-SECLEAK BASE-TRANS2"
 tests="$tests BASE-NTDENY1 BASE-NTDENY2  BASE-RENAME"
 tests="$tests RAW-QFSINFO RAW-QFILEINFO RAW-SFILEINFO-BUG"
-tests="$tests RAW-LOCK RAW-MKDIR RAW-SEEK RAW-CONTEXT"
+tests="$tests RAW-LOCK RAW-MKDIR RAW-SEEK RAW-CONTEXT RAW-MUX"
 tests="$tests RAW-UNLINK RAW-READ RAW-CLOSE RAW-IOCTL RAW-SEARCH RAW-CHKPATH"
 tests="$tests LOCAL-ICONV LOCAL-TALLOC LOCAL-MESSAGING LOCAL-BINDING LOCAL-IDTREE"
 
 soon="BASE-DENY1 BASE-DEFER_OPEN BASE-OPENATTR BASE-CHARSET"
-soon="$soon RAW-SFILEINFO RAW-OPEN RAW-OPLOCK RAW-NOTIFY RAW-MUX"
+soon="$soon RAW-SFILEINFO RAW-OPEN RAW-OPLOCK RAW-NOTIFY"
 soon="$soon RAW-WRITE RAW-RENAME"
 
 for t in $tests; do
index 9c7d027f4a1795f156bfcd25bd153c6b6b3c7e54..615dd692a140f842bd8b7a9bb0696bd1b992e804 100644 (file)
@@ -2319,7 +2319,9 @@ void reply_ntcreate_and_X(struct smbsrv_request *req)
 ****************************************************************************/
 void reply_ntcancel(struct smbsrv_request *req)
 {
-       req_reply_error(req, NT_STATUS_FOOBAR);
+       /* NOTE: this request does not generate a reply */
+       ntvfs_cancel(req);
+       req_destroy(req);
 }
 
 /****************************************************************************
index c02045817e71523bc6947bb059627e599f79321d..7dddd0602c04b338d720a2ed4b666c9bfa54feb1 100644 (file)
@@ -252,6 +252,10 @@ static BOOL test_mux_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
        /* cancel the blocking lock */
        smb_raw_ntcancel(req);
 
+       /* the 2nd cancel is totally harmless, but tests the server trying to 
+          cancel an already cancelled request */
+       smb_raw_ntcancel(req);
+
        lock[0].pid = 1;
        io.lockx.in.ulock_cnt = 1;
        io.lockx.in.lock_cnt = 0;