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 static void aio_pwrite_smb1_done(struct tevent_req
*req
);
326 /****************************************************************************
327 Set up an aio request from a SMBwriteX call.
328 *****************************************************************************/
330 NTSTATUS
schedule_aio_write_and_X(connection_struct
*conn
,
331 struct smb_request
*smbreq
,
332 files_struct
*fsp
, const char *data
,
336 struct aio_extra
*aio_ex
;
339 size_t min_aio_write_size
= lp_aio_write_size(SNUM(conn
));
340 struct tevent_req
*req
;
342 if (fsp
->base_fsp
!= NULL
) {
343 /* No AIO on streams yet */
344 DEBUG(10, ("AIO on streams not yet supported\n"));
345 return NT_STATUS_RETRY
;
348 if ((!min_aio_write_size
|| (numtowrite
< min_aio_write_size
))
349 && !SMB_VFS_AIO_FORCE(fsp
)) {
350 /* Too small a write for aio request. */
351 DEBUG(10,("schedule_aio_write_and_X: write size (%u) too "
352 "small for minimum aio_write of %u\n",
353 (unsigned int)numtowrite
,
354 (unsigned int)min_aio_write_size
));
355 return NT_STATUS_RETRY
;
358 /* Only do this on non-chained and non-chaining writes not using the
360 if (req_is_in_chain(smbreq
) || (lp_write_cache_size(SNUM(conn
)) != 0)) {
361 return NT_STATUS_RETRY
;
364 if (outstanding_aio_calls
>= aio_pending_size
) {
365 DEBUG(3,("schedule_aio_write_and_X: Already have %d aio "
366 "activities outstanding.\n",
367 outstanding_aio_calls
));
368 DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
369 "aio_write for file %s, offset %.0f, len = %u "
371 fsp_str_dbg(fsp
), (double)startpos
,
372 (unsigned int)numtowrite
,
373 (unsigned int)smbreq
->mid
));
374 return NT_STATUS_RETRY
;
377 bufsize
= smb_size
+ 6*2;
379 if (!(aio_ex
= create_aio_extra(NULL
, fsp
, bufsize
))) {
380 DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n"));
381 return NT_STATUS_NO_MEMORY
;
383 aio_ex
->handle_completion
= handle_aio_write_complete
;
384 aio_ex
->write_through
= BITSETW(smbreq
->vwv
+7,0);
386 construct_reply_common_req(smbreq
, (char *)aio_ex
->outbuf
.data
);
387 srv_set_message((char *)aio_ex
->outbuf
.data
, 6, 0, True
);
388 SCVAL(aio_ex
->outbuf
.data
,smb_vwv0
,0xFF); /* Never a chained reply. */
390 init_strict_lock_struct(fsp
, (uint64_t)smbreq
->smbpid
,
391 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
394 /* Take the lock until the AIO completes. */
395 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &aio_ex
->lock
)) {
397 return NT_STATUS_FILE_LOCK_CONFLICT
;
402 /* Now set up the aio record for the write call. */
404 a
->aio_fildes
= fsp
->fh
->fd
;
405 a
->aio_buf
= discard_const_p(char, data
);
406 a
->aio_nbytes
= numtowrite
;
407 a
->aio_offset
= startpos
;
408 a
->aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
409 a
->aio_sigevent
.sigev_signo
= RT_SIGNAL_AIO
;
410 a
->aio_sigevent
.sigev_value
.sival_ptr
= aio_ex
;
412 req
= SMB_VFS_PWRITE_SEND(aio_ex
, fsp
->conn
->sconn
->ev_ctx
, fsp
,
413 data
, numtowrite
, startpos
);
415 DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
416 "Error %s\n", strerror(errno
) ));
417 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &aio_ex
->lock
);
419 return NT_STATUS_RETRY
;
421 tevent_req_set_callback(req
, aio_pwrite_smb1_done
, aio_ex
);
423 aio_ex
->smbreq
= talloc_move(aio_ex
, &smbreq
);
425 /* This should actually be improved to span the write. */
426 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_WRITE
);
427 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_WRITE
);
429 if (!aio_ex
->write_through
&& !lp_syncalways(SNUM(fsp
->conn
))
430 && fsp
->aio_write_behind
) {
431 /* Lie to the client and immediately claim we finished the
433 SSVAL(aio_ex
->outbuf
.data
,smb_vwv2
,numtowrite
);
434 SSVAL(aio_ex
->outbuf
.data
,smb_vwv4
,(numtowrite
>>16)&1);
435 show_msg((char *)aio_ex
->outbuf
.data
);
436 if (!srv_send_smb(aio_ex
->smbreq
->sconn
,
437 (char *)aio_ex
->outbuf
.data
,
438 true, aio_ex
->smbreq
->seqnum
+1,
439 IS_CONN_ENCRYPTED(fsp
->conn
),
440 &aio_ex
->smbreq
->pcd
)) {
441 exit_server_cleanly("schedule_aio_write_and_X: "
442 "srv_send_smb failed.");
444 DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
445 "behind for file %s\n", fsp_str_dbg(fsp
)));
448 DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file "
449 "%s, offset %.0f, len = %u (mid = %u) "
450 "outstanding_aio_calls = %d\n",
451 fsp_str_dbg(fsp
), (double)startpos
, (unsigned int)numtowrite
,
452 (unsigned int)aio_ex
->smbreq
->mid
, outstanding_aio_calls
));
457 static void aio_pwrite_smb1_done(struct tevent_req
*req
)
459 struct aio_extra
*aio_ex
= tevent_req_callback_data(
460 req
, struct aio_extra
);
461 files_struct
*fsp
= aio_ex
->fsp
;
462 char *outbuf
= (char *)aio_ex
->outbuf
.data
;
463 ssize_t numtowrite
= aio_ex
->acb
.aio_nbytes
;
467 nwritten
= SMB_VFS_PWRITE_RECV(req
, &err
);
470 DEBUG(10, ("pwrite_recv returned %d, err = %s\n", (int)nwritten
,
471 (nwritten
== -1) ? strerror(err
) : "no error"));
474 DEBUG( 3, ("aio_pwrite_smb1_done: file closed whilst "
475 "aio outstanding (mid[%llu]).\n",
476 (unsigned long long)aio_ex
->smbreq
->mid
));
481 /* Unlock now we're done. */
482 SMB_VFS_STRICT_UNLOCK(fsp
->conn
, fsp
, &aio_ex
->lock
);
484 if (fsp
->aio_write_behind
) {
486 if (nwritten
!= numtowrite
) {
487 if (nwritten
== -1) {
488 DEBUG(5,("handle_aio_write_complete: "
489 "aio_write_behind failed ! File %s "
490 "is corrupt ! Error %s\n",
491 fsp_str_dbg(fsp
), strerror(err
)));
493 DEBUG(0,("handle_aio_write_complete: "
494 "aio_write_behind failed ! File %s "
495 "is corrupt ! Wanted %u bytes but "
496 "only wrote %d\n", fsp_str_dbg(fsp
),
497 (unsigned int)numtowrite
,
501 DEBUG(10,("handle_aio_write_complete: "
502 "aio_write_behind completed for file %s\n",
505 /* TODO: should no return success in case of an error !!! */
510 /* We don't need outsize or set_message here as we've already set the
511 fixed size length when we set up the aio call. */
513 if (nwritten
== -1) {
514 DEBUG(3, ("handle_aio_write: file %s wanted %u bytes. "
515 "nwritten == %d. Error = %s\n",
516 fsp_str_dbg(fsp
), (unsigned int)numtowrite
,
517 (int)nwritten
, strerror(err
)));
519 ERROR_NT(map_nt_error_from_unix(err
));
520 srv_set_message(outbuf
,0,0,true);
524 SSVAL(outbuf
,smb_vwv2
,nwritten
);
525 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
526 if (nwritten
< (ssize_t
)numtowrite
) {
527 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
528 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
531 DEBUG(3,("handle_aio_write: %s, num=%d wrote=%d\n",
532 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
533 status
= sync_file(fsp
->conn
,fsp
, aio_ex
->write_through
);
534 if (!NT_STATUS_IS_OK(status
)) {
535 ERROR_BOTH(map_nt_error_from_unix(errno
),
536 ERRHRD
, ERRdiskfull
);
537 srv_set_message(outbuf
,0,0,true);
538 DEBUG(5, ("handle_aio_write: sync_file for %s "
540 fsp_str_dbg(fsp
), nt_errstr(status
)));
543 aio_ex
->fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nwritten
;
547 if (!srv_send_smb(aio_ex
->smbreq
->sconn
, outbuf
,
548 true, aio_ex
->smbreq
->seqnum
+1,
549 IS_CONN_ENCRYPTED(fsp
->conn
),
551 exit_server_cleanly("handle_aio_write_complete: "
552 "srv_send_smb failed.");
555 DEBUG(10, ("handle_aio_write_complete: scheduled aio_write completed "
556 "for file %s, offset %.0f, requested %u, written = %u\n",
557 fsp_str_dbg(fsp
), (double)aio_ex
->acb
.aio_offset
,
558 (unsigned int)numtowrite
, (unsigned int)nwritten
));
563 bool cancel_smb2_aio(struct smb_request
*smbreq
)
565 struct smbd_smb2_request
*smb2req
= smbreq
->smb2req
;
566 struct aio_extra
*aio_ex
= NULL
;
570 aio_ex
= talloc_get_type(smbreq
->async_priv
,
574 if (aio_ex
== NULL
) {
578 if (aio_ex
->fsp
== NULL
) {
582 ret
= SMB_VFS_AIO_CANCEL(aio_ex
->fsp
, &aio_ex
->acb
);
583 if (ret
!= AIO_CANCELED
) {
590 static void aio_pread_smb2_done(struct tevent_req
*req
);
592 /****************************************************************************
593 Set up an aio request from a SMB2 read call.
594 *****************************************************************************/
596 NTSTATUS
schedule_smb2_aio_read(connection_struct
*conn
,
597 struct smb_request
*smbreq
,
604 struct aio_extra
*aio_ex
;
606 size_t min_aio_read_size
= lp_aio_read_size(SNUM(conn
));
607 struct tevent_req
*req
;
609 if (fsp
->base_fsp
!= NULL
) {
610 /* No AIO on streams yet */
611 DEBUG(10, ("AIO on streams not yet supported\n"));
612 return NT_STATUS_RETRY
;
615 if ((!min_aio_read_size
|| (smb_maxcnt
< min_aio_read_size
))
616 && !SMB_VFS_AIO_FORCE(fsp
)) {
617 /* Too small a read for aio request. */
618 DEBUG(10,("smb2: read size (%u) too small "
619 "for minimum aio_read of %u\n",
620 (unsigned int)smb_maxcnt
,
621 (unsigned int)min_aio_read_size
));
622 return NT_STATUS_RETRY
;
625 /* Only do this on reads not using the write cache. */
626 if (lp_write_cache_size(SNUM(conn
)) != 0) {
627 return NT_STATUS_RETRY
;
630 if (outstanding_aio_calls
>= aio_pending_size
) {
631 DEBUG(10,("smb2: Already have %d aio "
632 "activities outstanding.\n",
633 outstanding_aio_calls
));
634 return NT_STATUS_RETRY
;
637 /* Create the out buffer. */
638 *preadbuf
= data_blob_talloc(ctx
, NULL
, smb_maxcnt
);
639 if (preadbuf
->data
== NULL
) {
640 return NT_STATUS_NO_MEMORY
;
643 if (!(aio_ex
= create_aio_extra(smbreq
->smb2req
, fsp
, 0))) {
644 return NT_STATUS_NO_MEMORY
;
646 aio_ex
->handle_completion
= handle_aio_smb2_read_complete
;
648 init_strict_lock_struct(fsp
, (uint64_t)smbreq
->smbpid
,
649 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
652 /* Take the lock until the AIO completes. */
653 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &aio_ex
->lock
)) {
655 return NT_STATUS_FILE_LOCK_CONFLICT
;
660 /* Now set up the aio record for the read call. */
662 a
->aio_fildes
= fsp
->fh
->fd
;
663 a
->aio_buf
= preadbuf
->data
;
664 a
->aio_nbytes
= smb_maxcnt
;
665 a
->aio_offset
= startpos
;
666 a
->aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
667 a
->aio_sigevent
.sigev_signo
= RT_SIGNAL_AIO
;
668 a
->aio_sigevent
.sigev_value
.sival_ptr
= aio_ex
;
670 req
= SMB_VFS_PREAD_SEND(aio_ex
, fsp
->conn
->sconn
->ev_ctx
, fsp
,
671 preadbuf
->data
, smb_maxcnt
, startpos
);
673 DEBUG(0, ("smb2: SMB_VFS_PREAD_SEND failed. "
674 "Error %s\n", strerror(errno
)));
675 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &aio_ex
->lock
);
677 return NT_STATUS_RETRY
;
679 tevent_req_set_callback(req
, aio_pread_smb2_done
, aio_ex
);
681 /* We don't need talloc_move here as both aio_ex and
682 * smbreq are children of smbreq->smb2req. */
683 aio_ex
->smbreq
= smbreq
;
684 smbreq
->async_priv
= aio_ex
;
686 DEBUG(10,("smb2: scheduled aio_read for file %s, "
687 "offset %.0f, len = %u (mid = %u)\n",
688 fsp_str_dbg(fsp
), (double)startpos
, (unsigned int)smb_maxcnt
,
689 (unsigned int)aio_ex
->smbreq
->mid
));
694 static void aio_pread_smb2_done(struct tevent_req
*req
)
696 struct aio_extra
*aio_ex
= tevent_req_callback_data(
697 req
, struct aio_extra
);
698 struct tevent_req
*subreq
= aio_ex
->smbreq
->smb2req
->subreq
;
699 files_struct
*fsp
= aio_ex
->fsp
;
704 nread
= SMB_VFS_PREAD_RECV(req
, &err
);
707 DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread
,
708 (nread
== -1) ? strerror(err
) : "no error"));
711 DEBUG( 3, ("aio_pread_smb2_done: file closed whilst "
712 "aio outstanding (mid[%llu]).\n",
713 (unsigned long long)aio_ex
->smbreq
->mid
));
718 /* Unlock now we're done. */
719 SMB_VFS_STRICT_UNLOCK(fsp
->conn
, fsp
, &aio_ex
->lock
);
721 /* Common error or success code processing for async or sync
724 status
= smb2_read_complete(subreq
, nread
, err
);
727 fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nread
;
728 fsp
->fh
->position_information
= fsp
->fh
->pos
;
731 DEBUG(10, ("smb2: scheduled aio_read completed "
732 "for file %s, offset %.0f, len = %u "
733 "(errcode = %d, NTSTATUS = %s)\n",
734 fsp_str_dbg(aio_ex
->fsp
),
735 (double)aio_ex
->acb
.aio_offset
,
737 err
, nt_errstr(status
)));
739 if (!NT_STATUS_IS_OK(status
)) {
740 tevent_req_nterror(subreq
, status
);
743 tevent_req_done(subreq
);
746 static void aio_pwrite_smb2_done(struct tevent_req
*req
);
748 /****************************************************************************
749 Set up an aio request from a SMB2write call.
750 *****************************************************************************/
752 NTSTATUS
schedule_aio_smb2_write(connection_struct
*conn
,
753 struct smb_request
*smbreq
,
759 struct aio_extra
*aio_ex
= NULL
;
760 SMB_STRUCT_AIOCB
*a
= NULL
;
761 size_t min_aio_write_size
= lp_aio_write_size(SNUM(conn
));
762 struct tevent_req
*req
;
764 if (fsp
->base_fsp
!= NULL
) {
765 /* No AIO on streams yet */
766 DEBUG(10, ("AIO on streams not yet supported\n"));
767 return NT_STATUS_RETRY
;
770 if ((!min_aio_write_size
|| (in_data
.length
< min_aio_write_size
))
771 && !SMB_VFS_AIO_FORCE(fsp
)) {
772 /* Too small a write for aio request. */
773 DEBUG(10,("smb2: write size (%u) too "
774 "small for minimum aio_write of %u\n",
775 (unsigned int)in_data
.length
,
776 (unsigned int)min_aio_write_size
));
777 return NT_STATUS_RETRY
;
780 /* Only do this on writes not using the write cache. */
781 if (lp_write_cache_size(SNUM(conn
)) != 0) {
782 return NT_STATUS_RETRY
;
785 if (outstanding_aio_calls
>= aio_pending_size
) {
786 DEBUG(3,("smb2: Already have %d aio "
787 "activities outstanding.\n",
788 outstanding_aio_calls
));
789 return NT_STATUS_RETRY
;
792 if (!(aio_ex
= create_aio_extra(smbreq
->smb2req
, fsp
, 0))) {
793 return NT_STATUS_NO_MEMORY
;
796 aio_ex
->handle_completion
= handle_aio_smb2_write_complete
;
797 aio_ex
->write_through
= write_through
;
799 init_strict_lock_struct(fsp
, (uint64_t)smbreq
->smbpid
,
800 in_offset
, (uint64_t)in_data
.length
, WRITE_LOCK
,
803 /* Take the lock until the AIO completes. */
804 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &aio_ex
->lock
)) {
806 return NT_STATUS_FILE_LOCK_CONFLICT
;
811 /* Now set up the aio record for the write call. */
813 a
->aio_fildes
= fsp
->fh
->fd
;
814 a
->aio_buf
= in_data
.data
;
815 a
->aio_nbytes
= in_data
.length
;
816 a
->aio_offset
= in_offset
;
817 a
->aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
818 a
->aio_sigevent
.sigev_signo
= RT_SIGNAL_AIO
;
819 a
->aio_sigevent
.sigev_value
.sival_ptr
= aio_ex
;
821 req
= SMB_VFS_PWRITE_SEND(aio_ex
, fsp
->conn
->sconn
->ev_ctx
, fsp
,
822 in_data
.data
, in_data
.length
, in_offset
);
824 DEBUG(3, ("smb2: SMB_VFS_PWRITE_SEND failed. "
825 "Error %s\n", strerror(errno
)));
826 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &aio_ex
->lock
);
828 return NT_STATUS_RETRY
;
830 tevent_req_set_callback(req
, aio_pwrite_smb2_done
, aio_ex
);
832 /* We don't need talloc_move here as both aio_ex and
833 * smbreq are children of smbreq->smb2req. */
834 aio_ex
->smbreq
= smbreq
;
835 smbreq
->async_priv
= aio_ex
;
837 /* This should actually be improved to span the write. */
838 contend_level2_oplocks_begin(fsp
, LEVEL2_CONTEND_WRITE
);
839 contend_level2_oplocks_end(fsp
, LEVEL2_CONTEND_WRITE
);
842 * We don't want to do write behind due to ownership
843 * issues of the request structs. Maybe add it if I
844 * figure those out. JRA.
847 DEBUG(10,("smb2: scheduled aio_write for file "
848 "%s, offset %.0f, len = %u (mid = %u) "
849 "outstanding_aio_calls = %d\n",
852 (unsigned int)in_data
.length
,
853 (unsigned int)aio_ex
->smbreq
->mid
,
854 outstanding_aio_calls
));
859 static void aio_pwrite_smb2_done(struct tevent_req
*req
)
861 struct aio_extra
*aio_ex
= tevent_req_callback_data(
862 req
, struct aio_extra
);
863 ssize_t numtowrite
= aio_ex
->acb
.aio_nbytes
;
864 struct tevent_req
*subreq
= aio_ex
->smbreq
->smb2req
->subreq
;
865 files_struct
*fsp
= aio_ex
->fsp
;
870 nwritten
= SMB_VFS_PWRITE_RECV(req
, &err
);
873 DEBUG(10, ("pwrite_recv returned %d, err = %s\n", (int)nwritten
,
874 (nwritten
== -1) ? strerror(err
) : "no error"));
877 DEBUG( 3, ("aio_pwrite_smb2_done: file closed whilst "
878 "aio outstanding (mid[%llu]).\n",
879 (unsigned long long)aio_ex
->smbreq
->mid
));
884 /* Unlock now we're done. */
885 SMB_VFS_STRICT_UNLOCK(fsp
->conn
, fsp
, &aio_ex
->lock
);
887 status
= smb2_write_complete(subreq
, nwritten
, err
);
889 DEBUG(10, ("smb2: scheduled aio_write completed "
890 "for file %s, offset %.0f, requested %u, "
891 "written = %u (errcode = %d, NTSTATUS = %s)\n",
893 (double)aio_ex
->acb
.aio_offset
,
894 (unsigned int)numtowrite
,
895 (unsigned int)nwritten
,
896 err
, nt_errstr(status
)));
898 if (!NT_STATUS_IS_OK(status
)) {
899 tevent_req_nterror(subreq
, status
);
902 tevent_req_done(subreq
);
905 /****************************************************************************
906 Complete the read and return the data or error back to the client.
907 Returns errno or zero if all ok.
908 *****************************************************************************/
910 static int handle_aio_read_complete(struct aio_extra
*aio_ex
, int errcode
)
913 char *outbuf
= (char *)aio_ex
->outbuf
.data
;
914 char *data
= smb_buf(outbuf
);
915 ssize_t nread
= SMB_VFS_AIO_RETURN(aio_ex
->fsp
,&aio_ex
->acb
);
918 /* We're relying here on the fact that if the fd is
919 closed then the aio will complete and aio_return
920 will return an error. Hopefully this is
923 DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d. "
925 fsp_str_dbg(aio_ex
->fsp
), (int)nread
, strerror(errcode
)));
927 ERROR_NT(map_nt_error_from_unix(errcode
));
928 outsize
= srv_set_message(outbuf
,0,0,true);
930 outsize
= srv_set_message(outbuf
,12,nread
,False
);
931 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be * -1. */
932 SSVAL(outbuf
,smb_vwv5
,nread
);
933 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
934 SSVAL(outbuf
,smb_vwv7
,((nread
>> 16) & 1));
935 SSVAL(smb_buf(outbuf
),-2,nread
);
937 aio_ex
->fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nread
;
938 aio_ex
->fsp
->fh
->position_information
= aio_ex
->fsp
->fh
->pos
;
940 DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
942 fsp_str_dbg(aio_ex
->fsp
),
943 (int)aio_ex
->acb
.aio_nbytes
, (int)nread
) );
946 smb_setlen(outbuf
,outsize
- 4);
948 if (!srv_send_smb(aio_ex
->smbreq
->sconn
, outbuf
,
949 true, aio_ex
->smbreq
->seqnum
+1,
950 IS_CONN_ENCRYPTED(aio_ex
->fsp
->conn
), NULL
)) {
951 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
955 DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed "
956 "for file %s, offset %.0f, len = %u\n",
957 fsp_str_dbg(aio_ex
->fsp
), (double)aio_ex
->acb
.aio_offset
,
958 (unsigned int)nread
));
963 /****************************************************************************
964 Complete the write and return the data or error back to the client.
965 Returns error code or zero if all ok.
966 *****************************************************************************/
968 static int handle_aio_write_complete(struct aio_extra
*aio_ex
, int errcode
)
970 files_struct
*fsp
= aio_ex
->fsp
;
971 char *outbuf
= (char *)aio_ex
->outbuf
.data
;
972 ssize_t numtowrite
= aio_ex
->acb
.aio_nbytes
;
973 ssize_t nwritten
= SMB_VFS_AIO_RETURN(fsp
,&aio_ex
->acb
);
975 if (fsp
->aio_write_behind
) {
976 if (nwritten
!= numtowrite
) {
977 if (nwritten
== -1) {
978 DEBUG(5,("handle_aio_write_complete: "
979 "aio_write_behind failed ! File %s "
980 "is corrupt ! Error %s\n",
981 fsp_str_dbg(fsp
), strerror(errcode
)));
983 DEBUG(0,("handle_aio_write_complete: "
984 "aio_write_behind failed ! File %s "
985 "is corrupt ! Wanted %u bytes but "
986 "only wrote %d\n", fsp_str_dbg(fsp
),
987 (unsigned int)numtowrite
,
992 DEBUG(10,("handle_aio_write_complete: "
993 "aio_write_behind completed for file %s\n",
996 /* TODO: should no return 0 in case of an error !!! */
1000 /* We don't need outsize or set_message here as we've already set the
1001 fixed size length when we set up the aio call. */
1003 if(nwritten
== -1) {
1004 DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. "
1005 "nwritten == %d. Error = %s\n",
1006 fsp_str_dbg(fsp
), (unsigned int)numtowrite
,
1007 (int)nwritten
, strerror(errcode
) ));
1009 ERROR_NT(map_nt_error_from_unix(errcode
));
1010 srv_set_message(outbuf
,0,0,true);
1014 SSVAL(outbuf
,smb_vwv2
,nwritten
);
1015 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
1016 if (nwritten
< (ssize_t
)numtowrite
) {
1017 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
1018 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1021 DEBUG(3,("handle_aio_write: %s, num=%d wrote=%d\n",
1022 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
1023 status
= sync_file(fsp
->conn
,fsp
, aio_ex
->write_through
);
1024 if (!NT_STATUS_IS_OK(status
)) {
1026 ERROR_BOTH(map_nt_error_from_unix(errcode
),
1027 ERRHRD
, ERRdiskfull
);
1028 srv_set_message(outbuf
,0,0,true);
1029 DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
1030 fsp_str_dbg(fsp
), nt_errstr(status
)));
1033 aio_ex
->fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nwritten
;
1035 mark_file_modified(aio_ex
->fsp
);
1039 if (!srv_send_smb(aio_ex
->smbreq
->sconn
, outbuf
,
1040 true, aio_ex
->smbreq
->seqnum
+1,
1041 IS_CONN_ENCRYPTED(fsp
->conn
),
1043 exit_server_cleanly("handle_aio_write_complete: "
1044 "srv_send_smb failed.");
1047 DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
1048 "for file %s, offset %.0f, requested %u, written = %u\n",
1049 fsp_str_dbg(fsp
), (double)aio_ex
->acb
.aio_offset
,
1050 (unsigned int)numtowrite
, (unsigned int)nwritten
));
1055 /****************************************************************************
1056 Complete the read and return the data or error back to the client.
1057 Returns errno or zero if all ok.
1058 *****************************************************************************/
1060 static int handle_aio_smb2_read_complete(struct aio_extra
*aio_ex
, int errcode
)
1063 struct tevent_req
*subreq
= aio_ex
->smbreq
->smb2req
->subreq
;
1064 ssize_t nread
= SMB_VFS_AIO_RETURN(aio_ex
->fsp
,&aio_ex
->acb
);
1066 /* Common error or success code processing for async or sync
1069 status
= smb2_read_complete(subreq
, nread
, errcode
);
1072 aio_ex
->fsp
->fh
->pos
= aio_ex
->acb
.aio_offset
+ nread
;
1073 aio_ex
->fsp
->fh
->position_information
= aio_ex
->fsp
->fh
->pos
;
1076 DEBUG(10,("smb2: scheduled aio_read completed "
1077 "for file %s, offset %.0f, len = %u "
1078 "(errcode = %d, NTSTATUS = %s)\n",
1079 fsp_str_dbg(aio_ex
->fsp
),
1080 (double)aio_ex
->acb
.aio_offset
,
1081 (unsigned int)nread
,
1083 nt_errstr(status
) ));
1085 if (!NT_STATUS_IS_OK(status
)) {
1086 tevent_req_nterror(subreq
, status
);
1090 tevent_req_done(subreq
);
1094 /****************************************************************************
1095 Complete the SMB2 write and return the data or error back to the client.
1096 Returns error code or zero if all ok.
1097 *****************************************************************************/
1099 static int handle_aio_smb2_write_complete(struct aio_extra
*aio_ex
, int errcode
)
1101 files_struct
*fsp
= aio_ex
->fsp
;
1102 ssize_t numtowrite
= aio_ex
->acb
.aio_nbytes
;
1103 ssize_t nwritten
= SMB_VFS_AIO_RETURN(fsp
,&aio_ex
->acb
);
1104 struct tevent_req
*subreq
= aio_ex
->smbreq
->smb2req
->subreq
;
1107 status
= smb2_write_complete(subreq
, nwritten
, errcode
);
1109 DEBUG(10,("smb2: scheduled aio_write completed "
1110 "for file %s, offset %.0f, requested %u, "
1111 "written = %u (errcode = %d, NTSTATUS = %s)\n",
1113 (double)aio_ex
->acb
.aio_offset
,
1114 (unsigned int)numtowrite
,
1115 (unsigned int)nwritten
,
1117 nt_errstr(status
) ));
1119 if (!NT_STATUS_IS_OK(status
)) {
1120 tevent_req_nterror(subreq
, status
);
1124 mark_file_modified(fsp
);
1126 tevent_req_done(subreq
);
1130 /****************************************************************************
1131 Handle any aio completion. Returns True if finished (and sets *perr if err
1132 was non-zero), False if not.
1133 *****************************************************************************/
1135 static bool handle_aio_completed(struct aio_extra
*aio_ex
, int *perr
)
1137 files_struct
*fsp
= NULL
;
1141 DEBUG(3, ("handle_aio_completed: Non-existing aio_ex passed\n"));
1146 DEBUG(3, ("handle_aio_completed: aio_ex->fsp == NULL\n"));
1152 /* Ensure the operation has really completed. */
1153 err
= SMB_VFS_AIO_ERROR(fsp
, &aio_ex
->acb
);
1154 if (err
== EINPROGRESS
) {
1155 DEBUG(10,( "handle_aio_completed: operation mid %llu still in "
1156 "process for file %s\n",
1157 (unsigned long long)aio_ex
->smbreq
->mid
,
1158 fsp_str_dbg(aio_ex
->fsp
)));
1162 if (err
== ECANCELED
) {
1163 DEBUG(10,( "handle_aio_completed: operation mid %llu canceled "
1165 (unsigned long long)aio_ex
->smbreq
->mid
,
1166 fsp_str_dbg(aio_ex
->fsp
)));
1169 /* Unlock now we're done. */
1170 SMB_VFS_STRICT_UNLOCK(fsp
->conn
, fsp
, &aio_ex
->lock
);
1172 err
= aio_ex
->handle_completion(aio_ex
, err
);
1174 *perr
= err
; /* Only save non-zero errors. */
1180 /****************************************************************************
1181 Handle any aio completion inline.
1182 *****************************************************************************/
1184 void smbd_aio_complete_aio_ex(struct aio_extra
*aio_ex
)
1186 files_struct
*fsp
= NULL
;
1189 DEBUG(10,("smbd_aio_complete_mid: mid[%llu]\n",
1190 (unsigned long long)aio_ex
->smbreq
->mid
));
1194 /* file was closed whilst I/O was outstanding. Just
1196 DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
1197 "aio outstanding (mid[%llu]).\n",
1198 (unsigned long long)aio_ex
->smbreq
->mid
));
1202 if (!handle_aio_completed(aio_ex
, &ret
)) {
1207 /****************************************************************************
1208 We're doing write behind and the client closed the file. Wait up to 45
1209 seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes
1210 completed, errno to return if not.
1211 *****************************************************************************/
1213 #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 45
1215 int wait_for_aio_completion(files_struct
*fsp
)
1217 struct aio_extra
*aio_ex
;
1218 const SMB_STRUCT_AIOCB
**aiocb_list
;
1219 int aio_completion_count
= 0;
1220 time_t start_time
= time_mono(NULL
);
1223 for (seconds_left
= SMB_TIME_FOR_AIO_COMPLETE_WAIT
;
1224 seconds_left
>= 0;) {
1229 aio_completion_count
= 0;
1230 for( aio_ex
= aio_list_head
; aio_ex
; aio_ex
= aio_ex
->next
) {
1231 if (aio_ex
->fsp
== fsp
) {
1232 aio_completion_count
++;
1236 if (!aio_completion_count
) {
1240 DEBUG(3,("wait_for_aio_completion: waiting for %d aio events "
1241 "to complete.\n", aio_completion_count
));
1243 aiocb_list
= SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB
*,
1244 aio_completion_count
);
1249 for( i
= 0, aio_ex
= aio_list_head
;
1251 aio_ex
= aio_ex
->next
) {
1252 if (aio_ex
->fsp
== fsp
) {
1253 aiocb_list
[i
++] = &aio_ex
->acb
;
1257 /* Now wait up to seconds_left for completion. */
1258 ts
.tv_sec
= seconds_left
;
1261 DEBUG(10,("wait_for_aio_completion: %d events, doing a wait "
1263 aio_completion_count
, seconds_left
));
1265 err
= SMB_VFS_AIO_SUSPEND(fsp
, aiocb_list
,
1266 aio_completion_count
, &ts
);
1268 DEBUG(10,("wait_for_aio_completion: returned err = %d, "
1269 "errno = %s\n", err
, strerror(errno
) ));
1271 if (err
== -1 && errno
== EAGAIN
) {
1272 DEBUG(0,("wait_for_aio_completion: aio_suspend timed "
1273 "out waiting for %d events after a wait of "
1274 "%d seconds\n", aio_completion_count
,
1277 SAFE_FREE(aiocb_list
);
1278 /* We're hosed here - IO may complete
1279 and trample over memory if we free
1280 the aio_ex struct, but if we don't
1281 we leak IO requests. I think smb_panic()
1282 if the right thing to do here. JRA.
1284 smb_panic("AIO suspend timed out - cannot continue.");
1288 /* One or more events might have completed - process them if
1290 for( i
= 0; i
< aio_completion_count
; i
++) {
1291 aio_ex
= (struct aio_extra
*)aiocb_list
[i
]->aio_sigevent
.sigev_value
.sival_ptr
;
1293 if (!handle_aio_completed(aio_ex
, &err
)) {
1296 TALLOC_FREE(aio_ex
);
1299 SAFE_FREE(aiocb_list
);
1300 seconds_left
= SMB_TIME_FOR_AIO_COMPLETE_WAIT
1301 - (time_mono(NULL
) - start_time
);
1304 /* We timed out - we don't know why. Return ret if already an error,
1306 DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting "
1308 aio_completion_count
));
1315 bool initialize_async_io_handler(void)
1320 NTSTATUS
schedule_aio_read_and_X(connection_struct
*conn
,
1321 struct smb_request
*smbreq
,
1322 files_struct
*fsp
, off_t startpos
,
1325 return NT_STATUS_RETRY
;
1328 NTSTATUS
schedule_aio_write_and_X(connection_struct
*conn
,
1329 struct smb_request
*smbreq
,
1330 files_struct
*fsp
, const char *data
,
1334 return NT_STATUS_RETRY
;
1337 bool cancel_smb2_aio(struct smb_request
*smbreq
)
1342 NTSTATUS
schedule_smb2_aio_read(connection_struct
*conn
,
1343 struct smb_request
*smbreq
,
1346 DATA_BLOB
*preadbuf
,
1350 return NT_STATUS_RETRY
;
1353 NTSTATUS
schedule_aio_smb2_write(connection_struct
*conn
,
1354 struct smb_request
*smbreq
,
1360 return NT_STATUS_RETRY
;
1363 int wait_for_aio_completion(files_struct
*fsp
)
1368 void smbd_aio_complete_mid(uint64_t mid
);