s3:smbd/aio: add cancel_smb2_aio()
[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 bool cancel_smb2_aio(struct smb_request *smbreq)
384 {
385         struct smbd_smb2_request *smb2req = smbreq->smb2req;
386         struct aio_extra *aio_ex = NULL;
387         int ret;
388
389         if (smbreq) {
390                 smb2req = smbreq->smb2req;
391         }
392
393         if (smb2req) {
394                 aio_ex = talloc_get_type(smbreq->async_priv,
395                                          struct aio_extra);
396         }
397
398         if (aio_ex == NULL) {
399                 return false;
400         }
401
402         if (aio_ex->fsp == NULL) {
403                 return false;
404         }
405
406         ret = SMB_VFS_AIO_CANCEL(aio_ex->fsp, &aio_ex->acb);
407         if (ret != AIO_CANCELED) {
408                 return false;
409         }
410
411         return true;
412 }
413
414 /****************************************************************************
415  Set up an aio request from a SMB2 read call.
416 *****************************************************************************/
417
418 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
419                                 struct smb_request *smbreq,
420                                 files_struct *fsp,
421                                 TALLOC_CTX *ctx,
422                                 DATA_BLOB *preadbuf,
423                                 SMB_OFF_T startpos,
424                                 size_t smb_maxcnt)
425 {
426         struct aio_extra *aio_ex;
427         SMB_STRUCT_AIOCB *a;
428         size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
429         int ret;
430
431         /* Ensure aio is initialized. */
432         if (!initialize_async_io_handler()) {
433                 return NT_STATUS_RETRY;
434         }
435
436         if (fsp->base_fsp != NULL) {
437                 /* No AIO on streams yet */
438                 DEBUG(10, ("AIO on streams not yet supported\n"));
439                 return NT_STATUS_RETRY;
440         }
441
442         if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
443             && !SMB_VFS_AIO_FORCE(fsp)) {
444                 /* Too small a read for aio request. */
445                 DEBUG(10,("smb2: read size (%u) too small "
446                         "for minimum aio_read of %u\n",
447                         (unsigned int)smb_maxcnt,
448                         (unsigned int)min_aio_read_size ));
449                 return NT_STATUS_RETRY;
450         }
451
452         /* Only do this on reads not using the write cache. */
453         if (lp_write_cache_size(SNUM(conn)) != 0) {
454                 return NT_STATUS_RETRY;
455         }
456
457         if (outstanding_aio_calls >= aio_pending_size) {
458                 DEBUG(10,("smb2: Already have %d aio "
459                         "activities outstanding.\n",
460                         outstanding_aio_calls ));
461                 return NT_STATUS_RETRY;
462         }
463
464         /* Create the out buffer. */
465         *preadbuf = data_blob_talloc(ctx, NULL, smb_maxcnt);
466         if (preadbuf->data == NULL) {
467                 return NT_STATUS_NO_MEMORY;
468         }
469
470         if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
471                 return NT_STATUS_NO_MEMORY;
472         }
473         aio_ex->handle_completion = handle_aio_smb2_read_complete;
474
475         init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
476                 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
477                 &aio_ex->lock);
478
479         /* Take the lock until the AIO completes. */
480         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
481                 TALLOC_FREE(aio_ex);
482                 return NT_STATUS_FILE_LOCK_CONFLICT;
483         }
484
485         a = &aio_ex->acb;
486
487         /* Now set up the aio record for the read call. */
488
489         a->aio_fildes = fsp->fh->fd;
490         a->aio_buf = preadbuf->data;
491         a->aio_nbytes = smb_maxcnt;
492         a->aio_offset = startpos;
493         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
494         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
495         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
496
497         ret = SMB_VFS_AIO_READ(fsp, a);
498         if (ret == -1) {
499                 DEBUG(0,("smb2: aio_read failed. "
500                         "Error %s\n", strerror(errno) ));
501                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
502                 TALLOC_FREE(aio_ex);
503                 return NT_STATUS_RETRY;
504         }
505
506         outstanding_aio_calls++;
507         /* We don't need talloc_move here as both aio_ex and
508          * smbreq are children of smbreq->smb2req. */
509         aio_ex->smbreq = smbreq;
510         smbreq->async_priv = aio_ex;
511
512         DEBUG(10,("smb2: scheduled aio_read for file %s, "
513                 "offset %.0f, len = %u (mid = %u)\n",
514                 fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
515                 (unsigned int)aio_ex->smbreq->mid ));
516
517         return NT_STATUS_OK;
518 }
519
520 /****************************************************************************
521  Set up an aio request from a SMB2write call.
522 *****************************************************************************/
523
524 NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
525                                 struct smb_request *smbreq,
526                                 files_struct *fsp,
527                                 uint64_t in_offset,
528                                 DATA_BLOB in_data,
529                                 bool write_through)
530 {
531         struct aio_extra *aio_ex = NULL;
532         SMB_STRUCT_AIOCB *a = NULL;
533         size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
534         int ret;
535
536         /* Ensure aio is initialized. */
537         if (!initialize_async_io_handler()) {
538                 return NT_STATUS_RETRY;
539         }
540
541         if (fsp->base_fsp != NULL) {
542                 /* No AIO on streams yet */
543                 DEBUG(10, ("AIO on streams not yet supported\n"));
544                 return NT_STATUS_RETRY;
545         }
546
547         if ((!min_aio_write_size || (in_data.length < min_aio_write_size))
548             && !SMB_VFS_AIO_FORCE(fsp)) {
549                 /* Too small a write for aio request. */
550                 DEBUG(10,("smb2: write size (%u) too "
551                         "small for minimum aio_write of %u\n",
552                         (unsigned int)in_data.length,
553                         (unsigned int)min_aio_write_size ));
554                 return NT_STATUS_RETRY;
555         }
556
557         /* Only do this on writes not using the write cache. */
558         if (lp_write_cache_size(SNUM(conn)) != 0) {
559                 return NT_STATUS_RETRY;
560         }
561
562         if (outstanding_aio_calls >= aio_pending_size) {
563                 DEBUG(3,("smb2: Already have %d aio "
564                         "activities outstanding.\n",
565                         outstanding_aio_calls ));
566                 return NT_STATUS_RETRY;
567         }
568
569         if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
570                 return NT_STATUS_NO_MEMORY;
571         }
572
573         aio_ex->handle_completion = handle_aio_smb2_write_complete;
574         aio_ex->write_through = write_through;
575
576         init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
577                 in_offset, (uint64_t)in_data.length, WRITE_LOCK,
578                 &aio_ex->lock);
579
580         /* Take the lock until the AIO completes. */
581         if (!SMB_VFS_STRICT_LOCK(conn, fsp, &aio_ex->lock)) {
582                 TALLOC_FREE(aio_ex);
583                 return NT_STATUS_FILE_LOCK_CONFLICT;
584         }
585
586         a = &aio_ex->acb;
587
588         /* Now set up the aio record for the write call. */
589
590         a->aio_fildes = fsp->fh->fd;
591         a->aio_buf = in_data.data;
592         a->aio_nbytes = in_data.length;
593         a->aio_offset = in_offset;
594         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
595         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
596         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
597
598         ret = SMB_VFS_AIO_WRITE(fsp, a);
599         if (ret == -1) {
600                 DEBUG(3,("smb2: aio_write failed. "
601                         "Error %s\n", strerror(errno) ));
602                 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
603                 TALLOC_FREE(aio_ex);
604                 return NT_STATUS_RETRY;
605         }
606
607         outstanding_aio_calls++;
608         /* We don't need talloc_move here as both aio_ex and
609         * smbreq are children of smbreq->smb2req. */
610         aio_ex->smbreq = smbreq;
611         smbreq->async_priv = aio_ex;
612
613         /* This should actually be improved to span the write. */
614         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
615         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
616
617         /*
618          * We don't want to do write behind due to ownership
619          * issues of the request structs. Maybe add it if I
620          * figure those out. JRA.
621          */
622
623         DEBUG(10,("smb2: scheduled aio_write for file "
624                 "%s, offset %.0f, len = %u (mid = %u) "
625                 "outstanding_aio_calls = %d\n",
626                 fsp_str_dbg(fsp),
627                 (double)in_offset,
628                 (unsigned int)in_data.length,
629                 (unsigned int)aio_ex->smbreq->mid,
630                 outstanding_aio_calls ));
631
632         return NT_STATUS_OK;
633 }
634
635 /****************************************************************************
636  Complete the read and return the data or error back to the client.
637  Returns errno or zero if all ok.
638 *****************************************************************************/
639
640 static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
641 {
642         int outsize;
643         char *outbuf = (char *)aio_ex->outbuf.data;
644         char *data = smb_buf(outbuf);
645         ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
646
647         if (nread < 0) {
648                 /* We're relying here on the fact that if the fd is
649                    closed then the aio will complete and aio_return
650                    will return an error. Hopefully this is
651                    true.... JRA. */
652
653                 DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d. "
654                            "Error = %s\n",
655                            fsp_str_dbg(aio_ex->fsp), (int)nread, strerror(errcode)));
656
657                 ERROR_NT(map_nt_error_from_unix(errcode));
658                 outsize = srv_set_message(outbuf,0,0,true);
659         } else {
660                 outsize = srv_set_message(outbuf,12,nread,False);
661                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */
662                 SSVAL(outbuf,smb_vwv5,nread);
663                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
664                 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
665                 SSVAL(smb_buf(outbuf),-2,nread);
666
667                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
668                 aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
669
670                 DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
671                             "nread=%d\n",
672                             fsp_str_dbg(aio_ex->fsp),
673                             (int)aio_ex->acb.aio_nbytes, (int)nread ) );
674
675         }
676         smb_setlen(outbuf,outsize - 4);
677         show_msg(outbuf);
678         if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
679                         true, aio_ex->smbreq->seqnum+1,
680                         IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) {
681                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
682                                     "failed.");
683         }
684
685         DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed "
686                   "for file %s, offset %.0f, len = %u\n",
687                   fsp_str_dbg(aio_ex->fsp), (double)aio_ex->acb.aio_offset,
688                   (unsigned int)nread ));
689
690         return errcode;
691 }
692
693 /****************************************************************************
694  Complete the write and return the data or error back to the client.
695  Returns error code or zero if all ok.
696 *****************************************************************************/
697
698 static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
699 {
700         files_struct *fsp = aio_ex->fsp;
701         char *outbuf = (char *)aio_ex->outbuf.data;
702         ssize_t numtowrite = aio_ex->acb.aio_nbytes;
703         ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
704
705         if (fsp->aio_write_behind) {
706                 if (nwritten != numtowrite) {
707                         if (nwritten == -1) {
708                                 DEBUG(5,("handle_aio_write_complete: "
709                                          "aio_write_behind failed ! File %s "
710                                          "is corrupt ! Error %s\n",
711                                          fsp_str_dbg(fsp), strerror(errcode)));
712                         } else {
713                                 DEBUG(0,("handle_aio_write_complete: "
714                                          "aio_write_behind failed ! File %s "
715                                          "is corrupt ! Wanted %u bytes but "
716                                          "only wrote %d\n", fsp_str_dbg(fsp),
717                                          (unsigned int)numtowrite,
718                                          (int)nwritten ));
719                                 errcode = EIO;
720                         }
721                 } else {
722                         DEBUG(10,("handle_aio_write_complete: "
723                                   "aio_write_behind completed for file %s\n",
724                                   fsp_str_dbg(fsp)));
725                 }
726                 /* TODO: should no return 0 in case of an error !!! */
727                 return 0;
728         }
729
730         /* We don't need outsize or set_message here as we've already set the
731            fixed size length when we set up the aio call. */
732
733         if(nwritten == -1) {
734                 DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. "
735                            "nwritten == %d. Error = %s\n",
736                            fsp_str_dbg(fsp), (unsigned int)numtowrite,
737                            (int)nwritten, strerror(errcode) ));
738
739                 ERROR_NT(map_nt_error_from_unix(errcode));
740                 srv_set_message(outbuf,0,0,true);
741         } else {
742                 NTSTATUS status;
743
744                 SSVAL(outbuf,smb_vwv2,nwritten);
745                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
746                 if (nwritten < (ssize_t)numtowrite) {
747                         SCVAL(outbuf,smb_rcls,ERRHRD);
748                         SSVAL(outbuf,smb_err,ERRdiskfull);
749                 }
750
751                 DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n",
752                          fsp->fnum, (int)numtowrite, (int)nwritten));
753                 status = sync_file(fsp->conn,fsp, aio_ex->write_through);
754                 if (!NT_STATUS_IS_OK(status)) {
755                         errcode = errno;
756                         ERROR_BOTH(map_nt_error_from_unix(errcode),
757                                    ERRHRD, ERRdiskfull);
758                         srv_set_message(outbuf,0,0,true);
759                         DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
760                                  fsp_str_dbg(fsp), nt_errstr(status)));
761                 }
762
763                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten;
764         }
765
766         show_msg(outbuf);
767         if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
768                           true, aio_ex->smbreq->seqnum+1,
769                           IS_CONN_ENCRYPTED(fsp->conn),
770                           NULL)) {
771                 exit_server_cleanly("handle_aio_write_complete: "
772                                     "srv_send_smb failed.");
773         }
774
775         DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
776                   "for file %s, offset %.0f, requested %u, written = %u\n",
777                   fsp_str_dbg(fsp), (double)aio_ex->acb.aio_offset,
778                   (unsigned int)numtowrite, (unsigned int)nwritten ));
779
780         return errcode;
781 }
782
783 /****************************************************************************
784  Complete the read and return the data or error back to the client.
785  Returns errno or zero if all ok.
786 *****************************************************************************/
787
788 static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode)
789 {
790         NTSTATUS status;
791         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
792         ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
793
794         /* Common error or success code processing for async or sync
795            read returns. */
796
797         status = smb2_read_complete(subreq, nread, errcode);
798
799         if (nread > 0) {
800                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
801                 aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
802         }
803
804         DEBUG(10,("smb2: scheduled aio_read completed "
805                 "for file %s, offset %.0f, len = %u "
806                 "(errcode = %d, NTSTATUS = %s)\n",
807                 fsp_str_dbg(aio_ex->fsp),
808                 (double)aio_ex->acb.aio_offset,
809                 (unsigned int)nread,
810                 errcode,
811                 nt_errstr(status) ));
812
813         if (!NT_STATUS_IS_OK(status)) {
814                 tevent_req_nterror(subreq, status);
815                 return errcode;
816         }
817
818         tevent_req_done(subreq);
819         return errcode;
820 }
821
822 /****************************************************************************
823  Complete the SMB2 write and return the data or error back to the client.
824  Returns error code or zero if all ok.
825 *****************************************************************************/
826
827 static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode)
828 {
829         files_struct *fsp = aio_ex->fsp;
830         ssize_t numtowrite = aio_ex->acb.aio_nbytes;
831         ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
832         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
833         NTSTATUS status;
834
835         status = smb2_write_complete(subreq, nwritten, errcode);
836
837         DEBUG(10,("smb2: scheduled aio_write completed "
838                 "for file %s, offset %.0f, requested %u, "
839                 "written = %u (errcode = %d, NTSTATUS = %s)\n",
840                 fsp_str_dbg(fsp),
841                 (double)aio_ex->acb.aio_offset,
842                 (unsigned int)numtowrite,
843                 (unsigned int)nwritten,
844                 errcode,
845                 nt_errstr(status) ));
846
847         if (!NT_STATUS_IS_OK(status)) {
848                 tevent_req_nterror(subreq, status);
849                 return errcode;
850         }
851
852         tevent_req_done(subreq);
853         return errcode;
854 }
855
856 /****************************************************************************
857  Handle any aio completion. Returns True if finished (and sets *perr if err
858  was non-zero), False if not.
859 *****************************************************************************/
860
861 static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr)
862 {
863         files_struct *fsp = NULL;
864         int err;
865
866         if(!aio_ex) {
867                 DEBUG(3, ("handle_aio_completed: Non-existing aio_ex passed\n"));
868                 return false;
869         }
870
871         fsp = aio_ex->fsp;
872
873         /* Ensure the operation has really completed. */
874         err = SMB_VFS_AIO_ERROR(fsp, &aio_ex->acb);
875         if (err == EINPROGRESS) {
876                 DEBUG(10,( "handle_aio_completed: operation mid %llu still in "
877                         "process for file %s\n",
878                         (unsigned long long)aio_ex->smbreq->mid,
879                         fsp_str_dbg(aio_ex->fsp)));
880                 return False;
881         }
882
883         /* Unlock now we're done. */
884         SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
885
886         if (err == ECANCELED) {
887                 /* If error is ECANCELED then don't return anything to the
888                  * client. */
889                 DEBUG(10,( "handle_aio_completed: operation mid %llu"
890                         " canceled\n",
891                         (unsigned long long)aio_ex->smbreq->mid));
892                 return True;
893         }
894
895         err = aio_ex->handle_completion(aio_ex, err);
896         if (err) {
897                 *perr = err; /* Only save non-zero errors. */
898         }
899
900         return True;
901 }
902
903 /****************************************************************************
904  Handle any aio completion inline.
905 *****************************************************************************/
906
907 void smbd_aio_complete_aio_ex(struct aio_extra *aio_ex)
908 {
909         files_struct *fsp = NULL;
910         int ret = 0;
911
912         outstanding_aio_calls--;
913
914         DEBUG(10,("smbd_aio_complete_mid: mid[%llu]\n",
915                 (unsigned long long)aio_ex->smbreq->mid));
916
917         fsp = aio_ex->fsp;
918         if (fsp == NULL) {
919                 /* file was closed whilst I/O was outstanding. Just
920                  * ignore. */
921                 DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
922                         "aio outstanding (mid[%llu]).\n",
923                         (unsigned long long)aio_ex->smbreq->mid));
924                 return;
925         }
926
927         if (!handle_aio_completed(aio_ex, &ret)) {
928                 return;
929         }
930
931         TALLOC_FREE(aio_ex);
932 }
933
934 /****************************************************************************
935  We're doing write behind and the client closed the file. Wait up to 30
936  seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes
937  completed, errno to return if not.
938 *****************************************************************************/
939
940 #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29
941
942 int wait_for_aio_completion(files_struct *fsp)
943 {
944         struct aio_extra *aio_ex;
945         const SMB_STRUCT_AIOCB **aiocb_list;
946         int aio_completion_count = 0;
947         time_t start_time = time_mono(NULL);
948         int seconds_left;
949
950         for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT;
951              seconds_left >= 0;) {
952                 int err = 0;
953                 int i;
954                 struct timespec ts;
955
956                 aio_completion_count = 0;
957                 for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
958                         if (aio_ex->fsp == fsp) {
959                                 aio_completion_count++;
960                         }
961                 }
962
963                 if (!aio_completion_count) {
964                         return 0;
965                 }
966
967                 DEBUG(3,("wait_for_aio_completion: waiting for %d aio events "
968                          "to complete.\n", aio_completion_count ));
969
970                 aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *,
971                                               aio_completion_count);
972                 if (!aiocb_list) {
973                         return ENOMEM;
974                 }
975
976                 for( i = 0, aio_ex = aio_list_head;
977                      aio_ex;
978                      aio_ex = aio_ex->next) {
979                         if (aio_ex->fsp == fsp) {
980                                 aiocb_list[i++] = &aio_ex->acb;
981                         }
982                 }
983
984                 /* Now wait up to seconds_left for completion. */
985                 ts.tv_sec = seconds_left;
986                 ts.tv_nsec = 0;
987
988                 DEBUG(10,("wait_for_aio_completion: %d events, doing a wait "
989                           "of %d seconds.\n",
990                           aio_completion_count, seconds_left ));
991
992                 err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list,
993                                           aio_completion_count, &ts);
994
995                 DEBUG(10,("wait_for_aio_completion: returned err = %d, "
996                           "errno = %s\n", err, strerror(errno) ));
997
998                 if (err == -1 && errno == EAGAIN) {
999                         DEBUG(0,("wait_for_aio_completion: aio_suspend timed "
1000                                  "out waiting for %d events after a wait of "
1001                                  "%d seconds\n", aio_completion_count,
1002                                  seconds_left));
1003                         /* Timeout. */
1004                         cancel_aio_by_fsp(fsp);
1005                         SAFE_FREE(aiocb_list);
1006                         return EIO;
1007                 }
1008
1009                 /* One or more events might have completed - process them if
1010                  * so. */
1011                 for( i = 0; i < aio_completion_count; i++) {
1012                         aio_ex = (struct aio_extra *)aiocb_list[i]->aio_sigevent.sigev_value.sival_ptr;
1013
1014                         if (!handle_aio_completed(aio_ex, &err)) {
1015                                 continue;
1016                         }
1017                         TALLOC_FREE(aio_ex);
1018                 }
1019
1020                 SAFE_FREE(aiocb_list);
1021                 seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT
1022                         - (time_mono(NULL) - start_time);
1023         }
1024
1025         /* We timed out - we don't know why. Return ret if already an error,
1026          * else EIO. */
1027         DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting "
1028                   "for %d events\n",
1029                   aio_completion_count));
1030
1031         return EIO;
1032 }
1033
1034 /****************************************************************************
1035  Cancel any outstanding aio requests. The client doesn't care about the reply.
1036 *****************************************************************************/
1037
1038 void cancel_aio_by_fsp(files_struct *fsp)
1039 {
1040         struct aio_extra *aio_ex;
1041
1042         for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
1043                 if (aio_ex->fsp == fsp) {
1044                         /* Unlock now we're done. */
1045                         SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
1046
1047                         /* Don't delete the aio_extra record as we may have
1048                            completed and don't yet know it. Just do the
1049                            aio_cancel call and return. */
1050                         SMB_VFS_AIO_CANCEL(fsp, &aio_ex->acb);
1051                         aio_ex->fsp = NULL; /* fsp will be closed when we
1052                                              * return. */
1053                 }
1054         }
1055 }
1056
1057 #else
1058 NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
1059                              struct smb_request *smbreq,
1060                              files_struct *fsp, SMB_OFF_T startpos,
1061                              size_t smb_maxcnt)
1062 {
1063         return NT_STATUS_RETRY;
1064 }
1065
1066 NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
1067                               struct smb_request *smbreq,
1068                               files_struct *fsp, const char *data,
1069                               SMB_OFF_T startpos,
1070                               size_t numtowrite)
1071 {
1072         return NT_STATUS_RETRY;
1073 }
1074
1075 bool cancel_smb2_aio(struct smb_request *smbreq)
1076 {
1077         return false;
1078 }
1079
1080 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
1081                                 struct smb_request *smbreq,
1082                                 files_struct *fsp,
1083                                 TALLOC_CTX *ctx,
1084                                 DATA_BLOB *preadbuf,
1085                                 SMB_OFF_T startpos,
1086                                 size_t smb_maxcnt)
1087 {
1088         return NT_STATUS_RETRY;
1089 }
1090
1091 NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
1092                                 struct smb_request *smbreq,
1093                                 files_struct *fsp,
1094                                 uint64_t in_offset,
1095                                 DATA_BLOB in_data,
1096                                 bool write_through)
1097 {
1098         return NT_STATUS_RETRY;
1099 }
1100
1101 void cancel_aio_by_fsp(files_struct *fsp)
1102 {
1103 }
1104
1105 int wait_for_aio_completion(files_struct *fsp)
1106 {
1107         return 0;
1108 }
1109
1110 void smbd_aio_complete_mid(uint64_t mid);
1111
1112 #endif