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