2 Unix SMB/Netbios implementation.
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/>.
22 #include "smbd/smbd.h"
23 #include "smbd/globals.h"
24 #include "../lib/util/tevent_ntstatus.h"
28 /* The signal we'll use to signify aio done. */
30 #define RT_SIGNAL_AIO (SIGRTMIN+3)
33 #ifndef HAVE_STRUCT_SIGEVENT_SIGEV_VALUE_SIVAL_PTR
34 #ifdef HAVE_STRUCT_SIGEVENT_SIGEV_VALUE_SIGVAL_PTR
35 #define sival_int sigval_int
36 #define sival_ptr sigval_ptr
40 /****************************************************************************
41 The buffer we keep around whilst an aio request is in process.
42 *****************************************************************************/
45 struct aio_extra
*next
, *prev
;
48 struct smb_request
*smbreq
;
50 struct lock_struct lock
;
52 int (*handle_completion
)(struct aio_extra
*ex
, int errcode
);
55 /****************************************************************************
56 Accessor function to return write_through state.
57 *****************************************************************************/
59 bool aio_write_through_requested(struct aio_extra
*aio_ex
)
61 return aio_ex
->write_through
;
64 /****************************************************************************
65 Initialize the signal handler for aio read/write.
66 *****************************************************************************/
68 static void smbd_aio_signal_handler(struct tevent_context
*ev_ctx
,
69 struct tevent_signal
*se
,
70 int signum
, int count
,
71 void *_info
, void *private_data
)
73 siginfo_t
*info
= (siginfo_t
*)_info
;
74 struct aio_extra
*aio_ex
= (struct aio_extra
*)
75 info
->si_value
.sival_ptr
;
77 smbd_aio_complete_aio_ex(aio_ex
);
82 bool initialize_async_io_handler(void)
84 static bool tried_signal_setup
= false;
86 if (aio_signal_event
) {
89 if (tried_signal_setup
) {
92 tried_signal_setup
= true;
94 aio_signal_event
= tevent_add_signal(server_event_context(),
95 server_event_context(),
96 RT_SIGNAL_AIO
, SA_SIGINFO
,
97 smbd_aio_signal_handler
,
99 if (!aio_signal_event
) {
100 DEBUG(10, ("Failed to setup RT_SIGNAL_AIO handler\n"));
106 static int handle_aio_read_complete(struct aio_extra
*aio_ex
, int errcode
);
107 static int handle_aio_write_complete(struct aio_extra
*aio_ex
, int errcode
);
108 static int handle_aio_smb2_read_complete(struct aio_extra
*aio_ex
, int errcode
);
109 static int handle_aio_smb2_write_complete(struct aio_extra
*aio_ex
, int errcode
);
111 static int aio_extra_destructor(struct aio_extra
*aio_ex
)
113 DLIST_REMOVE(aio_list_head
, aio_ex
);
114 outstanding_aio_calls
--;
118 /****************************************************************************
119 Create the extended aio struct we must keep around for the lifetime
121 *****************************************************************************/
123 static struct aio_extra
*create_aio_extra(TALLOC_CTX
*mem_ctx
,
127 struct aio_extra
*aio_ex
= talloc_zero(mem_ctx
, struct aio_extra
);
133 /* The output buffer stored in the aio_ex is the start of
134 the smb return buffer. The buffer used in the acb
135 is the start of the reply data portion of that buffer. */
138 aio_ex
->outbuf
= data_blob_talloc(aio_ex
, NULL
, buflen
);
139 if (!aio_ex
->outbuf
.data
) {
144 DLIST_ADD(aio_list_head
, aio_ex
);
145 talloc_set_destructor(aio_ex
, aio_extra_destructor
);
147 outstanding_aio_calls
++;
151 static void aio_pread_smb1_done(struct tevent_req
*req
);
153 /****************************************************************************
154 Set up an aio request from a SMBreadX call.
155 *****************************************************************************/
157 NTSTATUS
schedule_aio_read_and_X(connection_struct
*conn
,
158 struct smb_request
*smbreq
,
159 files_struct
*fsp
, off_t startpos
,
162 struct aio_extra
*aio_ex
;
165 size_t min_aio_read_size
= lp_aio_read_size(SNUM(conn
));
166 struct tevent_req
*req
;
168 if (fsp
->base_fsp
!= NULL
) {
169 /* No AIO on streams yet */
170 DEBUG(10, ("AIO on streams not yet supported\n"));
171 return NT_STATUS_RETRY
;
174 if ((!min_aio_read_size
|| (smb_maxcnt
< min_aio_read_size
))
175 && !SMB_VFS_AIO_FORCE(fsp
)) {
176 /* Too small a read for aio request. */
177 DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small "
178 "for minimum aio_read of %u\n",
179 (unsigned int)smb_maxcnt
,
180 (unsigned int)min_aio_read_size
));
181 return NT_STATUS_RETRY
;
184 /* Only do this on non-chained and non-chaining reads not using the
186 if (req_is_in_chain(smbreq
) || (lp_write_cache_size(SNUM(conn
)) != 0)) {
187 return NT_STATUS_RETRY
;
190 if (outstanding_aio_calls
>= aio_pending_size
) {
191 DEBUG(10,("schedule_aio_read_and_X: Already have %d aio "
192 "activities outstanding.\n",
193 outstanding_aio_calls
));
194 return NT_STATUS_RETRY
;
197 /* The following is safe from integer wrap as we've already checked
198 smb_maxcnt is 128k or less. Wct is 12 for read replies */
200 bufsize
= smb_size
+ 12 * 2 + smb_maxcnt
;
202 if ((aio_ex
= create_aio_extra(NULL
, fsp
, bufsize
)) == NULL
) {
203 DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
204 return NT_STATUS_NO_MEMORY
;
206 aio_ex
->handle_completion
= handle_aio_read_complete
;
208 construct_reply_common_req(smbreq
, (char *)aio_ex
->outbuf
.data
);
209 srv_set_message((char *)aio_ex
->outbuf
.data
, 12, 0, True
);
210 SCVAL(aio_ex
->outbuf
.data
,smb_vwv0
,0xFF); /* Never a chained reply. */
212 init_strict_lock_struct(fsp
, (uint64_t)smbreq
->smbpid
,
213 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
216 /* Take the lock until the AIO completes. */
217 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &aio_ex
->lock
)) {
219 return NT_STATUS_FILE_LOCK_CONFLICT
;
224 /* Now set up the aio record for the read call. */
226 a
->aio_fildes
= fsp
->fh
->fd
;
227 a
->aio_buf
= smb_buf(aio_ex
->outbuf
.data
);
228 a
->aio_nbytes
= smb_maxcnt
;
229 a
->aio_offset
= startpos
;
230 a
->aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
231 a
->aio_sigevent
.sigev_signo
= RT_SIGNAL_AIO
;
232 a
->aio_sigevent
.sigev_value
.sival_ptr
= aio_ex
;
234 req
= SMB_VFS_PREAD_SEND(aio_ex
, fsp
->conn
->sconn
->ev_ctx
,
235 fsp
, smb_buf(aio_ex
->outbuf
.data
),
236 smb_maxcnt
, startpos
);
238 DEBUG(0,("schedule_aio_read_and_X: aio_read failed. "
239 "Error %s\n", strerror(errno
) ));
240 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &aio_ex
->lock
);
242 return NT_STATUS_RETRY
;
244 tevent_req_set_callback(req
, aio_pread_smb1_done
, aio_ex
);
246 aio_ex
->smbreq
= talloc_move(aio_ex
, &smbreq
);
248 DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, "
249 "offset %.0f, len = %u (mid = %u)\n",
250 fsp_str_dbg(fsp
), (double)startpos
, (unsigned int)smb_maxcnt
,
251 (unsigned int)aio_ex
->smbreq
->mid
));
256 static void aio_pread_smb1_done(struct tevent_req
*req
)
258 struct aio_extra
*aio_ex
= tevent_req_callback_data(
259 req
, struct aio_extra
);
260 files_struct
*fsp
= aio_ex
->fsp
;
262 char *outbuf
= (char *)aio_ex
->outbuf
.data
;
263 char *data
= smb_buf(outbuf
);
267 nread
= SMB_VFS_PREAD_RECV(req
, &err
);
270 DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread
,
271 (nread
== -1) ? strerror(err
) : "no error"));
274 DEBUG( 3, ("aio_pread_smb1_done: file closed whilst "
275 "aio outstanding (mid[%llu]).\n",
276 (unsigned long long)aio_ex
->smbreq
->mid
));
281 /* Unlock now we're done. */
282 SMB_VFS_STRICT_UNLOCK(fsp
->conn
, fsp
, &aio_ex
->lock
);
285 DEBUG( 3, ("handle_aio_read_complete: file %s nread == %d. "
286 "Error = %s\n", fsp_str_dbg(fsp
), (int)nread
,
289 ERROR_NT(map_nt_error_from_unix(err
));
290 outsize
= srv_set_message(outbuf
,0,0,true);
292 outsize
= srv_set_message(outbuf
, 12, nread
, False
);
293 SSVAL(outbuf
,smb_vwv2
, 0xFFFF); /* Remaining - must be * -1. */
294 SSVAL(outbuf
,smb_vwv5
, nread
);
295 SSVAL(outbuf
,smb_vwv6
, smb_offset(data
,outbuf
));
296 SSVAL(outbuf
,smb_vwv7
, ((nread
>> 16) & 1));
297 SSVAL(smb_buf(outbuf
), -2, nread
);
299 aio_ex
->fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nread
;
300 aio_ex
->fsp
->fh
->position_information
= aio_ex
->fsp
->fh
->pos
;
302 DEBUG( 3, ("handle_aio_read_complete file %s max=%d "
303 "nread=%d\n", fsp_str_dbg(fsp
),
304 (int)aio_ex
->acb
.aio_nbytes
, (int)nread
) );
307 smb_setlen(outbuf
, outsize
- 4);
309 if (!srv_send_smb(aio_ex
->smbreq
->sconn
, outbuf
,
310 true, aio_ex
->smbreq
->seqnum
+1,
311 IS_CONN_ENCRYPTED(fsp
->conn
), NULL
)) {
312 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
316 DEBUG(10, ("handle_aio_read_complete: scheduled aio_read completed "
317 "for file %s, offset %.0f, len = %u\n",
318 fsp_str_dbg(fsp
), (double)aio_ex
->acb
.aio_offset
,
319 (unsigned int)nread
));
324 /****************************************************************************
325 Set up an aio request from a SMBwriteX call.
326 *****************************************************************************/
328 NTSTATUS
schedule_aio_write_and_X(connection_struct
*conn
,
329 struct smb_request
*smbreq
,
330 files_struct
*fsp
, const char *data
,
334 struct aio_extra
*aio_ex
;
337 size_t min_aio_write_size
= lp_aio_write_size(SNUM(conn
));
340 if (fsp
->base_fsp
!= NULL
) {
341 /* No AIO on streams yet */
342 DEBUG(10, ("AIO on streams not yet supported\n"));
343 return NT_STATUS_RETRY
;
346 if ((!min_aio_write_size
|| (numtowrite
< min_aio_write_size
))
347 && !SMB_VFS_AIO_FORCE(fsp
)) {
348 /* Too small a write for aio request. */
349 DEBUG(10,("schedule_aio_write_and_X: write size (%u) too "
350 "small for minimum aio_write of %u\n",
351 (unsigned int)numtowrite
,
352 (unsigned int)min_aio_write_size
));
353 return NT_STATUS_RETRY
;
356 /* Only do this on non-chained and non-chaining writes not using the
358 if (req_is_in_chain(smbreq
) || (lp_write_cache_size(SNUM(conn
)) != 0)) {
359 return NT_STATUS_RETRY
;
362 if (outstanding_aio_calls
>= aio_pending_size
) {
363 DEBUG(3,("schedule_aio_write_and_X: Already have %d aio "
364 "activities outstanding.\n",
365 outstanding_aio_calls
));
366 DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
367 "aio_write for file %s, offset %.0f, len = %u "
369 fsp_str_dbg(fsp
), (double)startpos
,
370 (unsigned int)numtowrite
,
371 (unsigned int)smbreq
->mid
));
372 return NT_STATUS_RETRY
;
375 bufsize
= smb_size
+ 6*2;
377 if (!(aio_ex
= create_aio_extra(NULL
, fsp
, bufsize
))) {
378 DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n"));
379 return NT_STATUS_NO_MEMORY
;
381 aio_ex
->handle_completion
= handle_aio_write_complete
;
382 aio_ex
->write_through
= BITSETW(smbreq
->vwv
+7,0);
384 construct_reply_common_req(smbreq
, (char *)aio_ex
->outbuf
.data
);
385 srv_set_message((char *)aio_ex
->outbuf
.data
, 6, 0, True
);
386 SCVAL(aio_ex
->outbuf
.data
,smb_vwv0
,0xFF); /* Never a chained reply. */
388 init_strict_lock_struct(fsp
, (uint64_t)smbreq
->smbpid
,
389 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
392 /* Take the lock until the AIO completes. */
393 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &aio_ex
->lock
)) {
395 return NT_STATUS_FILE_LOCK_CONFLICT
;
400 /* Now set up the aio record for the write call. */
402 a
->aio_fildes
= fsp
->fh
->fd
;
403 a
->aio_buf
= discard_const_p(char, data
);
404 a
->aio_nbytes
= numtowrite
;
405 a
->aio_offset
= startpos
;
406 a
->aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
407 a
->aio_sigevent
.sigev_signo
= RT_SIGNAL_AIO
;
408 a
->aio_sigevent
.sigev_value
.sival_ptr
= aio_ex
;
410 ret
= SMB_VFS_AIO_WRITE(fsp
, a
);
412 DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
413 "Error %s\n", strerror(errno
) ));
414 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &aio_ex
->lock
);
416 return NT_STATUS_RETRY
;
419 aio_ex
->smbreq
= talloc_move(aio_ex
, &smbreq
);
421 /* This should actually be improved to span the write. */
422 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_WRITE
);
423 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_WRITE
);
425 if (!aio_ex
->write_through
&& !lp_syncalways(SNUM(fsp
->conn
))
426 && fsp
->aio_write_behind
) {
427 /* Lie to the client and immediately claim we finished the
429 SSVAL(aio_ex
->outbuf
.data
,smb_vwv2
,numtowrite
);
430 SSVAL(aio_ex
->outbuf
.data
,smb_vwv4
,(numtowrite
>>16)&1);
431 show_msg((char *)aio_ex
->outbuf
.data
);
432 if (!srv_send_smb(aio_ex
->smbreq
->sconn
,
433 (char *)aio_ex
->outbuf
.data
,
434 true, aio_ex
->smbreq
->seqnum
+1,
435 IS_CONN_ENCRYPTED(fsp
->conn
),
436 &aio_ex
->smbreq
->pcd
)) {
437 exit_server_cleanly("schedule_aio_write_and_X: "
438 "srv_send_smb failed.");
440 DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
441 "behind for file %s\n", fsp_str_dbg(fsp
)));
444 DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file "
445 "%s, offset %.0f, len = %u (mid = %u) "
446 "outstanding_aio_calls = %d\n",
447 fsp_str_dbg(fsp
), (double)startpos
, (unsigned int)numtowrite
,
448 (unsigned int)aio_ex
->smbreq
->mid
, outstanding_aio_calls
));
453 bool cancel_smb2_aio(struct smb_request
*smbreq
)
455 struct smbd_smb2_request
*smb2req
= smbreq
->smb2req
;
456 struct aio_extra
*aio_ex
= NULL
;
460 aio_ex
= talloc_get_type(smbreq
->async_priv
,
464 if (aio_ex
== NULL
) {
468 if (aio_ex
->fsp
== NULL
) {
472 ret
= SMB_VFS_AIO_CANCEL(aio_ex
->fsp
, &aio_ex
->acb
);
473 if (ret
!= AIO_CANCELED
) {
480 /****************************************************************************
481 Set up an aio request from a SMB2 read call.
482 *****************************************************************************/
484 NTSTATUS
schedule_smb2_aio_read(connection_struct
*conn
,
485 struct smb_request
*smbreq
,
492 struct aio_extra
*aio_ex
;
494 size_t min_aio_read_size
= lp_aio_read_size(SNUM(conn
));
497 if (fsp
->base_fsp
!= NULL
) {
498 /* No AIO on streams yet */
499 DEBUG(10, ("AIO on streams not yet supported\n"));
500 return NT_STATUS_RETRY
;
503 if ((!min_aio_read_size
|| (smb_maxcnt
< min_aio_read_size
))
504 && !SMB_VFS_AIO_FORCE(fsp
)) {
505 /* Too small a read for aio request. */
506 DEBUG(10,("smb2: read size (%u) too small "
507 "for minimum aio_read of %u\n",
508 (unsigned int)smb_maxcnt
,
509 (unsigned int)min_aio_read_size
));
510 return NT_STATUS_RETRY
;
513 /* Only do this on reads not using the write cache. */
514 if (lp_write_cache_size(SNUM(conn
)) != 0) {
515 return NT_STATUS_RETRY
;
518 if (outstanding_aio_calls
>= aio_pending_size
) {
519 DEBUG(10,("smb2: Already have %d aio "
520 "activities outstanding.\n",
521 outstanding_aio_calls
));
522 return NT_STATUS_RETRY
;
525 /* Create the out buffer. */
526 *preadbuf
= data_blob_talloc(ctx
, NULL
, smb_maxcnt
);
527 if (preadbuf
->data
== NULL
) {
528 return NT_STATUS_NO_MEMORY
;
531 if (!(aio_ex
= create_aio_extra(smbreq
->smb2req
, fsp
, 0))) {
532 return NT_STATUS_NO_MEMORY
;
534 aio_ex
->handle_completion
= handle_aio_smb2_read_complete
;
536 init_strict_lock_struct(fsp
, (uint64_t)smbreq
->smbpid
,
537 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
540 /* Take the lock until the AIO completes. */
541 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &aio_ex
->lock
)) {
543 return NT_STATUS_FILE_LOCK_CONFLICT
;
548 /* Now set up the aio record for the read call. */
550 a
->aio_fildes
= fsp
->fh
->fd
;
551 a
->aio_buf
= preadbuf
->data
;
552 a
->aio_nbytes
= smb_maxcnt
;
553 a
->aio_offset
= startpos
;
554 a
->aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
555 a
->aio_sigevent
.sigev_signo
= RT_SIGNAL_AIO
;
556 a
->aio_sigevent
.sigev_value
.sival_ptr
= aio_ex
;
558 ret
= SMB_VFS_AIO_READ(fsp
, a
);
560 DEBUG(0,("smb2: aio_read failed. "
561 "Error %s\n", strerror(errno
) ));
562 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &aio_ex
->lock
);
564 return NT_STATUS_RETRY
;
567 /* We don't need talloc_move here as both aio_ex and
568 * smbreq are children of smbreq->smb2req. */
569 aio_ex
->smbreq
= smbreq
;
570 smbreq
->async_priv
= aio_ex
;
572 DEBUG(10,("smb2: scheduled aio_read for file %s, "
573 "offset %.0f, len = %u (mid = %u)\n",
574 fsp_str_dbg(fsp
), (double)startpos
, (unsigned int)smb_maxcnt
,
575 (unsigned int)aio_ex
->smbreq
->mid
));
580 /****************************************************************************
581 Set up an aio request from a SMB2write call.
582 *****************************************************************************/
584 NTSTATUS
schedule_aio_smb2_write(connection_struct
*conn
,
585 struct smb_request
*smbreq
,
591 struct aio_extra
*aio_ex
= NULL
;
592 SMB_STRUCT_AIOCB
*a
= NULL
;
593 size_t min_aio_write_size
= lp_aio_write_size(SNUM(conn
));
596 if (fsp
->base_fsp
!= NULL
) {
597 /* No AIO on streams yet */
598 DEBUG(10, ("AIO on streams not yet supported\n"));
599 return NT_STATUS_RETRY
;
602 if ((!min_aio_write_size
|| (in_data
.length
< min_aio_write_size
))
603 && !SMB_VFS_AIO_FORCE(fsp
)) {
604 /* Too small a write for aio request. */
605 DEBUG(10,("smb2: write size (%u) too "
606 "small for minimum aio_write of %u\n",
607 (unsigned int)in_data
.length
,
608 (unsigned int)min_aio_write_size
));
609 return NT_STATUS_RETRY
;
612 /* Only do this on writes not using the write cache. */
613 if (lp_write_cache_size(SNUM(conn
)) != 0) {
614 return NT_STATUS_RETRY
;
617 if (outstanding_aio_calls
>= aio_pending_size
) {
618 DEBUG(3,("smb2: Already have %d aio "
619 "activities outstanding.\n",
620 outstanding_aio_calls
));
621 return NT_STATUS_RETRY
;
624 if (!(aio_ex
= create_aio_extra(smbreq
->smb2req
, fsp
, 0))) {
625 return NT_STATUS_NO_MEMORY
;
628 aio_ex
->handle_completion
= handle_aio_smb2_write_complete
;
629 aio_ex
->write_through
= write_through
;
631 init_strict_lock_struct(fsp
, (uint64_t)smbreq
->smbpid
,
632 in_offset
, (uint64_t)in_data
.length
, WRITE_LOCK
,
635 /* Take the lock until the AIO completes. */
636 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &aio_ex
->lock
)) {
638 return NT_STATUS_FILE_LOCK_CONFLICT
;
643 /* Now set up the aio record for the write call. */
645 a
->aio_fildes
= fsp
->fh
->fd
;
646 a
->aio_buf
= in_data
.data
;
647 a
->aio_nbytes
= in_data
.length
;
648 a
->aio_offset
= in_offset
;
649 a
->aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
650 a
->aio_sigevent
.sigev_signo
= RT_SIGNAL_AIO
;
651 a
->aio_sigevent
.sigev_value
.sival_ptr
= aio_ex
;
653 ret
= SMB_VFS_AIO_WRITE(fsp
, a
);
655 DEBUG(3,("smb2: aio_write failed. "
656 "Error %s\n", strerror(errno
) ));
657 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &aio_ex
->lock
);
659 return NT_STATUS_RETRY
;
662 /* We don't need talloc_move here as both aio_ex and
663 * smbreq are children of smbreq->smb2req. */
664 aio_ex
->smbreq
= smbreq
;
665 smbreq
->async_priv
= aio_ex
;
667 /* This should actually be improved to span the write. */
668 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_WRITE
);
669 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_WRITE
);
672 * We don't want to do write behind due to ownership
673 * issues of the request structs. Maybe add it if I
674 * figure those out. JRA.
677 DEBUG(10,("smb2: scheduled aio_write for file "
678 "%s, offset %.0f, len = %u (mid = %u) "
679 "outstanding_aio_calls = %d\n",
682 (unsigned int)in_data
.length
,
683 (unsigned int)aio_ex
->smbreq
->mid
,
684 outstanding_aio_calls
));
689 /****************************************************************************
690 Complete the read and return the data or error back to the client.
691 Returns errno or zero if all ok.
692 *****************************************************************************/
694 static int handle_aio_read_complete(struct aio_extra
*aio_ex
, int errcode
)
697 char *outbuf
= (char *)aio_ex
->outbuf
.data
;
698 char *data
= smb_buf(outbuf
);
699 ssize_t nread
= SMB_VFS_AIO_RETURN(aio_ex
->fsp
,&aio_ex
->acb
);
702 /* We're relying here on the fact that if the fd is
703 closed then the aio will complete and aio_return
704 will return an error. Hopefully this is
707 DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d. "
709 fsp_str_dbg(aio_ex
->fsp
), (int)nread
, strerror(errcode
)));
711 ERROR_NT(map_nt_error_from_unix(errcode
));
712 outsize
= srv_set_message(outbuf
,0,0,true);
714 outsize
= srv_set_message(outbuf
,12,nread
,False
);
715 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be * -1. */
716 SSVAL(outbuf
,smb_vwv5
,nread
);
717 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
718 SSVAL(outbuf
,smb_vwv7
,((nread
>> 16) & 1));
719 SSVAL(smb_buf(outbuf
),-2,nread
);
721 aio_ex
->fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nread
;
722 aio_ex
->fsp
->fh
->position_information
= aio_ex
->fsp
->fh
->pos
;
724 DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
726 fsp_str_dbg(aio_ex
->fsp
),
727 (int)aio_ex
->acb
.aio_nbytes
, (int)nread
) );
730 smb_setlen(outbuf
,outsize
- 4);
732 if (!srv_send_smb(aio_ex
->smbreq
->sconn
, outbuf
,
733 true, aio_ex
->smbreq
->seqnum
+1,
734 IS_CONN_ENCRYPTED(aio_ex
->fsp
->conn
), NULL
)) {
735 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
739 DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed "
740 "for file %s, offset %.0f, len = %u\n",
741 fsp_str_dbg(aio_ex
->fsp
), (double)aio_ex
->acb
.aio_offset
,
742 (unsigned int)nread
));
747 /****************************************************************************
748 Complete the write and return the data or error back to the client.
749 Returns error code or zero if all ok.
750 *****************************************************************************/
752 static int handle_aio_write_complete(struct aio_extra
*aio_ex
, int errcode
)
754 files_struct
*fsp
= aio_ex
->fsp
;
755 char *outbuf
= (char *)aio_ex
->outbuf
.data
;
756 ssize_t numtowrite
= aio_ex
->acb
.aio_nbytes
;
757 ssize_t nwritten
= SMB_VFS_AIO_RETURN(fsp
,&aio_ex
->acb
);
759 if (fsp
->aio_write_behind
) {
760 if (nwritten
!= numtowrite
) {
761 if (nwritten
== -1) {
762 DEBUG(5,("handle_aio_write_complete: "
763 "aio_write_behind failed ! File %s "
764 "is corrupt ! Error %s\n",
765 fsp_str_dbg(fsp
), strerror(errcode
)));
767 DEBUG(0,("handle_aio_write_complete: "
768 "aio_write_behind failed ! File %s "
769 "is corrupt ! Wanted %u bytes but "
770 "only wrote %d\n", fsp_str_dbg(fsp
),
771 (unsigned int)numtowrite
,
776 DEBUG(10,("handle_aio_write_complete: "
777 "aio_write_behind completed for file %s\n",
780 /* TODO: should no return 0 in case of an error !!! */
784 /* We don't need outsize or set_message here as we've already set the
785 fixed size length when we set up the aio call. */
788 DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. "
789 "nwritten == %d. Error = %s\n",
790 fsp_str_dbg(fsp
), (unsigned int)numtowrite
,
791 (int)nwritten
, strerror(errcode
) ));
793 ERROR_NT(map_nt_error_from_unix(errcode
));
794 srv_set_message(outbuf
,0,0,true);
798 SSVAL(outbuf
,smb_vwv2
,nwritten
);
799 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
800 if (nwritten
< (ssize_t
)numtowrite
) {
801 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
802 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
805 DEBUG(3,("handle_aio_write: %s, num=%d wrote=%d\n",
806 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
807 status
= sync_file(fsp
->conn
,fsp
, aio_ex
->write_through
);
808 if (!NT_STATUS_IS_OK(status
)) {
810 ERROR_BOTH(map_nt_error_from_unix(errcode
),
811 ERRHRD
, ERRdiskfull
);
812 srv_set_message(outbuf
,0,0,true);
813 DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
814 fsp_str_dbg(fsp
), nt_errstr(status
)));
817 aio_ex
->fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nwritten
;
819 mark_file_modified(aio_ex
->fsp
);
823 if (!srv_send_smb(aio_ex
->smbreq
->sconn
, outbuf
,
824 true, aio_ex
->smbreq
->seqnum
+1,
825 IS_CONN_ENCRYPTED(fsp
->conn
),
827 exit_server_cleanly("handle_aio_write_complete: "
828 "srv_send_smb failed.");
831 DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
832 "for file %s, offset %.0f, requested %u, written = %u\n",
833 fsp_str_dbg(fsp
), (double)aio_ex
->acb
.aio_offset
,
834 (unsigned int)numtowrite
, (unsigned int)nwritten
));
839 /****************************************************************************
840 Complete the read and return the data or error back to the client.
841 Returns errno or zero if all ok.
842 *****************************************************************************/
844 static int handle_aio_smb2_read_complete(struct aio_extra
*aio_ex
, int errcode
)
847 struct tevent_req
*subreq
= aio_ex
->smbreq
->smb2req
->subreq
;
848 ssize_t nread
= SMB_VFS_AIO_RETURN(aio_ex
->fsp
,&aio_ex
->acb
);
850 /* Common error or success code processing for async or sync
853 status
= smb2_read_complete(subreq
, nread
, errcode
);
856 aio_ex
->fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nread
;
857 aio_ex
->fsp
->fh
->position_information
= aio_ex
->fsp
->fh
->pos
;
860 DEBUG(10,("smb2: scheduled aio_read completed "
861 "for file %s, offset %.0f, len = %u "
862 "(errcode = %d, NTSTATUS = %s)\n",
863 fsp_str_dbg(aio_ex
->fsp
),
864 (double)aio_ex
->acb
.aio_offset
,
867 nt_errstr(status
) ));
869 if (!NT_STATUS_IS_OK(status
)) {
870 tevent_req_nterror(subreq
, status
);
874 tevent_req_done(subreq
);
878 /****************************************************************************
879 Complete the SMB2 write and return the data or error back to the client.
880 Returns error code or zero if all ok.
881 *****************************************************************************/
883 static int handle_aio_smb2_write_complete(struct aio_extra
*aio_ex
, int errcode
)
885 files_struct
*fsp
= aio_ex
->fsp
;
886 ssize_t numtowrite
= aio_ex
->acb
.aio_nbytes
;
887 ssize_t nwritten
= SMB_VFS_AIO_RETURN(fsp
,&aio_ex
->acb
);
888 struct tevent_req
*subreq
= aio_ex
->smbreq
->smb2req
->subreq
;
891 status
= smb2_write_complete(subreq
, nwritten
, errcode
);
893 DEBUG(10,("smb2: scheduled aio_write completed "
894 "for file %s, offset %.0f, requested %u, "
895 "written = %u (errcode = %d, NTSTATUS = %s)\n",
897 (double)aio_ex
->acb
.aio_offset
,
898 (unsigned int)numtowrite
,
899 (unsigned int)nwritten
,
901 nt_errstr(status
) ));
903 if (!NT_STATUS_IS_OK(status
)) {
904 tevent_req_nterror(subreq
, status
);
908 mark_file_modified(fsp
);
910 tevent_req_done(subreq
);
914 /****************************************************************************
915 Handle any aio completion. Returns True if finished (and sets *perr if err
916 was non-zero), False if not.
917 *****************************************************************************/
919 static bool handle_aio_completed(struct aio_extra
*aio_ex
, int *perr
)
921 files_struct
*fsp
= NULL
;
925 DEBUG(3, ("handle_aio_completed: Non-existing aio_ex passed\n"));
930 DEBUG(3, ("handle_aio_completed: aio_ex->fsp == NULL\n"));
936 /* Ensure the operation has really completed. */
937 err
= SMB_VFS_AIO_ERROR(fsp
, &aio_ex
->acb
);
938 if (err
== EINPROGRESS
) {
939 DEBUG(10,( "handle_aio_completed: operation mid %llu still in "
940 "process for file %s\n",
941 (unsigned long long)aio_ex
->smbreq
->mid
,
942 fsp_str_dbg(aio_ex
->fsp
)));
946 if (err
== ECANCELED
) {
947 DEBUG(10,( "handle_aio_completed: operation mid %llu canceled "
949 (unsigned long long)aio_ex
->smbreq
->mid
,
950 fsp_str_dbg(aio_ex
->fsp
)));
953 /* Unlock now we're done. */
954 SMB_VFS_STRICT_UNLOCK(fsp
->conn
, fsp
, &aio_ex
->lock
);
956 err
= aio_ex
->handle_completion(aio_ex
, err
);
958 *perr
= err
; /* Only save non-zero errors. */
964 /****************************************************************************
965 Handle any aio completion inline.
966 *****************************************************************************/
968 void smbd_aio_complete_aio_ex(struct aio_extra
*aio_ex
)
970 files_struct
*fsp
= NULL
;
973 DEBUG(10,("smbd_aio_complete_mid: mid[%llu]\n",
974 (unsigned long long)aio_ex
->smbreq
->mid
));
978 /* file was closed whilst I/O was outstanding. Just
980 DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
981 "aio outstanding (mid[%llu]).\n",
982 (unsigned long long)aio_ex
->smbreq
->mid
));
986 if (!handle_aio_completed(aio_ex
, &ret
)) {
991 /****************************************************************************
992 We're doing write behind and the client closed the file. Wait up to 45
993 seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes
994 completed, errno to return if not.
995 *****************************************************************************/
997 #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 45
999 int wait_for_aio_completion(files_struct
*fsp
)
1001 struct aio_extra
*aio_ex
;
1002 const SMB_STRUCT_AIOCB
**aiocb_list
;
1003 int aio_completion_count
= 0;
1004 time_t start_time
= time_mono(NULL
);
1007 for (seconds_left
= SMB_TIME_FOR_AIO_COMPLETE_WAIT
;
1008 seconds_left
>= 0;) {
1013 aio_completion_count
= 0;
1014 for( aio_ex
= aio_list_head
; aio_ex
; aio_ex
= aio_ex
->next
) {
1015 if (aio_ex
->fsp
== fsp
) {
1016 aio_completion_count
++;
1020 if (!aio_completion_count
) {
1024 DEBUG(3,("wait_for_aio_completion: waiting for %d aio events "
1025 "to complete.\n", aio_completion_count
));
1027 aiocb_list
= SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB
*,
1028 aio_completion_count
);
1033 for( i
= 0, aio_ex
= aio_list_head
;
1035 aio_ex
= aio_ex
->next
) {
1036 if (aio_ex
->fsp
== fsp
) {
1037 aiocb_list
[i
++] = &aio_ex
->acb
;
1041 /* Now wait up to seconds_left for completion. */
1042 ts
.tv_sec
= seconds_left
;
1045 DEBUG(10,("wait_for_aio_completion: %d events, doing a wait "
1047 aio_completion_count
, seconds_left
));
1049 err
= SMB_VFS_AIO_SUSPEND(fsp
, aiocb_list
,
1050 aio_completion_count
, &ts
);
1052 DEBUG(10,("wait_for_aio_completion: returned err = %d, "
1053 "errno = %s\n", err
, strerror(errno
) ));
1055 if (err
== -1 && errno
== EAGAIN
) {
1056 DEBUG(0,("wait_for_aio_completion: aio_suspend timed "
1057 "out waiting for %d events after a wait of "
1058 "%d seconds\n", aio_completion_count
,
1061 SAFE_FREE(aiocb_list
);
1062 /* We're hosed here - IO may complete
1063 and trample over memory if we free
1064 the aio_ex struct, but if we don't
1065 we leak IO requests. I think smb_panic()
1066 if the right thing to do here. JRA.
1068 smb_panic("AIO suspend timed out - cannot continue.");
1072 /* One or more events might have completed - process them if
1074 for( i
= 0; i
< aio_completion_count
; i
++) {
1075 aio_ex
= (struct aio_extra
*)aiocb_list
[i
]->aio_sigevent
.sigev_value
.sival_ptr
;
1077 if (!handle_aio_completed(aio_ex
, &err
)) {
1080 TALLOC_FREE(aio_ex
);
1083 SAFE_FREE(aiocb_list
);
1084 seconds_left
= SMB_TIME_FOR_AIO_COMPLETE_WAIT
1085 - (time_mono(NULL
) - start_time
);
1088 /* We timed out - we don't know why. Return ret if already an error,
1090 DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting "
1092 aio_completion_count
));
1099 bool initialize_async_io_handler(void)
1104 NTSTATUS
schedule_aio_read_and_X(connection_struct
*conn
,
1105 struct smb_request
*smbreq
,
1106 files_struct
*fsp
, off_t startpos
,
1109 return NT_STATUS_RETRY
;
1112 NTSTATUS
schedule_aio_write_and_X(connection_struct
*conn
,
1113 struct smb_request
*smbreq
,
1114 files_struct
*fsp
, const char *data
,
1118 return NT_STATUS_RETRY
;
1121 bool cancel_smb2_aio(struct smb_request
*smbreq
)
1126 NTSTATUS
schedule_smb2_aio_read(connection_struct
*conn
,
1127 struct smb_request
*smbreq
,
1130 DATA_BLOB
*preadbuf
,
1134 return NT_STATUS_RETRY
;
1137 NTSTATUS
schedule_aio_smb2_write(connection_struct
*conn
,
1138 struct smb_request
*smbreq
,
1144 return NT_STATUS_RETRY
;
1147 int wait_for_aio_completion(files_struct
*fsp
)
1152 void smbd_aio_complete_mid(uint64_t mid
);