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