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