s4/test-libnet: Helper func to initialize libnet_context
[Samba.git] / source3 / smbd / aio.c
bloba5a0e44738d4f54ee1217bfdaddf674c36d41e93
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 async_io read handling using POSIX async io.
5 Copyright (C) Jeremy Allison 2005.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "smbd/globals.h"
24 #if defined(WITH_AIO)
26 /* The signal we'll use to signify aio done. */
27 #ifndef RT_SIGNAL_AIO
28 #define RT_SIGNAL_AIO (SIGRTMIN+3)
29 #endif
31 #ifndef HAVE_STRUCT_SIGEVENT_SIGEV_VALUE_SIVAL_PTR
32 #ifdef HAVE_STRUCT_SIGEVENT_SIGEV_VALUE_SIGVAL_PTR
33 #define sival_int sigval_int
34 #define sival_ptr sigval_ptr
35 #endif
36 #endif
38 /****************************************************************************
39 The buffer we keep around whilst an aio request is in process.
40 *****************************************************************************/
42 struct aio_extra {
43 struct aio_extra *next, *prev;
44 SMB_STRUCT_AIOCB acb;
45 files_struct *fsp;
46 struct smb_request *smbreq;
47 DATA_BLOB outbuf;
48 struct lock_struct lock;
49 bool write_through;
50 int (*handle_completion)(struct aio_extra *ex, int errcode);
53 /****************************************************************************
54 Initialize the signal handler for aio read/write.
55 *****************************************************************************/
57 static void smbd_aio_signal_handler(struct tevent_context *ev_ctx,
58 struct tevent_signal *se,
59 int signum, int count,
60 void *_info, void *private_data)
62 siginfo_t *info = (siginfo_t *)_info;
63 struct aio_extra *aio_ex = (struct aio_extra *)
64 info->si_value.sival_ptr;
66 smbd_aio_complete_aio_ex(aio_ex);
70 static void initialize_async_io_handler(void)
72 if (aio_signal_event) {
73 return;
76 aio_signal_event = tevent_add_signal(smbd_event_context(),
77 smbd_event_context(),
78 RT_SIGNAL_AIO, SA_SIGINFO,
79 smbd_aio_signal_handler,
80 NULL);
81 if (!aio_signal_event) {
82 exit_server("Failed to setup RT_SIGNAL_AIO handler");
85 /* tevent supports 100 signal with SA_SIGINFO */
86 aio_pending_size = 100;
89 static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode);
90 static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode);
91 static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode);
92 static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode);
94 static int aio_extra_destructor(struct aio_extra *aio_ex)
96 DLIST_REMOVE(aio_list_head, aio_ex);
97 return 0;
100 /****************************************************************************
101 Create the extended aio struct we must keep around for the lifetime
102 of the aio call.
103 *****************************************************************************/
105 static struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx,
106 files_struct *fsp,
107 size_t buflen)
109 struct aio_extra *aio_ex = TALLOC_ZERO_P(mem_ctx, struct aio_extra);
111 if (!aio_ex) {
112 return NULL;
115 /* The output buffer stored in the aio_ex is the start of
116 the smb return buffer. The buffer used in the acb
117 is the start of the reply data portion of that buffer. */
119 if (buflen) {
120 aio_ex->outbuf = data_blob_talloc(aio_ex, NULL, buflen);
121 if (!aio_ex->outbuf.data) {
122 TALLOC_FREE(aio_ex);
123 return NULL;
126 DLIST_ADD(aio_list_head, aio_ex);
127 talloc_set_destructor(aio_ex, aio_extra_destructor);
128 aio_ex->fsp = fsp;
129 return aio_ex;
132 /****************************************************************************
133 Set up an aio request from a SMBreadX call.
134 *****************************************************************************/
136 NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
137 struct smb_request *smbreq,
138 files_struct *fsp, SMB_OFF_T startpos,
139 size_t smb_maxcnt)
141 struct aio_extra *aio_ex;
142 SMB_STRUCT_AIOCB *a;
143 size_t bufsize;
144 size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
145 int ret;
147 /* Ensure aio is initialized. */
148 initialize_async_io_handler();
150 if (fsp->base_fsp != NULL) {
151 /* No AIO on streams yet */
152 DEBUG(10, ("AIO on streams not yet supported\n"));
153 return NT_STATUS_RETRY;
156 if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
157 && !SMB_VFS_AIO_FORCE(fsp)) {
158 /* Too small a read for aio request. */
159 DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small "
160 "for minimum aio_read of %u\n",
161 (unsigned int)smb_maxcnt,
162 (unsigned int)min_aio_read_size ));
163 return NT_STATUS_RETRY;
166 /* Only do this on non-chained and non-chaining reads not using the
167 * write cache. */
168 if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) {
169 return NT_STATUS_RETRY;
172 if (outstanding_aio_calls >= aio_pending_size) {
173 DEBUG(10,("schedule_aio_read_and_X: Already have %d aio "
174 "activities outstanding.\n",
175 outstanding_aio_calls ));
176 return NT_STATUS_RETRY;
179 /* The following is safe from integer wrap as we've already checked
180 smb_maxcnt is 128k or less. Wct is 12 for read replies */
182 bufsize = smb_size + 12 * 2 + smb_maxcnt;
184 if ((aio_ex = create_aio_extra(NULL, fsp, bufsize)) == NULL) {
185 DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
186 return NT_STATUS_NO_MEMORY;
188 aio_ex->handle_completion = handle_aio_read_complete;
190 construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
191 srv_set_message((char *)aio_ex->outbuf.data, 12, 0, True);
192 SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
194 init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
195 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
196 &aio_ex->lock);
198 /* Take the lock until the AIO completes. */
199 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
200 TALLOC_FREE(aio_ex);
201 return NT_STATUS_FILE_LOCK_CONFLICT;
204 a = &aio_ex->acb;
206 /* Now set up the aio record for the read call. */
208 a->aio_fildes = fsp->fh->fd;
209 a->aio_buf = smb_buf(aio_ex->outbuf.data);
210 a->aio_nbytes = smb_maxcnt;
211 a->aio_offset = startpos;
212 a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
213 a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO;
214 a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
216 ret = SMB_VFS_AIO_READ(fsp, a);
217 if (ret == -1) {
218 DEBUG(0,("schedule_aio_read_and_X: aio_read failed. "
219 "Error %s\n", strerror(errno) ));
220 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
221 TALLOC_FREE(aio_ex);
222 return NT_STATUS_RETRY;
225 outstanding_aio_calls++;
226 aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
228 DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, "
229 "offset %.0f, len = %u (mid = %u)\n",
230 fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
231 (unsigned int)aio_ex->smbreq->mid ));
233 return NT_STATUS_OK;
236 /****************************************************************************
237 Set up an aio request from a SMBwriteX call.
238 *****************************************************************************/
240 NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
241 struct smb_request *smbreq,
242 files_struct *fsp, char *data,
243 SMB_OFF_T startpos,
244 size_t numtowrite)
246 struct aio_extra *aio_ex;
247 SMB_STRUCT_AIOCB *a;
248 size_t bufsize;
249 size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
250 int ret;
252 /* Ensure aio is initialized. */
253 initialize_async_io_handler();
255 if (fsp->base_fsp != NULL) {
256 /* No AIO on streams yet */
257 DEBUG(10, ("AIO on streams not yet supported\n"));
258 return NT_STATUS_RETRY;
261 if ((!min_aio_write_size || (numtowrite < min_aio_write_size))
262 && !SMB_VFS_AIO_FORCE(fsp)) {
263 /* Too small a write for aio request. */
264 DEBUG(10,("schedule_aio_write_and_X: write size (%u) too "
265 "small for minimum aio_write of %u\n",
266 (unsigned int)numtowrite,
267 (unsigned int)min_aio_write_size ));
268 return NT_STATUS_RETRY;
271 /* Only do this on non-chained and non-chaining writes not using the
272 * write cache. */
273 if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) {
274 return NT_STATUS_RETRY;
277 if (outstanding_aio_calls >= aio_pending_size) {
278 DEBUG(3,("schedule_aio_write_and_X: Already have %d aio "
279 "activities outstanding.\n",
280 outstanding_aio_calls ));
281 DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
282 "aio_write for file %s, offset %.0f, len = %u "
283 "(mid = %u)\n",
284 fsp_str_dbg(fsp), (double)startpos,
285 (unsigned int)numtowrite,
286 (unsigned int)smbreq->mid ));
287 return NT_STATUS_RETRY;
290 bufsize = smb_size + 6*2;
292 if (!(aio_ex = create_aio_extra(NULL, fsp, bufsize))) {
293 DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n"));
294 return NT_STATUS_NO_MEMORY;
296 aio_ex->handle_completion = handle_aio_write_complete;
297 aio_ex->write_through = BITSETW(smbreq->vwv+7,0);
299 construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
300 srv_set_message((char *)aio_ex->outbuf.data, 6, 0, True);
301 SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
303 init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
304 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
305 &aio_ex->lock);
307 /* Take the lock until the AIO completes. */
308 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
309 TALLOC_FREE(aio_ex);
310 return NT_STATUS_FILE_LOCK_CONFLICT;
313 a = &aio_ex->acb;
315 /* Now set up the aio record for the write call. */
317 a->aio_fildes = fsp->fh->fd;
318 a->aio_buf = data;
319 a->aio_nbytes = numtowrite;
320 a->aio_offset = startpos;
321 a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
322 a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO;
323 a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
325 ret = SMB_VFS_AIO_WRITE(fsp, a);
326 if (ret == -1) {
327 DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
328 "Error %s\n", strerror(errno) ));
329 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
330 TALLOC_FREE(aio_ex);
331 return NT_STATUS_RETRY;
334 outstanding_aio_calls++;
335 aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
337 /* This should actually be improved to span the write. */
338 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
339 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
341 if (!aio_ex->write_through && !lp_syncalways(SNUM(fsp->conn))
342 && fsp->aio_write_behind) {
343 /* Lie to the client and immediately claim we finished the
344 * write. */
345 SSVAL(aio_ex->outbuf.data,smb_vwv2,numtowrite);
346 SSVAL(aio_ex->outbuf.data,smb_vwv4,(numtowrite>>16)&1);
347 show_msg((char *)aio_ex->outbuf.data);
348 if (!srv_send_smb(smbd_server_fd(),(char *)aio_ex->outbuf.data,
349 true, aio_ex->smbreq->seqnum+1,
350 IS_CONN_ENCRYPTED(fsp->conn),
351 &aio_ex->smbreq->pcd)) {
352 exit_server_cleanly("handle_aio_write: srv_send_smb "
353 "failed.");
355 DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
356 "behind for file %s\n", fsp_str_dbg(fsp)));
359 DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file "
360 "%s, offset %.0f, len = %u (mid = %u) "
361 "outstanding_aio_calls = %d\n",
362 fsp_str_dbg(fsp), (double)startpos, (unsigned int)numtowrite,
363 (unsigned int)aio_ex->smbreq->mid, outstanding_aio_calls ));
365 return NT_STATUS_OK;
368 /****************************************************************************
369 Set up an aio request from a SMB2 read call.
370 *****************************************************************************/
372 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
373 struct smb_request *smbreq,
374 files_struct *fsp,
375 char *inbuf,
376 SMB_OFF_T startpos,
377 size_t smb_maxcnt)
379 struct aio_extra *aio_ex;
380 SMB_STRUCT_AIOCB *a;
381 size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
382 int ret;
384 /* Ensure aio is initialized. */
385 initialize_async_io_handler();
387 if (fsp->base_fsp != NULL) {
388 /* No AIO on streams yet */
389 DEBUG(10, ("AIO on streams not yet supported\n"));
390 return NT_STATUS_RETRY;
393 if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
394 && !SMB_VFS_AIO_FORCE(fsp)) {
395 /* Too small a read for aio request. */
396 DEBUG(10,("smb2: read size (%u) too small "
397 "for minimum aio_read of %u\n",
398 (unsigned int)smb_maxcnt,
399 (unsigned int)min_aio_read_size ));
400 return NT_STATUS_RETRY;
403 /* Only do this on reads not using the write cache. */
404 if (lp_write_cache_size(SNUM(conn)) != 0) {
405 return NT_STATUS_RETRY;
408 if (outstanding_aio_calls >= aio_pending_size) {
409 DEBUG(10,("smb2: Already have %d aio "
410 "activities outstanding.\n",
411 outstanding_aio_calls ));
412 return NT_STATUS_RETRY;
415 if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
416 return NT_STATUS_NO_MEMORY;
418 aio_ex->handle_completion = handle_aio_smb2_read_complete;
420 init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
421 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
422 &aio_ex->lock);
424 /* Take the lock until the AIO completes. */
425 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
426 TALLOC_FREE(aio_ex);
427 return NT_STATUS_FILE_LOCK_CONFLICT;
430 a = &aio_ex->acb;
432 /* Now set up the aio record for the read call. */
434 a->aio_fildes = fsp->fh->fd;
435 a->aio_buf = inbuf;
436 a->aio_nbytes = smb_maxcnt;
437 a->aio_offset = startpos;
438 a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
439 a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO;
440 a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
442 ret = SMB_VFS_AIO_READ(fsp, a);
443 if (ret == -1) {
444 DEBUG(0,("smb2: aio_read failed. "
445 "Error %s\n", strerror(errno) ));
446 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
447 TALLOC_FREE(aio_ex);
448 return NT_STATUS_RETRY;
451 outstanding_aio_calls++;
452 /* We don't need talloc_move here as both aio_ex and
453 * smbreq are children of smbreq->smb2req. */
454 aio_ex->smbreq = smbreq;
456 DEBUG(10,("smb2: scheduled aio_read for file %s, "
457 "offset %.0f, len = %u (mid = %u)\n",
458 fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
459 (unsigned int)aio_ex->smbreq->mid ));
461 return NT_STATUS_OK;
464 /****************************************************************************
465 Set up an aio request from a SMB2write call.
466 *****************************************************************************/
468 NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
469 struct smb_request *smbreq,
470 files_struct *fsp,
471 uint64_t in_offset,
472 DATA_BLOB in_data,
473 bool write_through)
475 struct aio_extra *aio_ex = NULL;
476 SMB_STRUCT_AIOCB *a = NULL;
477 size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
478 int ret;
480 /* Ensure aio is initialized. */
481 initialize_async_io_handler();
483 if (fsp->base_fsp != NULL) {
484 /* No AIO on streams yet */
485 DEBUG(10, ("AIO on streams not yet supported\n"));
486 return NT_STATUS_RETRY;
489 if ((!min_aio_write_size || (in_data.length < min_aio_write_size))
490 && !SMB_VFS_AIO_FORCE(fsp)) {
491 /* Too small a write for aio request. */
492 DEBUG(10,("smb2: write size (%u) too "
493 "small for minimum aio_write of %u\n",
494 (unsigned int)in_data.length,
495 (unsigned int)min_aio_write_size ));
496 return NT_STATUS_RETRY;
499 /* Only do this on writes not using the write cache. */
500 if (lp_write_cache_size(SNUM(conn)) != 0) {
501 return NT_STATUS_RETRY;
504 if (outstanding_aio_calls >= aio_pending_size) {
505 DEBUG(3,("smb2: Already have %d aio "
506 "activities outstanding.\n",
507 outstanding_aio_calls ));
508 return NT_STATUS_RETRY;
511 if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
512 return NT_STATUS_NO_MEMORY;
515 aio_ex->handle_completion = handle_aio_smb2_write_complete;
516 aio_ex->write_through = write_through;
518 init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
519 in_offset, (uint64_t)in_data.length, WRITE_LOCK,
520 &aio_ex->lock);
522 /* Take the lock until the AIO completes. */
523 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
524 TALLOC_FREE(aio_ex);
525 return NT_STATUS_FILE_LOCK_CONFLICT;
528 a = &aio_ex->acb;
530 /* Now set up the aio record for the write call. */
532 a->aio_fildes = fsp->fh->fd;
533 a->aio_buf = in_data.data;
534 a->aio_nbytes = in_data.length;
535 a->aio_offset = in_offset;
536 a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
537 a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO;
538 a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
540 ret = SMB_VFS_AIO_WRITE(fsp, a);
541 if (ret == -1) {
542 DEBUG(3,("smb2: aio_write failed. "
543 "Error %s\n", strerror(errno) ));
544 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
545 TALLOC_FREE(aio_ex);
546 return NT_STATUS_RETRY;
549 outstanding_aio_calls++;
550 /* We don't need talloc_move here as both aio_ex and
551 * smbreq are children of smbreq->smb2req. */
552 aio_ex->smbreq = smbreq;
554 /* This should actually be improved to span the write. */
555 contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
556 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
559 * We don't want to do write behind due to ownership
560 * issues of the request structs. Maybe add it if I
561 * figure those out. JRA.
564 DEBUG(10,("smb2: scheduled aio_write for file "
565 "%s, offset %.0f, len = %u (mid = %u) "
566 "outstanding_aio_calls = %d\n",
567 fsp_str_dbg(fsp),
568 (double)in_offset,
569 (unsigned int)in_data.length,
570 (unsigned int)aio_ex->smbreq->mid,
571 outstanding_aio_calls ));
573 return NT_STATUS_OK;
576 /****************************************************************************
577 Complete the read and return the data or error back to the client.
578 Returns errno or zero if all ok.
579 *****************************************************************************/
581 static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
583 int outsize;
584 char *outbuf = (char *)aio_ex->outbuf.data;
585 char *data = smb_buf(outbuf);
586 ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
588 if (nread < 0) {
589 /* We're relying here on the fact that if the fd is
590 closed then the aio will complete and aio_return
591 will return an error. Hopefully this is
592 true.... JRA. */
594 DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d. "
595 "Error = %s\n",
596 fsp_str_dbg(aio_ex->fsp), (int)nread, strerror(errcode)));
598 ERROR_NT(map_nt_error_from_unix(errcode));
599 outsize = srv_set_message(outbuf,0,0,true);
600 } else {
601 outsize = srv_set_message(outbuf,12,nread,False);
602 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */
603 SSVAL(outbuf,smb_vwv5,nread);
604 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
605 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
606 SSVAL(smb_buf(outbuf),-2,nread);
608 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
609 aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
611 DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
612 "nread=%d\n",
613 fsp_str_dbg(aio_ex->fsp),
614 (int)aio_ex->acb.aio_nbytes, (int)nread ) );
617 smb_setlen(outbuf,outsize - 4);
618 show_msg(outbuf);
619 if (!srv_send_smb(smbd_server_fd(),outbuf,
620 true, aio_ex->smbreq->seqnum+1,
621 IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) {
622 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
623 "failed.");
626 DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed "
627 "for file %s, offset %.0f, len = %u\n",
628 fsp_str_dbg(aio_ex->fsp), (double)aio_ex->acb.aio_offset,
629 (unsigned int)nread ));
631 return errcode;
634 /****************************************************************************
635 Complete the write and return the data or error back to the client.
636 Returns error code or zero if all ok.
637 *****************************************************************************/
639 static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
641 files_struct *fsp = aio_ex->fsp;
642 char *outbuf = (char *)aio_ex->outbuf.data;
643 ssize_t numtowrite = aio_ex->acb.aio_nbytes;
644 ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
646 if (fsp->aio_write_behind) {
647 if (nwritten != numtowrite) {
648 if (nwritten == -1) {
649 DEBUG(5,("handle_aio_write_complete: "
650 "aio_write_behind failed ! File %s "
651 "is corrupt ! Error %s\n",
652 fsp_str_dbg(fsp), strerror(errcode)));
653 } else {
654 DEBUG(0,("handle_aio_write_complete: "
655 "aio_write_behind failed ! File %s "
656 "is corrupt ! Wanted %u bytes but "
657 "only wrote %d\n", fsp_str_dbg(fsp),
658 (unsigned int)numtowrite,
659 (int)nwritten ));
660 errcode = EIO;
662 } else {
663 DEBUG(10,("handle_aio_write_complete: "
664 "aio_write_behind completed for file %s\n",
665 fsp_str_dbg(fsp)));
667 /* TODO: should no return 0 in case of an error !!! */
668 return 0;
671 /* We don't need outsize or set_message here as we've already set the
672 fixed size length when we set up the aio call. */
674 if(nwritten == -1) {
675 DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. "
676 "nwritten == %d. Error = %s\n",
677 fsp_str_dbg(fsp), (unsigned int)numtowrite,
678 (int)nwritten, strerror(errcode) ));
680 ERROR_NT(map_nt_error_from_unix(errcode));
681 srv_set_message(outbuf,0,0,true);
682 } else {
683 NTSTATUS status;
685 SSVAL(outbuf,smb_vwv2,nwritten);
686 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
687 if (nwritten < (ssize_t)numtowrite) {
688 SCVAL(outbuf,smb_rcls,ERRHRD);
689 SSVAL(outbuf,smb_err,ERRdiskfull);
692 DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n",
693 fsp->fnum, (int)numtowrite, (int)nwritten));
694 status = sync_file(fsp->conn,fsp, aio_ex->write_through);
695 if (!NT_STATUS_IS_OK(status)) {
696 errcode = errno;
697 ERROR_BOTH(map_nt_error_from_unix(errcode),
698 ERRHRD, ERRdiskfull);
699 srv_set_message(outbuf,0,0,true);
700 DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
701 fsp_str_dbg(fsp), nt_errstr(status)));
704 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten;
707 show_msg(outbuf);
708 if (!srv_send_smb(smbd_server_fd(),outbuf,
709 true, aio_ex->smbreq->seqnum+1,
710 IS_CONN_ENCRYPTED(fsp->conn),
711 NULL)) {
712 exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
715 DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
716 "for file %s, offset %.0f, requested %u, written = %u\n",
717 fsp_str_dbg(fsp), (double)aio_ex->acb.aio_offset,
718 (unsigned int)numtowrite, (unsigned int)nwritten ));
720 return errcode;
723 /****************************************************************************
724 Complete the read and return the data or error back to the client.
725 Returns errno or zero if all ok.
726 *****************************************************************************/
728 static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode)
730 NTSTATUS status;
731 struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
732 ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
734 /* Common error or success code processing for async or sync
735 read returns. */
737 status = smb2_read_complete(subreq, nread, errcode);
739 if (nread > 0) {
740 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
741 aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
744 DEBUG(10,("smb2: scheduled aio_read completed "
745 "for file %s, offset %.0f, len = %u "
746 "(errcode = %d, NTSTATUS = %s)\n",
747 fsp_str_dbg(aio_ex->fsp),
748 (double)aio_ex->acb.aio_offset,
749 (unsigned int)nread,
750 errcode,
751 nt_errstr(status) ));
753 if (!NT_STATUS_IS_OK(status)) {
754 tevent_req_nterror(subreq, status);
757 tevent_req_done(subreq);
758 return errcode;
761 /****************************************************************************
762 Complete the SMB2 write and return the data or error back to the client.
763 Returns error code or zero if all ok.
764 *****************************************************************************/
766 static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode)
768 files_struct *fsp = aio_ex->fsp;
769 ssize_t numtowrite = aio_ex->acb.aio_nbytes;
770 ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
771 struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
772 NTSTATUS status;
774 status = smb2_write_complete(subreq, nwritten, errcode);
776 DEBUG(10,("smb2: scheduled aio_write completed "
777 "for file %s, offset %.0f, requested %u, "
778 "written = %u (errcode = %d, NTSTATUS = %s)\n",
779 fsp_str_dbg(fsp),
780 (double)aio_ex->acb.aio_offset,
781 (unsigned int)numtowrite,
782 (unsigned int)nwritten,
783 errcode,
784 nt_errstr(status) ));
786 if (!NT_STATUS_IS_OK(status)) {
787 tevent_req_nterror(subreq, status);
790 tevent_req_done(subreq);
791 return errcode;
794 /****************************************************************************
795 Handle any aio completion. Returns True if finished (and sets *perr if err
796 was non-zero), False if not.
797 *****************************************************************************/
799 static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr)
801 files_struct *fsp = NULL;
802 int err;
804 if(!aio_ex) {
805 DEBUG(3, ("handle_aio_completed: Non-existing aio_ex passed\n"));
806 return false;
809 fsp = aio_ex->fsp;
811 /* Ensure the operation has really completed. */
812 err = SMB_VFS_AIO_ERROR(fsp, &aio_ex->acb);
813 if (err == EINPROGRESS) {
814 DEBUG(10,( "handle_aio_completed: operation mid %llu still in "
815 "process for file %s\n",
816 (unsigned long long)aio_ex->smbreq->mid,
817 fsp_str_dbg(aio_ex->fsp)));
818 return False;
821 /* Unlock now we're done. */
822 SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
824 if (err == ECANCELED) {
825 /* If error is ECANCELED then don't return anything to the
826 * client. */
827 DEBUG(10,( "handle_aio_completed: operation mid %llu"
828 " canceled\n",
829 (unsigned long long)aio_ex->smbreq->mid));
830 return True;
833 err = aio_ex->handle_completion(aio_ex, err);
834 if (err) {
835 *perr = err; /* Only save non-zero errors. */
838 return True;
841 /****************************************************************************
842 Handle any aio completion inline.
843 *****************************************************************************/
845 void smbd_aio_complete_aio_ex(struct aio_extra *aio_ex)
847 files_struct *fsp = NULL;
848 int ret = 0;
850 outstanding_aio_calls--;
852 DEBUG(10,("smbd_aio_complete_mid: mid[%llu]\n",
853 (unsigned long long)aio_ex->smbreq->mid));
855 fsp = aio_ex->fsp;
856 if (fsp == NULL) {
857 /* file was closed whilst I/O was outstanding. Just
858 * ignore. */
859 DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
860 "aio outstanding (mid[%llu]).\n",
861 (unsigned long long)aio_ex->smbreq->mid));
862 return;
865 if (!handle_aio_completed(aio_ex, &ret)) {
866 return;
869 TALLOC_FREE(aio_ex);
872 /****************************************************************************
873 We're doing write behind and the client closed the file. Wait up to 30
874 seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes
875 completed, errno to return if not.
876 *****************************************************************************/
878 #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29
880 int wait_for_aio_completion(files_struct *fsp)
882 struct aio_extra *aio_ex;
883 const SMB_STRUCT_AIOCB **aiocb_list;
884 int aio_completion_count = 0;
885 time_t start_time = time(NULL);
886 int seconds_left;
888 for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT;
889 seconds_left >= 0;) {
890 int err = 0;
891 int i;
892 struct timespec ts;
894 aio_completion_count = 0;
895 for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
896 if (aio_ex->fsp == fsp) {
897 aio_completion_count++;
901 if (!aio_completion_count) {
902 return 0;
905 DEBUG(3,("wait_for_aio_completion: waiting for %d aio events "
906 "to complete.\n", aio_completion_count ));
908 aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *,
909 aio_completion_count);
910 if (!aiocb_list) {
911 return ENOMEM;
914 for( i = 0, aio_ex = aio_list_head;
915 aio_ex;
916 aio_ex = aio_ex->next) {
917 if (aio_ex->fsp == fsp) {
918 aiocb_list[i++] = &aio_ex->acb;
922 /* Now wait up to seconds_left for completion. */
923 ts.tv_sec = seconds_left;
924 ts.tv_nsec = 0;
926 DEBUG(10,("wait_for_aio_completion: %d events, doing a wait "
927 "of %d seconds.\n",
928 aio_completion_count, seconds_left ));
930 err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list,
931 aio_completion_count, &ts);
933 DEBUG(10,("wait_for_aio_completion: returned err = %d, "
934 "errno = %s\n", err, strerror(errno) ));
936 if (err == -1 && errno == EAGAIN) {
937 DEBUG(0,("wait_for_aio_completion: aio_suspend timed "
938 "out waiting for %d events after a wait of "
939 "%d seconds\n", aio_completion_count,
940 seconds_left));
941 /* Timeout. */
942 cancel_aio_by_fsp(fsp);
943 SAFE_FREE(aiocb_list);
944 return EIO;
947 /* One or more events might have completed - process them if
948 * so. */
949 for( i = 0; i < aio_completion_count; i++) {
950 aio_ex = (struct aio_extra *)aiocb_list[i]->aio_sigevent.sigev_value.sival_ptr;
952 if (!handle_aio_completed(aio_ex, &err)) {
953 continue;
955 TALLOC_FREE(aio_ex);
958 SAFE_FREE(aiocb_list);
959 seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT
960 - (time(NULL) - start_time);
963 /* We timed out - we don't know why. Return ret if already an error,
964 * else EIO. */
965 DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting "
966 "for %d events\n",
967 aio_completion_count));
969 return EIO;
972 /****************************************************************************
973 Cancel any outstanding aio requests. The client doesn't care about the reply.
974 *****************************************************************************/
976 void cancel_aio_by_fsp(files_struct *fsp)
978 struct aio_extra *aio_ex;
980 for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
981 if (aio_ex->fsp == fsp) {
982 /* Unlock now we're done. */
983 SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
985 /* Don't delete the aio_extra record as we may have
986 completed and don't yet know it. Just do the
987 aio_cancel call and return. */
988 SMB_VFS_AIO_CANCEL(fsp, &aio_ex->acb);
989 aio_ex->fsp = NULL; /* fsp will be closed when we
990 * return. */
995 #else
996 NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
997 struct smb_request *smbreq,
998 files_struct *fsp, SMB_OFF_T startpos,
999 size_t smb_maxcnt)
1001 return NT_STATUS_RETRY;
1004 NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
1005 struct smb_request *smbreq,
1006 files_struct *fsp, char *data,
1007 SMB_OFF_T startpos,
1008 size_t numtowrite)
1010 return NT_STATUS_RETRY;
1013 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
1014 struct smb_request *smbreq,
1015 files_struct *fsp,
1016 char *inbuf,
1017 SMB_OFF_T startpos,
1018 size_t smb_maxcnt)
1020 return NT_STATUS_RETRY;
1023 NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
1024 struct smb_request *smbreq,
1025 files_struct *fsp,
1026 uint64_t in_offset,
1027 DATA_BLOB in_data,
1028 bool write_through)
1030 return NT_STATUS_RETRY;
1033 void cancel_aio_by_fsp(files_struct *fsp)
1037 int wait_for_aio_completion(files_struct *fsp)
1039 return 0;
1042 void smbd_aio_complete_mid(uint64_t mid);
1044 #endif