s3-talloc Change TALLOC_ZERO_P() to talloc_zero()
[kai/samba.git] / source3 / smbd / aio.c
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.
6
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.
11
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.
16
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/>.
19 */
20
21 #include "includes.h"
22 #include "smbd/smbd.h"
23 #include "smbd/globals.h"
24 #include "../lib/util/tevent_ntstatus.h"
25
26 #if defined(WITH_AIO)
27
28 /* The signal we'll use to signify aio done. */
29 #ifndef RT_SIGNAL_AIO
30 #define RT_SIGNAL_AIO   (SIGRTMIN+3)
31 #endif
32
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
37 #endif
38 #endif
39
40 /****************************************************************************
41  The buffer we keep around whilst an aio request is in process.
42 *****************************************************************************/
43
44 struct aio_extra {
45         struct aio_extra *next, *prev;
46         SMB_STRUCT_AIOCB acb;
47         files_struct *fsp;
48         struct smb_request *smbreq;
49         DATA_BLOB outbuf;
50         struct lock_struct lock;
51         bool write_through;
52         int (*handle_completion)(struct aio_extra *ex, int errcode);
53 };
54
55 /****************************************************************************
56  Initialize the signal handler for aio read/write.
57 *****************************************************************************/
58
59 static void smbd_aio_signal_handler(struct tevent_context *ev_ctx,
60                                     struct tevent_signal *se,
61                                     int signum, int count,
62                                     void *_info, void *private_data)
63 {
64         siginfo_t *info = (siginfo_t *)_info;
65         struct aio_extra *aio_ex = (struct aio_extra *)
66                                 info->si_value.sival_ptr;
67
68         smbd_aio_complete_aio_ex(aio_ex);
69 }
70
71
72 static bool initialize_async_io_handler(void)
73 {
74         static bool tried_signal_setup = false;
75
76         if (aio_signal_event) {
77                 return true;
78         }
79         if (tried_signal_setup) {
80                 return false;
81         }
82         tried_signal_setup = true;
83
84         aio_signal_event = tevent_add_signal(server_event_context(),
85                                              server_event_context(),
86                                              RT_SIGNAL_AIO, SA_SIGINFO,
87                                              smbd_aio_signal_handler,
88                                              NULL);
89         if (!aio_signal_event) {
90                 DEBUG(10, ("Failed to setup RT_SIGNAL_AIO handler\n"));
91                 return false;
92         }
93
94         /* tevent supports 100 signal with SA_SIGINFO */
95         aio_pending_size = 100;
96         return true;
97 }
98
99 static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode);
100 static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode);
101 static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode);
102 static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode);
103
104 static int aio_extra_destructor(struct aio_extra *aio_ex)
105 {
106         DLIST_REMOVE(aio_list_head, aio_ex);
107         return 0;
108 }
109
110 /****************************************************************************
111  Create the extended aio struct we must keep around for the lifetime
112  of the aio call.
113 *****************************************************************************/
114
115 static struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx,
116                                         files_struct *fsp,
117                                         size_t buflen)
118 {
119         struct aio_extra *aio_ex = talloc_zero(mem_ctx, struct aio_extra);
120
121         if (!aio_ex) {
122                 return NULL;
123         }
124
125         /* The output buffer stored in the aio_ex is the start of
126            the smb return buffer. The buffer used in the acb
127            is the start of the reply data portion of that buffer. */
128
129         if (buflen) {
130                 aio_ex->outbuf = data_blob_talloc(aio_ex, NULL, buflen);
131                 if (!aio_ex->outbuf.data) {
132                         TALLOC_FREE(aio_ex);
133                         return NULL;
134                 }
135         }
136         DLIST_ADD(aio_list_head, aio_ex);
137         talloc_set_destructor(aio_ex, aio_extra_destructor);
138         aio_ex->fsp = fsp;
139         return aio_ex;
140 }
141
142 /****************************************************************************
143  Set up an aio request from a SMBreadX call.
144 *****************************************************************************/
145
146 NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
147                              struct smb_request *smbreq,
148                              files_struct *fsp, SMB_OFF_T startpos,
149                              size_t smb_maxcnt)
150 {
151         struct aio_extra *aio_ex;
152         SMB_STRUCT_AIOCB *a;
153         size_t bufsize;
154         size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
155         int ret;
156
157         /* Ensure aio is initialized. */
158         if (!initialize_async_io_handler()) {
159                 return NT_STATUS_RETRY;
160         }
161
162         if (fsp->base_fsp != NULL) {
163                 /* No AIO on streams yet */
164                 DEBUG(10, ("AIO on streams not yet supported\n"));
165                 return NT_STATUS_RETRY;
166         }
167
168         if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
169             && !SMB_VFS_AIO_FORCE(fsp)) {
170                 /* Too small a read for aio request. */
171                 DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small "
172                           "for minimum aio_read of %u\n",
173                           (unsigned int)smb_maxcnt,
174                           (unsigned int)min_aio_read_size ));
175                 return NT_STATUS_RETRY;
176         }
177
178         /* Only do this on non-chained and non-chaining reads not using the
179          * write cache. */
180         if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) {
181                 return NT_STATUS_RETRY;
182         }
183
184         if (outstanding_aio_calls >= aio_pending_size) {
185                 DEBUG(10,("schedule_aio_read_and_X: Already have %d aio "
186                           "activities outstanding.\n",
187                           outstanding_aio_calls ));
188                 return NT_STATUS_RETRY;
189         }
190
191         /* The following is safe from integer wrap as we've already checked
192            smb_maxcnt is 128k or less. Wct is 12 for read replies */
193
194         bufsize = smb_size + 12 * 2 + smb_maxcnt;
195
196         if ((aio_ex = create_aio_extra(NULL, fsp, bufsize)) == NULL) {
197                 DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
198                 return NT_STATUS_NO_MEMORY;
199         }
200         aio_ex->handle_completion = handle_aio_read_complete;
201
202         construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
203         srv_set_message((char *)aio_ex->outbuf.data, 12, 0, True);
204         SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
205
206         init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
207                 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
208                 &aio_ex->lock);
209
210         /* Take the lock until the AIO completes. */
211         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
212                 TALLOC_FREE(aio_ex);
213                 return NT_STATUS_FILE_LOCK_CONFLICT;
214         }
215
216         a = &aio_ex->acb;
217
218         /* Now set up the aio record for the read call. */
219
220         a->aio_fildes = fsp->fh->fd;
221         a->aio_buf = smb_buf(aio_ex->outbuf.data);
222         a->aio_nbytes = smb_maxcnt;
223         a->aio_offset = startpos;
224         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
225         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
226         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
227
228         ret = SMB_VFS_AIO_READ(fsp, a);
229         if (ret == -1) {
230                 DEBUG(0,("schedule_aio_read_and_X: aio_read failed. "
231                          "Error %s\n", strerror(errno) ));
232                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
233                 TALLOC_FREE(aio_ex);
234                 return NT_STATUS_RETRY;
235         }
236
237         outstanding_aio_calls++;
238         aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
239
240         DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, "
241                   "offset %.0f, len = %u (mid = %u)\n",
242                   fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
243                   (unsigned int)aio_ex->smbreq->mid ));
244
245         return NT_STATUS_OK;
246 }
247
248 /****************************************************************************
249  Set up an aio request from a SMBwriteX call.
250 *****************************************************************************/
251
252 NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
253                               struct smb_request *smbreq,
254                               files_struct *fsp, const char *data,
255                               SMB_OFF_T startpos,
256                               size_t numtowrite)
257 {
258         struct aio_extra *aio_ex;
259         SMB_STRUCT_AIOCB *a;
260         size_t bufsize;
261         size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
262         int ret;
263
264         /* Ensure aio is initialized. */
265         if (!initialize_async_io_handler()) {
266                 return NT_STATUS_RETRY;
267         }
268
269         if (fsp->base_fsp != NULL) {
270                 /* No AIO on streams yet */
271                 DEBUG(10, ("AIO on streams not yet supported\n"));
272                 return NT_STATUS_RETRY;
273         }
274
275         if ((!min_aio_write_size || (numtowrite < min_aio_write_size))
276             && !SMB_VFS_AIO_FORCE(fsp)) {
277                 /* Too small a write for aio request. */
278                 DEBUG(10,("schedule_aio_write_and_X: write size (%u) too "
279                           "small for minimum aio_write of %u\n",
280                           (unsigned int)numtowrite,
281                           (unsigned int)min_aio_write_size ));
282                 return NT_STATUS_RETRY;
283         }
284
285         /* Only do this on non-chained and non-chaining writes not using the
286          * write cache. */
287         if (req_is_in_chain(smbreq) || (lp_write_cache_size(SNUM(conn)) != 0)) {
288                 return NT_STATUS_RETRY;
289         }
290
291         if (outstanding_aio_calls >= aio_pending_size) {
292                 DEBUG(3,("schedule_aio_write_and_X: Already have %d aio "
293                          "activities outstanding.\n",
294                           outstanding_aio_calls ));
295                 DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
296                           "aio_write for file %s, offset %.0f, len = %u "
297                           "(mid = %u)\n",
298                           fsp_str_dbg(fsp), (double)startpos,
299                           (unsigned int)numtowrite,
300                           (unsigned int)smbreq->mid ));
301                 return NT_STATUS_RETRY;
302         }
303
304         bufsize = smb_size + 6*2;
305
306         if (!(aio_ex = create_aio_extra(NULL, fsp, bufsize))) {
307                 DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n"));
308                 return NT_STATUS_NO_MEMORY;
309         }
310         aio_ex->handle_completion = handle_aio_write_complete;
311         aio_ex->write_through = BITSETW(smbreq->vwv+7,0);
312
313         construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
314         srv_set_message((char *)aio_ex->outbuf.data, 6, 0, True);
315         SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
316
317         init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
318                 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
319                 &aio_ex->lock);
320
321         /* Take the lock until the AIO completes. */
322         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
323                 TALLOC_FREE(aio_ex);
324                 return NT_STATUS_FILE_LOCK_CONFLICT;
325         }
326
327         a = &aio_ex->acb;
328
329         /* Now set up the aio record for the write call. */
330
331         a->aio_fildes = fsp->fh->fd;
332         a->aio_buf = discard_const_p(char, data);
333         a->aio_nbytes = numtowrite;
334         a->aio_offset = startpos;
335         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
336         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
337         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
338
339         ret = SMB_VFS_AIO_WRITE(fsp, a);
340         if (ret == -1) {
341                 DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
342                          "Error %s\n", strerror(errno) ));
343                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
344                 TALLOC_FREE(aio_ex);
345                 return NT_STATUS_RETRY;
346         }
347
348         outstanding_aio_calls++;
349         aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
350
351         /* This should actually be improved to span the write. */
352         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
353         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
354
355         if (!aio_ex->write_through && !lp_syncalways(SNUM(fsp->conn))
356             && fsp->aio_write_behind) {
357                 /* Lie to the client and immediately claim we finished the
358                  * write. */
359                 SSVAL(aio_ex->outbuf.data,smb_vwv2,numtowrite);
360                 SSVAL(aio_ex->outbuf.data,smb_vwv4,(numtowrite>>16)&1);
361                 show_msg((char *)aio_ex->outbuf.data);
362                 if (!srv_send_smb(aio_ex->smbreq->sconn,
363                                 (char *)aio_ex->outbuf.data,
364                                 true, aio_ex->smbreq->seqnum+1,
365                                 IS_CONN_ENCRYPTED(fsp->conn),
366                                 &aio_ex->smbreq->pcd)) {
367                         exit_server_cleanly("schedule_aio_write_and_X: "
368                                             "srv_send_smb failed.");
369                 }
370                 DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
371                           "behind for file %s\n", fsp_str_dbg(fsp)));
372         }
373
374         DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file "
375                   "%s, offset %.0f, len = %u (mid = %u) "
376                   "outstanding_aio_calls = %d\n",
377                   fsp_str_dbg(fsp), (double)startpos, (unsigned int)numtowrite,
378                   (unsigned int)aio_ex->smbreq->mid, outstanding_aio_calls ));
379
380         return NT_STATUS_OK;
381 }
382
383 /****************************************************************************
384  Set up an aio request from a SMB2 read call.
385 *****************************************************************************/
386
387 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
388                                 struct smb_request *smbreq,
389                                 files_struct *fsp,
390                                 TALLOC_CTX *ctx,
391                                 DATA_BLOB *preadbuf,
392                                 SMB_OFF_T startpos,
393                                 size_t smb_maxcnt)
394 {
395         struct aio_extra *aio_ex;
396         SMB_STRUCT_AIOCB *a;
397         size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
398         int ret;
399
400         /* Ensure aio is initialized. */
401         if (!initialize_async_io_handler()) {
402                 return NT_STATUS_RETRY;
403         }
404
405         if (fsp->base_fsp != NULL) {
406                 /* No AIO on streams yet */
407                 DEBUG(10, ("AIO on streams not yet supported\n"));
408                 return NT_STATUS_RETRY;
409         }
410
411         if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
412             && !SMB_VFS_AIO_FORCE(fsp)) {
413                 /* Too small a read for aio request. */
414                 DEBUG(10,("smb2: read size (%u) too small "
415                         "for minimum aio_read of %u\n",
416                         (unsigned int)smb_maxcnt,
417                         (unsigned int)min_aio_read_size ));
418                 return NT_STATUS_RETRY;
419         }
420
421         /* Only do this on reads not using the write cache. */
422         if (lp_write_cache_size(SNUM(conn)) != 0) {
423                 return NT_STATUS_RETRY;
424         }
425
426         if (outstanding_aio_calls >= aio_pending_size) {
427                 DEBUG(10,("smb2: Already have %d aio "
428                         "activities outstanding.\n",
429                         outstanding_aio_calls ));
430                 return NT_STATUS_RETRY;
431         }
432
433         /* Create the out buffer. */
434         *preadbuf = data_blob_talloc(ctx, NULL, smb_maxcnt);
435         if (preadbuf->data == NULL) {
436                 return NT_STATUS_NO_MEMORY;
437         }
438
439         if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
440                 return NT_STATUS_NO_MEMORY;
441         }
442         aio_ex->handle_completion = handle_aio_smb2_read_complete;
443
444         init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
445                 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
446                 &aio_ex->lock);
447
448         /* Take the lock until the AIO completes. */
449         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
450                 TALLOC_FREE(aio_ex);
451                 return NT_STATUS_FILE_LOCK_CONFLICT;
452         }
453
454         a = &aio_ex->acb;
455
456         /* Now set up the aio record for the read call. */
457
458         a->aio_fildes = fsp->fh->fd;
459         a->aio_buf = preadbuf->data;
460         a->aio_nbytes = smb_maxcnt;
461         a->aio_offset = startpos;
462         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
463         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
464         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
465
466         ret = SMB_VFS_AIO_READ(fsp, a);
467         if (ret == -1) {
468                 DEBUG(0,("smb2: aio_read failed. "
469                         "Error %s\n", strerror(errno) ));
470                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
471                 TALLOC_FREE(aio_ex);
472                 return NT_STATUS_RETRY;
473         }
474
475         outstanding_aio_calls++;
476         /* We don't need talloc_move here as both aio_ex and
477          * smbreq are children of smbreq->smb2req. */
478         aio_ex->smbreq = smbreq;
479
480         DEBUG(10,("smb2: scheduled aio_read for file %s, "
481                 "offset %.0f, len = %u (mid = %u)\n",
482                 fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
483                 (unsigned int)aio_ex->smbreq->mid ));
484
485         return NT_STATUS_OK;
486 }
487
488 /****************************************************************************
489  Set up an aio request from a SMB2write call.
490 *****************************************************************************/
491
492 NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
493                                 struct smb_request *smbreq,
494                                 files_struct *fsp,
495                                 uint64_t in_offset,
496                                 DATA_BLOB in_data,
497                                 bool write_through)
498 {
499         struct aio_extra *aio_ex = NULL;
500         SMB_STRUCT_AIOCB *a = NULL;
501         size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
502         int ret;
503
504         /* Ensure aio is initialized. */
505         if (!initialize_async_io_handler()) {
506                 return NT_STATUS_RETRY;
507         }
508
509         if (fsp->base_fsp != NULL) {
510                 /* No AIO on streams yet */
511                 DEBUG(10, ("AIO on streams not yet supported\n"));
512                 return NT_STATUS_RETRY;
513         }
514
515         if ((!min_aio_write_size || (in_data.length < min_aio_write_size))
516             && !SMB_VFS_AIO_FORCE(fsp)) {
517                 /* Too small a write for aio request. */
518                 DEBUG(10,("smb2: write size (%u) too "
519                         "small for minimum aio_write of %u\n",
520                         (unsigned int)in_data.length,
521                         (unsigned int)min_aio_write_size ));
522                 return NT_STATUS_RETRY;
523         }
524
525         /* Only do this on writes not using the write cache. */
526         if (lp_write_cache_size(SNUM(conn)) != 0) {
527                 return NT_STATUS_RETRY;
528         }
529
530         if (outstanding_aio_calls >= aio_pending_size) {
531                 DEBUG(3,("smb2: Already have %d aio "
532                         "activities outstanding.\n",
533                         outstanding_aio_calls ));
534                 return NT_STATUS_RETRY;
535         }
536
537         if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
538                 return NT_STATUS_NO_MEMORY;
539         }
540
541         aio_ex->handle_completion = handle_aio_smb2_write_complete;
542         aio_ex->write_through = write_through;
543
544         init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
545                 in_offset, (uint64_t)in_data.length, WRITE_LOCK,
546                 &aio_ex->lock);
547
548         /* Take the lock until the AIO completes. */
549         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
550                 TALLOC_FREE(aio_ex);
551                 return NT_STATUS_FILE_LOCK_CONFLICT;
552         }
553
554         a = &aio_ex->acb;
555
556         /* Now set up the aio record for the write call. */
557
558         a->aio_fildes = fsp->fh->fd;
559         a->aio_buf = in_data.data;
560         a->aio_nbytes = in_data.length;
561         a->aio_offset = in_offset;
562         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
563         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
564         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
565
566         ret = SMB_VFS_AIO_WRITE(fsp, a);
567         if (ret == -1) {
568                 DEBUG(3,("smb2: aio_write failed. "
569                         "Error %s\n", strerror(errno) ));
570                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
571                 TALLOC_FREE(aio_ex);
572                 return NT_STATUS_RETRY;
573         }
574
575         outstanding_aio_calls++;
576         /* We don't need talloc_move here as both aio_ex and
577         * smbreq are children of smbreq->smb2req. */
578         aio_ex->smbreq = smbreq;
579
580         /* This should actually be improved to span the write. */
581         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
582         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
583
584         /*
585          * We don't want to do write behind due to ownership
586          * issues of the request structs. Maybe add it if I
587          * figure those out. JRA.
588          */
589
590         DEBUG(10,("smb2: scheduled aio_write for file "
591                 "%s, offset %.0f, len = %u (mid = %u) "
592                 "outstanding_aio_calls = %d\n",
593                 fsp_str_dbg(fsp),
594                 (double)in_offset,
595                 (unsigned int)in_data.length,
596                 (unsigned int)aio_ex->smbreq->mid,
597                 outstanding_aio_calls ));
598
599         return NT_STATUS_OK;
600 }
601
602 /****************************************************************************
603  Complete the read and return the data or error back to the client.
604  Returns errno or zero if all ok.
605 *****************************************************************************/
606
607 static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
608 {
609         int outsize;
610         char *outbuf = (char *)aio_ex->outbuf.data;
611         char *data = smb_buf(outbuf);
612         ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
613
614         if (nread < 0) {
615                 /* We're relying here on the fact that if the fd is
616                    closed then the aio will complete and aio_return
617                    will return an error. Hopefully this is
618                    true.... JRA. */
619
620                 DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d. "
621                            "Error = %s\n",
622                            fsp_str_dbg(aio_ex->fsp), (int)nread, strerror(errcode)));
623
624                 ERROR_NT(map_nt_error_from_unix(errcode));
625                 outsize = srv_set_message(outbuf,0,0,true);
626         } else {
627                 outsize = srv_set_message(outbuf,12,nread,False);
628                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */
629                 SSVAL(outbuf,smb_vwv5,nread);
630                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
631                 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
632                 SSVAL(smb_buf(outbuf),-2,nread);
633
634                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
635                 aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
636
637                 DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
638                             "nread=%d\n",
639                             fsp_str_dbg(aio_ex->fsp),
640                             (int)aio_ex->acb.aio_nbytes, (int)nread ) );
641
642         }
643         smb_setlen(outbuf,outsize - 4);
644         show_msg(outbuf);
645         if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
646                         true, aio_ex->smbreq->seqnum+1,
647                         IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) {
648                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
649                                     "failed.");
650         }
651
652         DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed "
653                   "for file %s, offset %.0f, len = %u\n",
654                   fsp_str_dbg(aio_ex->fsp), (double)aio_ex->acb.aio_offset,
655                   (unsigned int)nread ));
656
657         return errcode;
658 }
659
660 /****************************************************************************
661  Complete the write and return the data or error back to the client.
662  Returns error code or zero if all ok.
663 *****************************************************************************/
664
665 static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
666 {
667         files_struct *fsp = aio_ex->fsp;
668         char *outbuf = (char *)aio_ex->outbuf.data;
669         ssize_t numtowrite = aio_ex->acb.aio_nbytes;
670         ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
671
672         if (fsp->aio_write_behind) {
673                 if (nwritten != numtowrite) {
674                         if (nwritten == -1) {
675                                 DEBUG(5,("handle_aio_write_complete: "
676                                          "aio_write_behind failed ! File %s "
677                                          "is corrupt ! Error %s\n",
678                                          fsp_str_dbg(fsp), strerror(errcode)));
679                         } else {
680                                 DEBUG(0,("handle_aio_write_complete: "
681                                          "aio_write_behind failed ! File %s "
682                                          "is corrupt ! Wanted %u bytes but "
683                                          "only wrote %d\n", fsp_str_dbg(fsp),
684                                          (unsigned int)numtowrite,
685                                          (int)nwritten ));
686                                 errcode = EIO;
687                         }
688                 } else {
689                         DEBUG(10,("handle_aio_write_complete: "
690                                   "aio_write_behind completed for file %s\n",
691                                   fsp_str_dbg(fsp)));
692                 }
693                 /* TODO: should no return 0 in case of an error !!! */
694                 return 0;
695         }
696
697         /* We don't need outsize or set_message here as we've already set the
698            fixed size length when we set up the aio call. */
699
700         if(nwritten == -1) {
701                 DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. "
702                            "nwritten == %d. Error = %s\n",
703                            fsp_str_dbg(fsp), (unsigned int)numtowrite,
704                            (int)nwritten, strerror(errcode) ));
705
706                 ERROR_NT(map_nt_error_from_unix(errcode));
707                 srv_set_message(outbuf,0,0,true);
708         } else {
709                 NTSTATUS status;
710
711                 SSVAL(outbuf,smb_vwv2,nwritten);
712                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
713                 if (nwritten < (ssize_t)numtowrite) {
714                         SCVAL(outbuf,smb_rcls,ERRHRD);
715                         SSVAL(outbuf,smb_err,ERRdiskfull);
716                 }
717
718                 DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n",
719                          fsp->fnum, (int)numtowrite, (int)nwritten));
720                 status = sync_file(fsp->conn,fsp, aio_ex->write_through);
721                 if (!NT_STATUS_IS_OK(status)) {
722                         errcode = errno;
723                         ERROR_BOTH(map_nt_error_from_unix(errcode),
724                                    ERRHRD, ERRdiskfull);
725                         srv_set_message(outbuf,0,0,true);
726                         DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
727                                  fsp_str_dbg(fsp), nt_errstr(status)));
728                 }
729
730                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten;
731         }
732
733         show_msg(outbuf);
734         if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
735                           true, aio_ex->smbreq->seqnum+1,
736                           IS_CONN_ENCRYPTED(fsp->conn),
737                           NULL)) {
738                 exit_server_cleanly("handle_aio_write_complete: "
739                                     "srv_send_smb failed.");
740         }
741
742         DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
743                   "for file %s, offset %.0f, requested %u, written = %u\n",
744                   fsp_str_dbg(fsp), (double)aio_ex->acb.aio_offset,
745                   (unsigned int)numtowrite, (unsigned int)nwritten ));
746
747         return errcode;
748 }
749
750 /****************************************************************************
751  Complete the read and return the data or error back to the client.
752  Returns errno or zero if all ok.
753 *****************************************************************************/
754
755 static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode)
756 {
757         NTSTATUS status;
758         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
759         ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
760
761         /* Common error or success code processing for async or sync
762            read returns. */
763
764         status = smb2_read_complete(subreq, nread, errcode);
765
766         if (nread > 0) {
767                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
768                 aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
769         }
770
771         DEBUG(10,("smb2: scheduled aio_read completed "
772                 "for file %s, offset %.0f, len = %u "
773                 "(errcode = %d, NTSTATUS = %s)\n",
774                 fsp_str_dbg(aio_ex->fsp),
775                 (double)aio_ex->acb.aio_offset,
776                 (unsigned int)nread,
777                 errcode,
778                 nt_errstr(status) ));
779
780         if (!NT_STATUS_IS_OK(status)) {
781                 tevent_req_nterror(subreq, status);
782         }
783
784         tevent_req_done(subreq);
785         return errcode;
786 }
787
788 /****************************************************************************
789  Complete the SMB2 write and return the data or error back to the client.
790  Returns error code or zero if all ok.
791 *****************************************************************************/
792
793 static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode)
794 {
795         files_struct *fsp = aio_ex->fsp;
796         ssize_t numtowrite = aio_ex->acb.aio_nbytes;
797         ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
798         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
799         NTSTATUS status;
800
801         status = smb2_write_complete(subreq, nwritten, errcode);
802
803         DEBUG(10,("smb2: scheduled aio_write completed "
804                 "for file %s, offset %.0f, requested %u, "
805                 "written = %u (errcode = %d, NTSTATUS = %s)\n",
806                 fsp_str_dbg(fsp),
807                 (double)aio_ex->acb.aio_offset,
808                 (unsigned int)numtowrite,
809                 (unsigned int)nwritten,
810                 errcode,
811                 nt_errstr(status) ));
812
813         if (!NT_STATUS_IS_OK(status)) {
814                 tevent_req_nterror(subreq, status);
815         }
816
817         tevent_req_done(subreq);
818         return errcode;
819 }
820
821 /****************************************************************************
822  Handle any aio completion. Returns True if finished (and sets *perr if err
823  was non-zero), False if not.
824 *****************************************************************************/
825
826 static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr)
827 {
828         files_struct *fsp = NULL;
829         int err;
830
831         if(!aio_ex) {
832                 DEBUG(3, ("handle_aio_completed: Non-existing aio_ex passed\n"));
833                 return false;
834         }
835
836         fsp = aio_ex->fsp;
837
838         /* Ensure the operation has really completed. */
839         err = SMB_VFS_AIO_ERROR(fsp, &aio_ex->acb);
840         if (err == EINPROGRESS) {
841                 DEBUG(10,( "handle_aio_completed: operation mid %llu still in "
842                         "process for file %s\n",
843                         (unsigned long long)aio_ex->smbreq->mid,
844                         fsp_str_dbg(aio_ex->fsp)));
845                 return False;
846         }
847
848         /* Unlock now we're done. */
849         SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
850
851         if (err == ECANCELED) {
852                 /* If error is ECANCELED then don't return anything to the
853                  * client. */
854                 DEBUG(10,( "handle_aio_completed: operation mid %llu"
855                         " canceled\n",
856                         (unsigned long long)aio_ex->smbreq->mid));
857                 return True;
858         }
859
860         err = aio_ex->handle_completion(aio_ex, err);
861         if (err) {
862                 *perr = err; /* Only save non-zero errors. */
863         }
864
865         return True;
866 }
867
868 /****************************************************************************
869  Handle any aio completion inline.
870 *****************************************************************************/
871
872 void smbd_aio_complete_aio_ex(struct aio_extra *aio_ex)
873 {
874         files_struct *fsp = NULL;
875         int ret = 0;
876
877         outstanding_aio_calls--;
878
879         DEBUG(10,("smbd_aio_complete_mid: mid[%llu]\n",
880                 (unsigned long long)aio_ex->smbreq->mid));
881
882         fsp = aio_ex->fsp;
883         if (fsp == NULL) {
884                 /* file was closed whilst I/O was outstanding. Just
885                  * ignore. */
886                 DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
887                         "aio outstanding (mid[%llu]).\n",
888                         (unsigned long long)aio_ex->smbreq->mid));
889                 return;
890         }
891
892         if (!handle_aio_completed(aio_ex, &ret)) {
893                 return;
894         }
895
896         TALLOC_FREE(aio_ex);
897 }
898
899 /****************************************************************************
900  We're doing write behind and the client closed the file. Wait up to 30
901  seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes
902  completed, errno to return if not.
903 *****************************************************************************/
904
905 #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29
906
907 int wait_for_aio_completion(files_struct *fsp)
908 {
909         struct aio_extra *aio_ex;
910         const SMB_STRUCT_AIOCB **aiocb_list;
911         int aio_completion_count = 0;
912         time_t start_time = time_mono(NULL);
913         int seconds_left;
914
915         for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT;
916              seconds_left >= 0;) {
917                 int err = 0;
918                 int i;
919                 struct timespec ts;
920
921                 aio_completion_count = 0;
922                 for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
923                         if (aio_ex->fsp == fsp) {
924                                 aio_completion_count++;
925                         }
926                 }
927
928                 if (!aio_completion_count) {
929                         return 0;
930                 }
931
932                 DEBUG(3,("wait_for_aio_completion: waiting for %d aio events "
933                          "to complete.\n", aio_completion_count ));
934
935                 aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *,
936                                               aio_completion_count);
937                 if (!aiocb_list) {
938                         return ENOMEM;
939                 }
940
941                 for( i = 0, aio_ex = aio_list_head;
942                      aio_ex;
943                      aio_ex = aio_ex->next) {
944                         if (aio_ex->fsp == fsp) {
945                                 aiocb_list[i++] = &aio_ex->acb;
946                         }
947                 }
948
949                 /* Now wait up to seconds_left for completion. */
950                 ts.tv_sec = seconds_left;
951                 ts.tv_nsec = 0;
952
953                 DEBUG(10,("wait_for_aio_completion: %d events, doing a wait "
954                           "of %d seconds.\n",
955                           aio_completion_count, seconds_left ));
956
957                 err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list,
958                                           aio_completion_count, &ts);
959
960                 DEBUG(10,("wait_for_aio_completion: returned err = %d, "
961                           "errno = %s\n", err, strerror(errno) ));
962
963                 if (err == -1 && errno == EAGAIN) {
964                         DEBUG(0,("wait_for_aio_completion: aio_suspend timed "
965                                  "out waiting for %d events after a wait of "
966                                  "%d seconds\n", aio_completion_count,
967                                  seconds_left));
968                         /* Timeout. */
969                         cancel_aio_by_fsp(fsp);
970                         SAFE_FREE(aiocb_list);
971                         return EIO;
972                 }
973
974                 /* One or more events might have completed - process them if
975                  * so. */
976                 for( i = 0; i < aio_completion_count; i++) {
977                         aio_ex = (struct aio_extra *)aiocb_list[i]->aio_sigevent.sigev_value.sival_ptr;
978
979                         if (!handle_aio_completed(aio_ex, &err)) {
980                                 continue;
981                         }
982                         TALLOC_FREE(aio_ex);
983                 }
984
985                 SAFE_FREE(aiocb_list);
986                 seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT
987                         - (time_mono(NULL) - start_time);
988         }
989
990         /* We timed out - we don't know why. Return ret if already an error,
991          * else EIO. */
992         DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting "
993                   "for %d events\n",
994                   aio_completion_count));
995
996         return EIO;
997 }
998
999 /****************************************************************************
1000  Cancel any outstanding aio requests. The client doesn't care about the reply.
1001 *****************************************************************************/
1002
1003 void cancel_aio_by_fsp(files_struct *fsp)
1004 {
1005         struct aio_extra *aio_ex;
1006
1007         for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
1008                 if (aio_ex->fsp == fsp) {
1009                         /* Unlock now we're done. */
1010                         SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
1011
1012                         /* Don't delete the aio_extra record as we may have
1013                            completed and don't yet know it. Just do the
1014                            aio_cancel call and return. */
1015                         SMB_VFS_AIO_CANCEL(fsp, &aio_ex->acb);
1016                         aio_ex->fsp = NULL; /* fsp will be closed when we
1017                                              * return. */
1018                 }
1019         }
1020 }
1021
1022 #else
1023 NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
1024                              struct smb_request *smbreq,
1025                              files_struct *fsp, SMB_OFF_T startpos,
1026                              size_t smb_maxcnt)
1027 {
1028         return NT_STATUS_RETRY;
1029 }
1030
1031 NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
1032                               struct smb_request *smbreq,
1033                               files_struct *fsp, const char *data,
1034                               SMB_OFF_T startpos,
1035                               size_t numtowrite)
1036 {
1037         return NT_STATUS_RETRY;
1038 }
1039
1040 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
1041                                 struct smb_request *smbreq,
1042                                 files_struct *fsp,
1043                                 TALLOC_CTX *ctx,
1044                                 DATA_BLOB *preadbuf,
1045                                 SMB_OFF_T startpos,
1046                                 size_t smb_maxcnt)
1047 {
1048         return NT_STATUS_RETRY;
1049 }
1050
1051 NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
1052                                 struct smb_request *smbreq,
1053                                 files_struct *fsp,
1054                                 uint64_t in_offset,
1055                                 DATA_BLOB in_data,
1056                                 bool write_through)
1057 {
1058         return NT_STATUS_RETRY;
1059 }
1060
1061 void cancel_aio_by_fsp(files_struct *fsp)
1062 {
1063 }
1064
1065 int wait_for_aio_completion(files_struct *fsp)
1066 {
1067         return 0;
1068 }
1069
1070 void smbd_aio_complete_mid(uint64_t mid);
1071
1072 #endif