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