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