8ac3ef7278ec30348c7742f6049f39350e31dd06
[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 #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 and don't try to cancel it which means
626          * processing of the SMB2 request must continue as normal, cf MS-SMB2
627          * 3.3.5.16:
628          *
629          *   If the target request is not successfully canceled, processing of
630          *   the target request MUST continue and no response is sent to the
631          *   cancel request.
632          */
633
634         return false;
635 }
636
637 static void aio_pread_smb2_done(struct tevent_req *req);
638
639 /****************************************************************************
640  Set up an aio request from a SMB2 read call.
641 *****************************************************************************/
642
643 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
644                                 struct smb_request *smbreq,
645                                 files_struct *fsp,
646                                 TALLOC_CTX *ctx,
647                                 DATA_BLOB *preadbuf,
648                                 off_t startpos,
649                                 size_t smb_maxcnt)
650 {
651         struct aio_extra *aio_ex;
652         size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
653         struct tevent_req *req;
654
655         if (fsp->base_fsp != NULL) {
656                 /* No AIO on streams yet */
657                 DEBUG(10, ("AIO on streams not yet supported\n"));
658                 return NT_STATUS_RETRY;
659         }
660
661         if (fsp->op == NULL) {
662                 /* No AIO on internal opens. */
663                 return NT_STATUS_RETRY;
664         }
665
666         if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
667             && !SMB_VFS_AIO_FORCE(fsp)) {
668                 /* Too small a read for aio request. */
669                 DEBUG(10,("smb2: read size (%u) too small "
670                         "for minimum aio_read of %u\n",
671                         (unsigned int)smb_maxcnt,
672                         (unsigned int)min_aio_read_size ));
673                 return NT_STATUS_RETRY;
674         }
675
676         /* Only do this on reads not using the write cache. */
677         if (lp_write_cache_size(SNUM(conn)) != 0) {
678                 return NT_STATUS_RETRY;
679         }
680
681         if (smbd_smb2_is_compound(smbreq->smb2req)) {
682                 return NT_STATUS_RETRY;
683         }
684
685         /* Create the out buffer. */
686         *preadbuf = data_blob_talloc(ctx, NULL, smb_maxcnt);
687         if (preadbuf->data == NULL) {
688                 return NT_STATUS_NO_MEMORY;
689         }
690
691         if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
692                 return NT_STATUS_NO_MEMORY;
693         }
694
695         init_strict_lock_struct(fsp, fsp->op->global->open_persistent_id,
696                 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
697                 &aio_ex->lock);
698
699         /* Take the lock until the AIO completes. */
700         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &aio_ex->lock)) {
701                 TALLOC_FREE(aio_ex);
702                 return NT_STATUS_FILE_LOCK_CONFLICT;
703         }
704
705         aio_ex->nbyte = smb_maxcnt;
706         aio_ex->offset = startpos;
707
708         req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
709                                  preadbuf->data, smb_maxcnt, startpos);
710         if (req == NULL) {
711                 DEBUG(0, ("smb2: SMB_VFS_PREAD_SEND failed. "
712                           "Error %s\n", strerror(errno)));
713                 TALLOC_FREE(aio_ex);
714                 return NT_STATUS_RETRY;
715         }
716         tevent_req_set_callback(req, aio_pread_smb2_done, aio_ex);
717
718         if (!aio_add_req_to_fsp(fsp, req)) {
719                 DEBUG(1, ("Could not add req to fsp\n"));
720                 TALLOC_FREE(aio_ex);
721                 return NT_STATUS_RETRY;
722         }
723
724         /* We don't need talloc_move here as both aio_ex and
725          * smbreq are children of smbreq->smb2req. */
726         aio_ex->smbreq = smbreq;
727         smbreq->async_priv = aio_ex;
728
729         DEBUG(10,("smb2: scheduled aio_read for file %s, "
730                 "offset %.0f, len = %u (mid = %u)\n",
731                 fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
732                 (unsigned int)aio_ex->smbreq->mid ));
733
734         return NT_STATUS_OK;
735 }
736
737 static void aio_pread_smb2_done(struct tevent_req *req)
738 {
739         struct aio_extra *aio_ex = tevent_req_callback_data(
740                 req, struct aio_extra);
741         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
742         files_struct *fsp = aio_ex->fsp;
743         NTSTATUS status;
744         ssize_t nread;
745         struct vfs_aio_state vfs_aio_state = { 0 };
746
747         nread = SMB_VFS_PREAD_RECV(req, &vfs_aio_state);
748         TALLOC_FREE(req);
749
750         DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread,
751                    (nread == -1) ? strerror(vfs_aio_state.error) : "no error"));
752
753         /* Common error or success code processing for async or sync
754            read returns. */
755
756         status = smb2_read_complete(subreq, nread, vfs_aio_state.error);
757
758         if (nread > 0) {
759                 fsp->fh->pos = aio_ex->offset + nread;
760                 fsp->fh->position_information = fsp->fh->pos;
761         }
762
763         DEBUG(10, ("smb2: scheduled aio_read completed "
764                    "for file %s, offset %.0f, len = %u "
765                    "(errcode = %d, NTSTATUS = %s)\n",
766                    fsp_str_dbg(aio_ex->fsp),
767                    (double)aio_ex->offset,
768                    (unsigned int)nread,
769                    vfs_aio_state.error, nt_errstr(status)));
770
771         if (!NT_STATUS_IS_OK(status)) {
772                 tevent_req_nterror(subreq, status);
773                 return;
774         }
775         tevent_req_done(subreq);
776 }
777
778 static void aio_pwrite_smb2_done(struct tevent_req *req);
779
780 /****************************************************************************
781  Set up an aio request from a SMB2write call.
782 *****************************************************************************/
783
784 NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
785                                 struct smb_request *smbreq,
786                                 files_struct *fsp,
787                                 uint64_t in_offset,
788                                 DATA_BLOB in_data,
789                                 bool write_through)
790 {
791         struct aio_extra *aio_ex = NULL;
792         size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
793         struct tevent_req *req;
794
795         if (fsp->base_fsp != NULL) {
796                 /* No AIO on streams yet */
797                 DEBUG(10, ("AIO on streams not yet supported\n"));
798                 return NT_STATUS_RETRY;
799         }
800
801         if (fsp->op == NULL) {
802                 /* No AIO on internal opens. */
803                 return NT_STATUS_RETRY;
804         }
805
806         if ((!min_aio_write_size || (in_data.length < min_aio_write_size))
807             && !SMB_VFS_AIO_FORCE(fsp)) {
808                 /* Too small a write for aio request. */
809                 DEBUG(10,("smb2: write size (%u) too "
810                         "small for minimum aio_write of %u\n",
811                         (unsigned int)in_data.length,
812                         (unsigned int)min_aio_write_size ));
813                 return NT_STATUS_RETRY;
814         }
815
816         /* Only do this on writes not using the write cache. */
817         if (lp_write_cache_size(SNUM(conn)) != 0) {
818                 return NT_STATUS_RETRY;
819         }
820
821         if (smbd_smb2_is_compound(smbreq->smb2req)) {
822                 return NT_STATUS_RETRY;
823         }
824
825         if (smbreq->unread_bytes) {
826                 /* Can't do async with recvfile. */
827                 return NT_STATUS_RETRY;
828         }
829
830         if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
831                 return NT_STATUS_NO_MEMORY;
832         }
833
834         aio_ex->write_through = write_through;
835
836         init_strict_lock_struct(fsp, fsp->op->global->open_persistent_id,
837                 in_offset, (uint64_t)in_data.length, WRITE_LOCK,
838                 &aio_ex->lock);
839
840         /* Take the lock until the AIO completes. */
841         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &aio_ex->lock)) {
842                 TALLOC_FREE(aio_ex);
843                 return NT_STATUS_FILE_LOCK_CONFLICT;
844         }
845
846         aio_ex->nbyte = in_data.length;
847         aio_ex->offset = in_offset;
848
849         req = pwrite_fsync_send(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
850                                 in_data.data, in_data.length, in_offset,
851                                 write_through);
852         if (req == NULL) {
853                 DEBUG(3, ("smb2: SMB_VFS_PWRITE_SEND failed. "
854                           "Error %s\n", strerror(errno)));
855                 TALLOC_FREE(aio_ex);
856                 return NT_STATUS_RETRY;
857         }
858         tevent_req_set_callback(req, aio_pwrite_smb2_done, aio_ex);
859
860         if (!aio_add_req_to_fsp(fsp, req)) {
861                 DEBUG(1, ("Could not add req to fsp\n"));
862                 TALLOC_FREE(aio_ex);
863                 return NT_STATUS_RETRY;
864         }
865
866         /* We don't need talloc_move here as both aio_ex and
867         * smbreq are children of smbreq->smb2req. */
868         aio_ex->smbreq = smbreq;
869         smbreq->async_priv = aio_ex;
870
871         /* This should actually be improved to span the write. */
872         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
873         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
874
875         /*
876          * We don't want to do write behind due to ownership
877          * issues of the request structs. Maybe add it if I
878          * figure those out. JRA.
879          */
880
881         DEBUG(10,("smb2: scheduled aio_write for file "
882                 "%s, offset %.0f, len = %u (mid = %u)\n",
883                 fsp_str_dbg(fsp),
884                 (double)in_offset,
885                 (unsigned int)in_data.length,
886                 (unsigned int)aio_ex->smbreq->mid));
887
888         return NT_STATUS_OK;
889 }
890
891 static void aio_pwrite_smb2_done(struct tevent_req *req)
892 {
893         struct aio_extra *aio_ex = tevent_req_callback_data(
894                 req, struct aio_extra);
895         ssize_t numtowrite = aio_ex->nbyte;
896         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
897         files_struct *fsp = aio_ex->fsp;
898         NTSTATUS status;
899         ssize_t nwritten;
900         int err = 0;
901
902         nwritten = pwrite_fsync_recv(req, &err);
903         TALLOC_FREE(req);
904
905         DEBUG(10, ("pwrite_recv returned %d, err = %s\n", (int)nwritten,
906                    (nwritten == -1) ? strerror(err) : "no error"));
907
908         mark_file_modified(fsp);
909
910         status = smb2_write_complete_nosync(subreq, nwritten, err);
911
912         DEBUG(10, ("smb2: scheduled aio_write completed "
913                    "for file %s, offset %.0f, requested %u, "
914                    "written = %u (errcode = %d, NTSTATUS = %s)\n",
915                    fsp_str_dbg(fsp),
916                    (double)aio_ex->offset,
917                    (unsigned int)numtowrite,
918                    (unsigned int)nwritten,
919                    err, nt_errstr(status)));
920
921         if (!NT_STATUS_IS_OK(status)) {
922                 tevent_req_nterror(subreq, status);
923                 return;
924         }
925         tevent_req_done(subreq);
926 }