*/
#include "includes.h"
+#include "smbd/smbd.h"
#include "smbd/globals.h"
+#include "../lib/util/tevent_ntstatus.h"
#if defined(WITH_AIO)
struct aio_extra *next, *prev;
SMB_STRUCT_AIOCB acb;
files_struct *fsp;
- struct smb_request *req;
- char *outbuf;
+ struct smb_request *smbreq;
+ DATA_BLOB outbuf;
struct lock_struct lock;
+ bool write_through;
int (*handle_completion)(struct aio_extra *ex, int errcode);
};
struct aio_extra *aio_ex = (struct aio_extra *)
info->si_value.sival_ptr;
- smbd_aio_complete_mid(aio_ex->req->mid);
+ smbd_aio_complete_aio_ex(aio_ex);
}
-static void initialize_async_io_handler(void)
+static bool initialize_async_io_handler(void)
{
+ static bool tried_signal_setup = false;
+
if (aio_signal_event) {
- return;
+ return true;
+ }
+ if (tried_signal_setup) {
+ return false;
}
+ tried_signal_setup = true;
- aio_signal_event = tevent_add_signal(smbd_event_context(),
- smbd_event_context(),
+ aio_signal_event = tevent_add_signal(server_event_context(),
+ server_event_context(),
RT_SIGNAL_AIO, SA_SIGINFO,
smbd_aio_signal_handler,
NULL);
if (!aio_signal_event) {
- exit_server("Failed to setup RT_SIGNAL_AIO handler");
+ DEBUG(10, ("Failed to setup RT_SIGNAL_AIO handler\n"));
+ return false;
}
/* tevent supports 100 signal with SA_SIGINFO */
aio_pending_size = 100;
+ return true;
}
static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode);
static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode);
+static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode);
+static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode);
static int aio_extra_destructor(struct aio_extra *aio_ex)
{
of the aio call.
*****************************************************************************/
-static struct aio_extra *create_aio_extra(files_struct *fsp, size_t buflen)
+static struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx,
+ files_struct *fsp,
+ size_t buflen)
{
- struct aio_extra *aio_ex = TALLOC_ZERO_P(NULL, struct aio_extra);
+ struct aio_extra *aio_ex = talloc_zero(mem_ctx, struct aio_extra);
if (!aio_ex) {
return NULL;
the smb return buffer. The buffer used in the acb
is the start of the reply data portion of that buffer. */
- aio_ex->outbuf = TALLOC_ARRAY(aio_ex, char, buflen);
- if (!aio_ex->outbuf) {
- TALLOC_FREE(aio_ex);
- return NULL;
+ if (buflen) {
+ aio_ex->outbuf = data_blob_talloc(aio_ex, NULL, buflen);
+ if (!aio_ex->outbuf.data) {
+ TALLOC_FREE(aio_ex);
+ return NULL;
+ }
}
DLIST_ADD(aio_list_head, aio_ex);
talloc_set_destructor(aio_ex, aio_extra_destructor);
return aio_ex;
}
-/****************************************************************************
- Given the mid find the extended aio struct containing it.
-*****************************************************************************/
-
-static struct aio_extra *find_aio_ex(uint64_t mid)
-{
- struct aio_extra *p;
-
- for( p = aio_list_head; p; p = p->next) {
- if (mid == p->req->mid) {
- return p;
- }
- }
- return NULL;
-}
-
-/****************************************************************************
- We can have these many aio buffers in flight.
-*****************************************************************************/
-
/****************************************************************************
Set up an aio request from a SMBreadX call.
*****************************************************************************/
NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
- struct smb_request *req,
+ struct smb_request *smbreq,
files_struct *fsp, SMB_OFF_T startpos,
size_t smb_maxcnt)
{
int ret;
/* Ensure aio is initialized. */
- initialize_async_io_handler();
+ if (!initialize_async_io_handler()) {
+ return NT_STATUS_RETRY;
+ }
if (fsp->base_fsp != NULL) {
/* No AIO on streams yet */
/* Only do this on non-chained and non-chaining reads not using the
* write cache. */
- if (req_is_in_chain(req) || (lp_write_cache_size(SNUM(conn)) != 0)) {
+ if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) {
return NT_STATUS_RETRY;
}
bufsize = smb_size + 12 * 2 + smb_maxcnt;
- if ((aio_ex = create_aio_extra(fsp, bufsize)) == NULL) {
+ if ((aio_ex = create_aio_extra(NULL, fsp, bufsize)) == NULL) {
DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
return NT_STATUS_NO_MEMORY;
}
aio_ex->handle_completion = handle_aio_read_complete;
- construct_reply_common_req(req, aio_ex->outbuf);
- srv_set_message(aio_ex->outbuf, 12, 0, True);
- SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */
+ construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
+ srv_set_message((char *)aio_ex->outbuf.data, 12, 0, True);
+ SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
- init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
+ init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
(uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
&aio_ex->lock);
/* Now set up the aio record for the read call. */
a->aio_fildes = fsp->fh->fd;
- a->aio_buf = smb_buf(aio_ex->outbuf);
+ a->aio_buf = smb_buf(aio_ex->outbuf.data);
a->aio_nbytes = smb_maxcnt;
a->aio_offset = startpos;
a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
}
outstanding_aio_calls++;
- aio_ex->req = talloc_move(aio_ex, &req);
+ aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, "
"offset %.0f, len = %u (mid = %u)\n",
fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
- (unsigned int)aio_ex->req->mid ));
+ (unsigned int)aio_ex->smbreq->mid ));
return NT_STATUS_OK;
}
*****************************************************************************/
NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
- struct smb_request *req,
- files_struct *fsp, char *data,
+ struct smb_request *smbreq,
+ files_struct *fsp, const char *data,
SMB_OFF_T startpos,
size_t numtowrite)
{
struct aio_extra *aio_ex;
SMB_STRUCT_AIOCB *a;
size_t bufsize;
- bool write_through = BITSETW(req->vwv+7,0);
size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
int ret;
/* Ensure aio is initialized. */
- initialize_async_io_handler();
+ if (!initialize_async_io_handler()) {
+ return NT_STATUS_RETRY;
+ }
if (fsp->base_fsp != NULL) {
/* No AIO on streams yet */
return NT_STATUS_RETRY;
}
- /* Only do this on non-chained and non-chaining reads not using the
+ /* Only do this on non-chained and non-chaining writes not using the
* write cache. */
- if (req_is_in_chain(req) || (lp_write_cache_size(SNUM(conn)) != 0)) {
+ if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) {
return NT_STATUS_RETRY;
}
"(mid = %u)\n",
fsp_str_dbg(fsp), (double)startpos,
(unsigned int)numtowrite,
- (unsigned int)req->mid ));
+ (unsigned int)smbreq->mid ));
return NT_STATUS_RETRY;
}
bufsize = smb_size + 6*2;
- if (!(aio_ex = create_aio_extra(fsp, bufsize))) {
+ if (!(aio_ex = create_aio_extra(NULL, fsp, bufsize))) {
DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n"));
return NT_STATUS_NO_MEMORY;
}
aio_ex->handle_completion = handle_aio_write_complete;
+ aio_ex->write_through = BITSETW(smbreq->vwv+7,0);
- construct_reply_common_req(req, aio_ex->outbuf);
- srv_set_message(aio_ex->outbuf, 6, 0, True);
- SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */
+ construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
+ srv_set_message((char *)aio_ex->outbuf.data, 6, 0, True);
+ SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
- init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
+ init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
(uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
&aio_ex->lock);
/* Now set up the aio record for the write call. */
a->aio_fildes = fsp->fh->fd;
- a->aio_buf = data;
+ a->aio_buf = discard_const_p(char, data);
a->aio_nbytes = numtowrite;
a->aio_offset = startpos;
a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
}
outstanding_aio_calls++;
- aio_ex->req = talloc_move(aio_ex, &req);
+ aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
/* This should actually be improved to span the write. */
contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
- if (!write_through && !lp_syncalways(SNUM(fsp->conn))
+ if (!aio_ex->write_through && !lp_syncalways(SNUM(fsp->conn))
&& fsp->aio_write_behind) {
/* Lie to the client and immediately claim we finished the
* write. */
- SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite);
- SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
- show_msg(aio_ex->outbuf);
- if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf,
- true, aio_ex->req->seqnum+1,
+ SSVAL(aio_ex->outbuf.data,smb_vwv2,numtowrite);
+ SSVAL(aio_ex->outbuf.data,smb_vwv4,(numtowrite>>16)&1);
+ show_msg((char *)aio_ex->outbuf.data);
+ if (!srv_send_smb(aio_ex->smbreq->sconn,
+ (char *)aio_ex->outbuf.data,
+ true, aio_ex->smbreq->seqnum+1,
IS_CONN_ENCRYPTED(fsp->conn),
- &aio_ex->req->pcd)) {
- exit_server_cleanly("handle_aio_write: srv_send_smb "
- "failed.");
+ &aio_ex->smbreq->pcd)) {
+ exit_server_cleanly("schedule_aio_write_and_X: "
+ "srv_send_smb failed.");
}
DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
"behind for file %s\n", fsp_str_dbg(fsp)));
"%s, offset %.0f, len = %u (mid = %u) "
"outstanding_aio_calls = %d\n",
fsp_str_dbg(fsp), (double)startpos, (unsigned int)numtowrite,
- (unsigned int)aio_ex->req->mid, outstanding_aio_calls ));
+ (unsigned int)aio_ex->smbreq->mid, outstanding_aio_calls ));
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Set up an aio request from a SMB2 read call.
+*****************************************************************************/
+
+NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
+ struct smb_request *smbreq,
+ files_struct *fsp,
+ TALLOC_CTX *ctx,
+ DATA_BLOB *preadbuf,
+ SMB_OFF_T startpos,
+ size_t smb_maxcnt)
+{
+ struct aio_extra *aio_ex;
+ SMB_STRUCT_AIOCB *a;
+ size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
+ int ret;
+
+ /* Ensure aio is initialized. */
+ if (!initialize_async_io_handler()) {
+ return NT_STATUS_RETRY;
+ }
+
+ if (fsp->base_fsp != NULL) {
+ /* No AIO on streams yet */
+ DEBUG(10, ("AIO on streams not yet supported\n"));
+ return NT_STATUS_RETRY;
+ }
+
+ if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
+ && !SMB_VFS_AIO_FORCE(fsp)) {
+ /* Too small a read for aio request. */
+ DEBUG(10,("smb2: read size (%u) too small "
+ "for minimum aio_read of %u\n",
+ (unsigned int)smb_maxcnt,
+ (unsigned int)min_aio_read_size ));
+ return NT_STATUS_RETRY;
+ }
+
+ /* Only do this on reads not using the write cache. */
+ if (lp_write_cache_size(SNUM(conn)) != 0) {
+ return NT_STATUS_RETRY;
+ }
+
+ if (outstanding_aio_calls >= aio_pending_size) {
+ DEBUG(10,("smb2: Already have %d aio "
+ "activities outstanding.\n",
+ outstanding_aio_calls ));
+ return NT_STATUS_RETRY;
+ }
+
+ /* Create the out buffer. */
+ *preadbuf = data_blob_talloc(ctx, NULL, smb_maxcnt);
+ if (preadbuf->data == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ aio_ex->handle_completion = handle_aio_smb2_read_complete;
+
+ init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
+ (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
+ &aio_ex->lock);
+
+ /* Take the lock until the AIO completes. */
+ if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
+ TALLOC_FREE(aio_ex);
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ }
+
+ a = &aio_ex->acb;
+
+ /* Now set up the aio record for the read call. */
+
+ a->aio_fildes = fsp->fh->fd;
+ a->aio_buf = preadbuf->data;
+ a->aio_nbytes = smb_maxcnt;
+ a->aio_offset = startpos;
+ a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO;
+ a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
+
+ ret = SMB_VFS_AIO_READ(fsp, a);
+ if (ret == -1) {
+ DEBUG(0,("smb2: aio_read failed. "
+ "Error %s\n", strerror(errno) ));
+ SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
+ TALLOC_FREE(aio_ex);
+ return NT_STATUS_RETRY;
+ }
+
+ outstanding_aio_calls++;
+ /* We don't need talloc_move here as both aio_ex and
+ * smbreq are children of smbreq->smb2req. */
+ aio_ex->smbreq = smbreq;
+
+ DEBUG(10,("smb2: scheduled aio_read for file %s, "
+ "offset %.0f, len = %u (mid = %u)\n",
+ fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
+ (unsigned int)aio_ex->smbreq->mid ));
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Set up an aio request from a SMB2write call.
+*****************************************************************************/
+
+NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
+ struct smb_request *smbreq,
+ files_struct *fsp,
+ uint64_t in_offset,
+ DATA_BLOB in_data,
+ bool write_through)
+{
+ struct aio_extra *aio_ex = NULL;
+ SMB_STRUCT_AIOCB *a = NULL;
+ size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
+ int ret;
+
+ /* Ensure aio is initialized. */
+ if (!initialize_async_io_handler()) {
+ return NT_STATUS_RETRY;
+ }
+
+ if (fsp->base_fsp != NULL) {
+ /* No AIO on streams yet */
+ DEBUG(10, ("AIO on streams not yet supported\n"));
+ return NT_STATUS_RETRY;
+ }
+
+ if ((!min_aio_write_size || (in_data.length < min_aio_write_size))
+ && !SMB_VFS_AIO_FORCE(fsp)) {
+ /* Too small a write for aio request. */
+ DEBUG(10,("smb2: write size (%u) too "
+ "small for minimum aio_write of %u\n",
+ (unsigned int)in_data.length,
+ (unsigned int)min_aio_write_size ));
+ return NT_STATUS_RETRY;
+ }
+
+ /* Only do this on writes not using the write cache. */
+ if (lp_write_cache_size(SNUM(conn)) != 0) {
+ return NT_STATUS_RETRY;
+ }
+
+ if (outstanding_aio_calls >= aio_pending_size) {
+ DEBUG(3,("smb2: Already have %d aio "
+ "activities outstanding.\n",
+ outstanding_aio_calls ));
+ return NT_STATUS_RETRY;
+ }
+
+ if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ aio_ex->handle_completion = handle_aio_smb2_write_complete;
+ aio_ex->write_through = write_through;
+
+ init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
+ in_offset, (uint64_t)in_data.length, WRITE_LOCK,
+ &aio_ex->lock);
+
+ /* Take the lock until the AIO completes. */
+ if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
+ TALLOC_FREE(aio_ex);
+ return NT_STATUS_FILE_LOCK_CONFLICT;
+ }
+
+ a = &aio_ex->acb;
+
+ /* Now set up the aio record for the write call. */
+
+ a->aio_fildes = fsp->fh->fd;
+ a->aio_buf = in_data.data;
+ a->aio_nbytes = in_data.length;
+ a->aio_offset = in_offset;
+ a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO;
+ a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
+
+ ret = SMB_VFS_AIO_WRITE(fsp, a);
+ if (ret == -1) {
+ DEBUG(3,("smb2: aio_write failed. "
+ "Error %s\n", strerror(errno) ));
+ SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
+ TALLOC_FREE(aio_ex);
+ return NT_STATUS_RETRY;
+ }
+
+ outstanding_aio_calls++;
+ /* We don't need talloc_move here as both aio_ex and
+ * smbreq are children of smbreq->smb2req. */
+ aio_ex->smbreq = smbreq;
+
+ /* This should actually be improved to span the write. */
+ contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
+ contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
+
+ /*
+ * We don't want to do write behind due to ownership
+ * issues of the request structs. Maybe add it if I
+ * figure those out. JRA.
+ */
+
+ DEBUG(10,("smb2: scheduled aio_write for file "
+ "%s, offset %.0f, len = %u (mid = %u) "
+ "outstanding_aio_calls = %d\n",
+ fsp_str_dbg(fsp),
+ (double)in_offset,
+ (unsigned int)in_data.length,
+ (unsigned int)aio_ex->smbreq->mid,
+ outstanding_aio_calls ));
return NT_STATUS_OK;
}
static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
{
int outsize;
- char *outbuf = aio_ex->outbuf;
+ char *outbuf = (char *)aio_ex->outbuf.data;
char *data = smb_buf(outbuf);
ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
}
smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
- if (!srv_send_smb(smbd_server_fd(),outbuf,
- true, aio_ex->req->seqnum+1,
+ if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
+ true, aio_ex->smbreq->seqnum+1,
IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) {
exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
"failed.");
static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
{
files_struct *fsp = aio_ex->fsp;
- char *outbuf = aio_ex->outbuf;
+ char *outbuf = (char *)aio_ex->outbuf.data;
ssize_t numtowrite = aio_ex->acb.aio_nbytes;
ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
ERROR_NT(map_nt_error_from_unix(errcode));
srv_set_message(outbuf,0,0,true);
} else {
- bool write_through = BITSETW(aio_ex->req->vwv+7,0);
NTSTATUS status;
SSVAL(outbuf,smb_vwv2,nwritten);
DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n",
fsp->fnum, (int)numtowrite, (int)nwritten));
- status = sync_file(fsp->conn,fsp, write_through);
+ status = sync_file(fsp->conn,fsp, aio_ex->write_through);
if (!NT_STATUS_IS_OK(status)) {
errcode = errno;
ERROR_BOTH(map_nt_error_from_unix(errcode),
}
show_msg(outbuf);
- if (!srv_send_smb(smbd_server_fd(),outbuf,
- true, aio_ex->req->seqnum+1,
+ if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
+ true, aio_ex->smbreq->seqnum+1,
IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
- exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
+ exit_server_cleanly("handle_aio_write_complete: "
+ "srv_send_smb failed.");
}
DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
return errcode;
}
+/****************************************************************************
+ Complete the read and return the data or error back to the client.
+ Returns errno or zero if all ok.
+*****************************************************************************/
+
+static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode)
+{
+ NTSTATUS status;
+ struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
+ ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
+
+ /* Common error or success code processing for async or sync
+ read returns. */
+
+ status = smb2_read_complete(subreq, nread, errcode);
+
+ if (nread > 0) {
+ aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
+ aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
+ }
+
+ DEBUG(10,("smb2: scheduled aio_read completed "
+ "for file %s, offset %.0f, len = %u "
+ "(errcode = %d, NTSTATUS = %s)\n",
+ fsp_str_dbg(aio_ex->fsp),
+ (double)aio_ex->acb.aio_offset,
+ (unsigned int)nread,
+ errcode,
+ nt_errstr(status) ));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(subreq, status);
+ }
+
+ tevent_req_done(subreq);
+ return errcode;
+}
+
+/****************************************************************************
+ Complete the SMB2 write and return the data or error back to the client.
+ Returns error code or zero if all ok.
+*****************************************************************************/
+
+static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode)
+{
+ files_struct *fsp = aio_ex->fsp;
+ ssize_t numtowrite = aio_ex->acb.aio_nbytes;
+ ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
+ struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
+ NTSTATUS status;
+
+ status = smb2_write_complete(subreq, nwritten, errcode);
+
+ DEBUG(10,("smb2: scheduled aio_write completed "
+ "for file %s, offset %.0f, requested %u, "
+ "written = %u (errcode = %d, NTSTATUS = %s)\n",
+ fsp_str_dbg(fsp),
+ (double)aio_ex->acb.aio_offset,
+ (unsigned int)numtowrite,
+ (unsigned int)nwritten,
+ errcode,
+ nt_errstr(status) ));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(subreq, status);
+ }
+
+ tevent_req_done(subreq);
+ return errcode;
+}
+
/****************************************************************************
Handle any aio completion. Returns True if finished (and sets *perr if err
was non-zero), False if not.
if (err == EINPROGRESS) {
DEBUG(10,( "handle_aio_completed: operation mid %llu still in "
"process for file %s\n",
- (unsigned long long)aio_ex->req->mid,
+ (unsigned long long)aio_ex->smbreq->mid,
fsp_str_dbg(aio_ex->fsp)));
return False;
}
* client. */
DEBUG(10,( "handle_aio_completed: operation mid %llu"
" canceled\n",
- (unsigned long long)aio_ex->req->mid));
+ (unsigned long long)aio_ex->smbreq->mid));
return True;
}
Handle any aio completion inline.
*****************************************************************************/
-void smbd_aio_complete_mid(uint64_t mid)
+void smbd_aio_complete_aio_ex(struct aio_extra *aio_ex)
{
files_struct *fsp = NULL;
- struct aio_extra *aio_ex = find_aio_ex(mid);
int ret = 0;
outstanding_aio_calls--;
DEBUG(10,("smbd_aio_complete_mid: mid[%llu]\n",
- (unsigned long long)mid));
-
- if (!aio_ex) {
- DEBUG(3,("smbd_aio_complete_mid: Can't find record to "
- "match mid %llu.\n",
- (unsigned long long)mid));
- return;
- }
+ (unsigned long long)aio_ex->smbreq->mid));
fsp = aio_ex->fsp;
if (fsp == NULL) {
* ignore. */
DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
"aio outstanding (mid[%llu]).\n",
- (unsigned long long)mid));
+ (unsigned long long)aio_ex->smbreq->mid));
return;
}
struct aio_extra *aio_ex;
const SMB_STRUCT_AIOCB **aiocb_list;
int aio_completion_count = 0;
- time_t start_time = time(NULL);
+ time_t start_time = time_mono(NULL);
int seconds_left;
for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT;
SAFE_FREE(aiocb_list);
seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT
- - (time(NULL) - start_time);
+ - (time_mono(NULL) - start_time);
}
/* We timed out - we don't know why. Return ret if already an error,
#else
NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
- struct smb_request *req,
+ struct smb_request *smbreq,
files_struct *fsp, SMB_OFF_T startpos,
size_t smb_maxcnt)
{
}
NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
- struct smb_request *req,
- files_struct *fsp, char *data,
+ struct smb_request *smbreq,
+ files_struct *fsp, const char *data,
SMB_OFF_T startpos,
size_t numtowrite)
{
return NT_STATUS_RETRY;
}
+NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
+ struct smb_request *smbreq,
+ files_struct *fsp,
+ TALLOC_CTX *ctx,
+ DATA_BLOB *preadbuf,
+ SMB_OFF_T startpos,
+ size_t smb_maxcnt)
+{
+ return NT_STATUS_RETRY;
+}
+
+NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
+ struct smb_request *smbreq,
+ files_struct *fsp,
+ uint64_t in_offset,
+ DATA_BLOB in_data,
+ bool write_through)
+{
+ return NT_STATUS_RETRY;
+}
+
void cancel_aio_by_fsp(files_struct *fsp)
{
}
int wait_for_aio_completion(files_struct *fsp)
{
- return ENOSYS;
+ return 0;
}
void smbd_aio_complete_mid(uint64_t mid);