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
*/
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;
servid_t server;
uint16_t tid;
struct messaging_context *messaging_ctx;
- struct lock_struct last_lock_failure;
+ struct lock_struct last_lock;
};
brl->server = server;
brl->tid = tid;
brl->messaging_ctx = messaging_ctx;
- ZERO_STRUCT(brl->last_lock_failure);
+ ZERO_STRUCT(brl->last_lock);
return brl;
}
*/
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
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
*/
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);
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
*/
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 */
/* 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 {
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;
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)
}
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);
+}
}
talloc_free(lck);
- talloc_steal(pvfs, req);
talloc_set_destructor(r, pvfs_retry_destructor);
#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;
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;
}
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;
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;
+}
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
/* 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;
};
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
*/
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;
}
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'
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
*/
ops.trans = unixuid_trans;
ops.logoff = unixuid_logoff;
ops.async_setup = unixuid_async_setup;
+ ops.cancel = unixuid_cancel;
ops.name = "unixuid";
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
****************************************************************************/
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);
}
/****************************************************************************
/* 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;