Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/smbd/aio.c

    r746 r988  
    2323#include "smbd/globals.h"
    2424#include "../lib/util/tevent_ntstatus.h"
    25 
    26 #if defined(WITH_AIO)
    27 
    28 /* The signal we'll use to signify aio done. */
    29 #ifndef RT_SIGNAL_AIO
    30 #define RT_SIGNAL_AIO   (SIGRTMIN+3)
    31 #endif
    32 
    33 #ifndef HAVE_STRUCT_SIGEVENT_SIGEV_VALUE_SIVAL_PTR
    34 #ifdef HAVE_STRUCT_SIGEVENT_SIGEV_VALUE_SIGVAL_PTR
    35 #define sival_int       sigval_int
    36 #define sival_ptr       sigval_ptr
    37 #endif
    38 #endif
     25#include "../lib/util/tevent_unix.h"
     26#include "lib/tevent_wait.h"
     27
     28/****************************************************************************
     29 Statics plus accessor functions.
     30*****************************************************************************/
     31
     32static int outstanding_aio_calls;
     33
     34int get_outstanding_aio_calls(void)
     35{
     36        return outstanding_aio_calls;
     37}
     38
     39void increment_outstanding_aio_calls(void)
     40{
     41        outstanding_aio_calls++;
     42}
     43
     44void decrement_outstanding_aio_calls(void)
     45{
     46        outstanding_aio_calls--;
     47}
    3948
    4049/****************************************************************************
     
    4352
    4453struct aio_extra {
    45         struct aio_extra *next, *prev;
    46         SMB_STRUCT_AIOCB acb;
    4754        files_struct *fsp;
    4855        struct smb_request *smbreq;
    4956        DATA_BLOB outbuf;
    5057        struct lock_struct lock;
     58        size_t nbyte;
     59        off_t offset;
    5160        bool write_through;
    52         int (*handle_completion)(struct aio_extra *ex, int errcode);
    5361};
    5462
    5563/****************************************************************************
    56  Initialize the signal handler for aio read/write.
     64 Accessor function to return write_through state.
    5765*****************************************************************************/
    5866
    59 static void smbd_aio_signal_handler(struct tevent_context *ev_ctx,
    60                                     struct tevent_signal *se,
    61                                     int signum, int count,
    62                                     void *_info, void *private_data)
    63 {
    64         siginfo_t *info = (siginfo_t *)_info;
    65         struct aio_extra *aio_ex = (struct aio_extra *)
    66                                 info->si_value.sival_ptr;
    67 
    68         smbd_aio_complete_aio_ex(aio_ex);
    69         TALLOC_FREE(aio_ex);
    70 }
    71 
    72 
    73 static bool initialize_async_io_handler(void)
    74 {
    75         static bool tried_signal_setup = false;
    76 
    77         if (aio_signal_event) {
    78                 return true;
    79         }
    80         if (tried_signal_setup) {
    81                 return false;
    82         }
    83         tried_signal_setup = true;
    84 
    85         aio_signal_event = tevent_add_signal(smbd_event_context(),
    86                                              smbd_event_context(),
    87                                              RT_SIGNAL_AIO, SA_SIGINFO,
    88                                              smbd_aio_signal_handler,
    89                                              NULL);
    90         if (!aio_signal_event) {
    91                 DEBUG(10, ("Failed to setup RT_SIGNAL_AIO handler\n"));
    92                 return false;
    93         }
    94 
    95         /* tevent supports 100 signal with SA_SIGINFO */
    96         aio_pending_size = 100;
    97         return true;
    98 }
    99 
    100 static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode);
    101 static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode);
    102 static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode);
    103 static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode);
     67bool aio_write_through_requested(struct aio_extra *aio_ex)
     68{
     69        return aio_ex->write_through;
     70}
    10471
    10572static int aio_extra_destructor(struct aio_extra *aio_ex)
    10673{
    107         DLIST_REMOVE(aio_list_head, aio_ex);
     74        decrement_outstanding_aio_calls();
    10875        return 0;
    10976}
     
    11885                                        size_t buflen)
    11986{
    120         struct aio_extra *aio_ex = TALLOC_ZERO_P(mem_ctx, struct aio_extra);
     87        struct aio_extra *aio_ex = talloc_zero(mem_ctx, struct aio_extra);
    12188
    12289        if (!aio_ex) {
     
    135102                }
    136103        }
    137         DLIST_ADD(aio_list_head, aio_ex);
    138104        talloc_set_destructor(aio_ex, aio_extra_destructor);
    139105        aio_ex->fsp = fsp;
     106        increment_outstanding_aio_calls();
    140107        return aio_ex;
    141108}
     109
     110struct aio_req_fsp_link {
     111        files_struct *fsp;
     112        struct tevent_req *req;
     113};
     114
     115static int aio_del_req_from_fsp(struct aio_req_fsp_link *lnk)
     116{
     117        unsigned i;
     118        files_struct *fsp = lnk->fsp;
     119        struct tevent_req *req = lnk->req;
     120
     121        for (i=0; i<fsp->num_aio_requests; i++) {
     122                if (fsp->aio_requests[i] == req) {
     123                        break;
     124                }
     125        }
     126        if (i == fsp->num_aio_requests) {
     127                DEBUG(1, ("req %p not found in fsp %p\n", req, fsp));
     128                return 0;
     129        }
     130        fsp->num_aio_requests -= 1;
     131        fsp->aio_requests[i] = fsp->aio_requests[fsp->num_aio_requests];
     132
     133        if (fsp->num_aio_requests == 0) {
     134                tevent_wait_done(fsp->deferred_close);
     135        }
     136        return 0;
     137}
     138
     139bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req)
     140{
     141        size_t array_len;
     142        struct aio_req_fsp_link *lnk;
     143
     144        lnk = talloc(req, struct aio_req_fsp_link);
     145        if (lnk == NULL) {
     146                return false;
     147        }
     148
     149        array_len = talloc_array_length(fsp->aio_requests);
     150        if (array_len <= fsp->num_aio_requests) {
     151                struct tevent_req **tmp;
     152
     153                tmp = talloc_realloc(
     154                        fsp, fsp->aio_requests, struct tevent_req *,
     155                        fsp->num_aio_requests+1);
     156                if (tmp == NULL) {
     157                        TALLOC_FREE(lnk);
     158                        return false;
     159                }
     160                fsp->aio_requests = tmp;
     161        }
     162        fsp->aio_requests[fsp->num_aio_requests] = req;
     163        fsp->num_aio_requests += 1;
     164
     165        lnk->fsp = fsp;
     166        lnk->req = req;
     167        talloc_set_destructor(lnk, aio_del_req_from_fsp);
     168
     169        return true;
     170}
     171
     172static void aio_pread_smb1_done(struct tevent_req *req);
    142173
    143174/****************************************************************************
     
    147178NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
    148179                             struct smb_request *smbreq,
    149                              files_struct *fsp, SMB_OFF_T startpos,
     180                             files_struct *fsp, off_t startpos,
    150181                             size_t smb_maxcnt)
    151182{
    152183        struct aio_extra *aio_ex;
    153         SMB_STRUCT_AIOCB *a;
    154184        size_t bufsize;
    155185        size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
    156         int ret;
    157 
    158         /* Ensure aio is initialized. */
    159         if (!initialize_async_io_handler()) {
    160                 return NT_STATUS_RETRY;
    161         }
     186        struct tevent_req *req;
    162187
    163188        if (fsp->base_fsp != NULL) {
     
    183208        }
    184209
    185         if (outstanding_aio_calls >= aio_pending_size) {
    186                 DEBUG(10,("schedule_aio_read_and_X: Already have %d aio "
    187                           "activities outstanding.\n",
    188                           outstanding_aio_calls ));
    189                 return NT_STATUS_RETRY;
    190         }
    191 
    192210        /* The following is safe from integer wrap as we've already checked
    193211           smb_maxcnt is 128k or less. Wct is 12 for read replies */
    194212
    195         bufsize = smb_size + 12 * 2 + smb_maxcnt;
     213        bufsize = smb_size + 12 * 2 + smb_maxcnt + 1 /* padding byte */;
    196214
    197215        if ((aio_ex = create_aio_extra(NULL, fsp, bufsize)) == NULL) {
     
    199217                return NT_STATUS_NO_MEMORY;
    200218        }
    201         aio_ex->handle_completion = handle_aio_read_complete;
    202219
    203220        construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
    204221        srv_set_message((char *)aio_ex->outbuf.data, 12, 0, True);
    205222        SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
     223        SCVAL(smb_buf(aio_ex->outbuf.data), 0, 0); /* padding byte */
    206224
    207225        init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
     
    215233        }
    216234
    217         a = &aio_ex->acb;
    218 
    219         /* Now set up the aio record for the read call. */
    220 
    221         a->aio_fildes = fsp->fh->fd;
    222         a->aio_buf = smb_buf(aio_ex->outbuf.data);
    223         a->aio_nbytes = smb_maxcnt;
    224         a->aio_offset = startpos;
    225         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    226         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
    227         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
    228 
    229         ret = SMB_VFS_AIO_READ(fsp, a);
    230         if (ret == -1) {
     235        aio_ex->nbyte = smb_maxcnt;
     236        aio_ex->offset = startpos;
     237
     238        req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx,
     239                                 fsp,
     240                                 smb_buf(aio_ex->outbuf.data) + 1 /* pad */,
     241                                 smb_maxcnt, startpos);
     242        if (req == NULL) {
    231243                DEBUG(0,("schedule_aio_read_and_X: aio_read failed. "
    232244                         "Error %s\n", strerror(errno) ));
     
    235247                return NT_STATUS_RETRY;
    236248        }
    237 
    238         outstanding_aio_calls++;
     249        tevent_req_set_callback(req, aio_pread_smb1_done, aio_ex);
     250
     251        if (!aio_add_req_to_fsp(fsp, req)) {
     252                DEBUG(1, ("Could not add req to fsp\n"));
     253                SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
     254                TALLOC_FREE(aio_ex);
     255                return NT_STATUS_RETRY;
     256        }
     257
    239258        aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
    240259
     
    247266}
    248267
     268static void aio_pread_smb1_done(struct tevent_req *req)
     269{
     270        struct aio_extra *aio_ex = tevent_req_callback_data(
     271                req, struct aio_extra);
     272        files_struct *fsp = aio_ex->fsp;
     273        int outsize;
     274        char *outbuf = (char *)aio_ex->outbuf.data;
     275        char *data = smb_buf(outbuf) + 1 /* padding byte */;
     276        ssize_t nread;
     277        int err;
     278
     279        nread = SMB_VFS_PREAD_RECV(req, &err);
     280        TALLOC_FREE(req);
     281
     282        DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread,
     283                   (nread == -1) ? strerror(err) : "no error"));
     284
     285        if (fsp == NULL) {
     286                DEBUG( 3, ("aio_pread_smb1_done: file closed whilst "
     287                           "aio outstanding (mid[%llu]).\n",
     288                           (unsigned long long)aio_ex->smbreq->mid));
     289                TALLOC_FREE(aio_ex);
     290                return;
     291        }
     292
     293        /* Unlock now we're done. */
     294        SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
     295
     296        if (nread < 0) {
     297                DEBUG( 3, ("handle_aio_read_complete: file %s nread == %d. "
     298                           "Error = %s\n", fsp_str_dbg(fsp), (int)nread,
     299                           strerror(err)));
     300
     301                ERROR_NT(map_nt_error_from_unix(err));
     302                outsize = srv_set_message(outbuf,0,0,true);
     303        } else {
     304                outsize = srv_set_message(outbuf, 12,
     305                                          nread + 1 /* padding byte */, false);
     306                SSVAL(outbuf,smb_vwv2, 0xFFFF); /* Remaining - must be * -1. */
     307                SSVAL(outbuf,smb_vwv5, nread);
     308                SSVAL(outbuf,smb_vwv6, smb_offset(data,outbuf));
     309                SSVAL(outbuf,smb_vwv7, ((nread >> 16) & 1));
     310                SSVAL(smb_buf(outbuf), -2, nread);
     311
     312                aio_ex->fsp->fh->pos = aio_ex->offset + nread;
     313                aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
     314
     315                DEBUG( 3, ("handle_aio_read_complete file %s max=%d "
     316                           "nread=%d\n", fsp_str_dbg(fsp),
     317                           (int)aio_ex->nbyte, (int)nread ) );
     318
     319        }
     320        smb_setlen(outbuf, outsize - 4);
     321        show_msg(outbuf);
     322        if (!srv_send_smb(aio_ex->smbreq->xconn, outbuf,
     323                          true, aio_ex->smbreq->seqnum+1,
     324                          IS_CONN_ENCRYPTED(fsp->conn), NULL)) {
     325                exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
     326                                    "failed.");
     327        }
     328
     329        DEBUG(10, ("handle_aio_read_complete: scheduled aio_read completed "
     330                   "for file %s, offset %.0f, len = %u\n",
     331                   fsp_str_dbg(fsp), (double)aio_ex->offset,
     332                   (unsigned int)nread));
     333
     334        TALLOC_FREE(aio_ex);
     335}
     336
     337struct pwrite_fsync_state {
     338        struct tevent_context *ev;
     339        files_struct *fsp;
     340        bool write_through;
     341        ssize_t nwritten;
     342};
     343
     344static void pwrite_fsync_write_done(struct tevent_req *subreq);
     345static void pwrite_fsync_sync_done(struct tevent_req *subreq);
     346
     347static struct tevent_req *pwrite_fsync_send(TALLOC_CTX *mem_ctx,
     348                                            struct tevent_context *ev,
     349                                            struct files_struct *fsp,
     350                                            const void *data,
     351                                            size_t n, off_t offset,
     352                                            bool write_through)
     353{
     354        struct tevent_req *req, *subreq;
     355        struct pwrite_fsync_state *state;
     356
     357        req = tevent_req_create(mem_ctx, &state, struct pwrite_fsync_state);
     358        if (req == NULL) {
     359                return NULL;
     360        }
     361        state->ev = ev;
     362        state->fsp = fsp;
     363        state->write_through = write_through;
     364
     365        subreq = SMB_VFS_PWRITE_SEND(state, ev, fsp, data, n, offset);
     366        if (tevent_req_nomem(subreq, req)) {
     367                return tevent_req_post(req, ev);
     368        }
     369        tevent_req_set_callback(subreq, pwrite_fsync_write_done, req);
     370        return req;
     371}
     372
     373static void pwrite_fsync_write_done(struct tevent_req *subreq)
     374{
     375        struct tevent_req *req = tevent_req_callback_data(
     376                subreq, struct tevent_req);
     377        struct pwrite_fsync_state *state = tevent_req_data(
     378                req, struct pwrite_fsync_state);
     379        connection_struct *conn = state->fsp->conn;
     380        int err;
     381        bool do_sync;
     382
     383        state->nwritten = SMB_VFS_PWRITE_RECV(subreq, &err);
     384        TALLOC_FREE(subreq);
     385        if (state->nwritten == -1) {
     386                tevent_req_error(req, err);
     387                return;
     388        }
     389
     390        do_sync = (lp_strict_sync(SNUM(conn)) &&
     391                   (lp_sync_always(SNUM(conn)) || state->write_through));
     392        if (!do_sync) {
     393                tevent_req_done(req);
     394                return;
     395        }
     396
     397        subreq = SMB_VFS_FSYNC_SEND(state, state->ev, state->fsp);
     398        if (tevent_req_nomem(subreq, req)) {
     399                return;
     400        }
     401        tevent_req_set_callback(subreq, pwrite_fsync_sync_done, req);
     402}
     403
     404static void pwrite_fsync_sync_done(struct tevent_req *subreq)
     405{
     406        struct tevent_req *req = tevent_req_callback_data(
     407                subreq, struct tevent_req);
     408        int ret, err;
     409
     410        ret = SMB_VFS_FSYNC_RECV(subreq, &err);
     411        TALLOC_FREE(subreq);
     412        if (ret == -1) {
     413                tevent_req_error(req, err);
     414                return;
     415        }
     416        tevent_req_done(req);
     417}
     418
     419static ssize_t pwrite_fsync_recv(struct tevent_req *req, int *perr)
     420{
     421        struct pwrite_fsync_state *state = tevent_req_data(
     422                req, struct pwrite_fsync_state);
     423
     424        if (tevent_req_is_unix_error(req, perr)) {
     425                return -1;
     426        }
     427        return state->nwritten;
     428}
     429
     430static void aio_pwrite_smb1_done(struct tevent_req *req);
     431
    249432/****************************************************************************
    250433 Set up an aio request from a SMBwriteX call.
     
    253436NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
    254437                              struct smb_request *smbreq,
    255                               files_struct *fsp, char *data,
    256                               SMB_OFF_T startpos,
     438                              files_struct *fsp, const char *data,
     439                              off_t startpos,
    257440                              size_t numtowrite)
    258441{
    259442        struct aio_extra *aio_ex;
    260         SMB_STRUCT_AIOCB *a;
    261443        size_t bufsize;
    262444        size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
    263         int ret;
    264 
    265         /* Ensure aio is initialized. */
    266         if (!initialize_async_io_handler()) {
    267                 return NT_STATUS_RETRY;
    268         }
     445        struct tevent_req *req;
    269446
    270447        if (fsp->base_fsp != NULL) {
     
    290467        }
    291468
    292         if (outstanding_aio_calls >= aio_pending_size) {
    293                 DEBUG(3,("schedule_aio_write_and_X: Already have %d aio "
    294                          "activities outstanding.\n",
    295                           outstanding_aio_calls ));
    296                 DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
    297                           "aio_write for file %s, offset %.0f, len = %u "
    298                           "(mid = %u)\n",
    299                           fsp_str_dbg(fsp), (double)startpos,
    300                           (unsigned int)numtowrite,
    301                           (unsigned int)smbreq->mid ));
    302                 return NT_STATUS_RETRY;
    303         }
    304 
    305469        bufsize = smb_size + 6*2;
    306470
     
    309473                return NT_STATUS_NO_MEMORY;
    310474        }
    311         aio_ex->handle_completion = handle_aio_write_complete;
    312475        aio_ex->write_through = BITSETW(smbreq->vwv+7,0);
    313476
     
    326489        }
    327490
    328         a = &aio_ex->acb;
    329 
    330         /* Now set up the aio record for the write call. */
    331 
    332         a->aio_fildes = fsp->fh->fd;
    333         a->aio_buf = data;
    334         a->aio_nbytes = numtowrite;
    335         a->aio_offset = startpos;
    336         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    337         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
    338         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
    339 
    340         ret = SMB_VFS_AIO_WRITE(fsp, a);
    341         if (ret == -1) {
     491        aio_ex->nbyte = numtowrite;
     492        aio_ex->offset = startpos;
     493
     494        req = pwrite_fsync_send(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
     495                                data, numtowrite, startpos,
     496                                aio_ex->write_through);
     497        if (req == NULL) {
    342498                DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
    343499                         "Error %s\n", strerror(errno) ));
     
    346502                return NT_STATUS_RETRY;
    347503        }
    348 
    349         outstanding_aio_calls++;
     504        tevent_req_set_callback(req, aio_pwrite_smb1_done, aio_ex);
     505
     506        if (!aio_add_req_to_fsp(fsp, req)) {
     507                DEBUG(1, ("Could not add req to fsp\n"));
     508                SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
     509                TALLOC_FREE(aio_ex);
     510                return NT_STATUS_RETRY;
     511        }
     512
    350513        aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
    351514
     
    354517        contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
    355518
    356         if (!aio_ex->write_through && !lp_syncalways(SNUM(fsp->conn))
     519        if (!aio_ex->write_through && !lp_sync_always(SNUM(fsp->conn))
    357520            && fsp->aio_write_behind) {
    358521                /* Lie to the client and immediately claim we finished the
     
    361524                SSVAL(aio_ex->outbuf.data,smb_vwv4,(numtowrite>>16)&1);
    362525                show_msg((char *)aio_ex->outbuf.data);
    363                 if (!srv_send_smb(aio_ex->smbreq->sconn,
     526                if (!srv_send_smb(aio_ex->smbreq->xconn,
    364527                                (char *)aio_ex->outbuf.data,
    365528                                true, aio_ex->smbreq->seqnum+1,
     
    377540                  "outstanding_aio_calls = %d\n",
    378541                  fsp_str_dbg(fsp), (double)startpos, (unsigned int)numtowrite,
    379                   (unsigned int)aio_ex->smbreq->mid, outstanding_aio_calls ));
     542                  (unsigned int)aio_ex->smbreq->mid,
     543                  get_outstanding_aio_calls() ));
    380544
    381545        return NT_STATUS_OK;
    382546}
     547
     548static void aio_pwrite_smb1_done(struct tevent_req *req)
     549{
     550        struct aio_extra *aio_ex = tevent_req_callback_data(
     551                req, struct aio_extra);
     552        files_struct *fsp = aio_ex->fsp;
     553        char *outbuf = (char *)aio_ex->outbuf.data;
     554        ssize_t numtowrite = aio_ex->nbyte;
     555        ssize_t nwritten;
     556        int err;
     557
     558        nwritten = pwrite_fsync_recv(req, &err);
     559        TALLOC_FREE(req);
     560
     561        DEBUG(10, ("pwrite_recv returned %d, err = %s\n", (int)nwritten,
     562                   (nwritten == -1) ? strerror(err) : "no error"));
     563
     564        if (fsp == NULL) {
     565                DEBUG( 3, ("aio_pwrite_smb1_done: file closed whilst "
     566                           "aio outstanding (mid[%llu]).\n",
     567                           (unsigned long long)aio_ex->smbreq->mid));
     568                TALLOC_FREE(aio_ex);
     569                return;
     570        }
     571
     572        /* Unlock now we're done. */
     573        SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
     574
     575        mark_file_modified(fsp);
     576
     577        if (fsp->aio_write_behind) {
     578
     579                if (nwritten != numtowrite) {
     580                        if (nwritten == -1) {
     581                                DEBUG(5,("handle_aio_write_complete: "
     582                                         "aio_write_behind failed ! File %s "
     583                                         "is corrupt ! Error %s\n",
     584                                         fsp_str_dbg(fsp), strerror(err)));
     585                        } else {
     586                                DEBUG(0,("handle_aio_write_complete: "
     587                                         "aio_write_behind failed ! File %s "
     588                                         "is corrupt ! Wanted %u bytes but "
     589                                         "only wrote %d\n", fsp_str_dbg(fsp),
     590                                         (unsigned int)numtowrite,
     591                                         (int)nwritten ));
     592                        }
     593                } else {
     594                        DEBUG(10,("handle_aio_write_complete: "
     595                                  "aio_write_behind completed for file %s\n",
     596                                  fsp_str_dbg(fsp)));
     597                }
     598                /* TODO: should no return success in case of an error !!! */
     599                TALLOC_FREE(aio_ex);
     600                return;
     601        }
     602
     603        /* We don't need outsize or set_message here as we've already set the
     604           fixed size length when we set up the aio call. */
     605
     606        if (nwritten == -1) {
     607                DEBUG(3, ("handle_aio_write: file %s wanted %u bytes. "
     608                          "nwritten == %d. Error = %s\n",
     609                          fsp_str_dbg(fsp), (unsigned int)numtowrite,
     610                          (int)nwritten, strerror(err)));
     611
     612                ERROR_NT(map_nt_error_from_unix(err));
     613                srv_set_message(outbuf,0,0,true);
     614        } else {
     615                SSVAL(outbuf,smb_vwv2,nwritten);
     616                SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
     617                if (nwritten < (ssize_t)numtowrite) {
     618                        SCVAL(outbuf,smb_rcls,ERRHRD);
     619                        SSVAL(outbuf,smb_err,ERRdiskfull);
     620                }
     621
     622                DEBUG(3,("handle_aio_write: %s, num=%d wrote=%d\n",
     623                         fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
     624
     625                aio_ex->fsp->fh->pos = aio_ex->offset + nwritten;
     626        }
     627
     628        show_msg(outbuf);
     629        if (!srv_send_smb(aio_ex->smbreq->xconn, outbuf,
     630                          true, aio_ex->smbreq->seqnum+1,
     631                          IS_CONN_ENCRYPTED(fsp->conn),
     632                          NULL)) {
     633                exit_server_cleanly("handle_aio_write_complete: "
     634                                    "srv_send_smb failed.");
     635        }
     636
     637        DEBUG(10, ("handle_aio_write_complete: scheduled aio_write completed "
     638                   "for file %s, offset %.0f, requested %u, written = %u\n",
     639                   fsp_str_dbg(fsp), (double)aio_ex->offset,
     640                   (unsigned int)numtowrite, (unsigned int)nwritten));
     641
     642        TALLOC_FREE(aio_ex);
     643}
     644
     645bool cancel_smb2_aio(struct smb_request *smbreq)
     646{
     647        struct smbd_smb2_request *smb2req = smbreq->smb2req;
     648        struct aio_extra *aio_ex = NULL;
     649
     650        if (smb2req) {
     651                aio_ex = talloc_get_type(smbreq->async_priv,
     652                                         struct aio_extra);
     653        }
     654
     655        if (aio_ex == NULL) {
     656                return false;
     657        }
     658
     659        if (aio_ex->fsp == NULL) {
     660                return false;
     661        }
     662
     663        /*
     664         * We let the aio request run. Setting fsp to NULL has the
     665         * effect that the _done routines don't send anything out.
     666         */
     667
     668        aio_ex->fsp = NULL;
     669        return true;
     670}
     671
     672static void aio_pread_smb2_done(struct tevent_req *req);
    383673
    384674/****************************************************************************
     
    391681                                TALLOC_CTX *ctx,
    392682                                DATA_BLOB *preadbuf,
    393                                 SMB_OFF_T startpos,
     683                                off_t startpos,
    394684                                size_t smb_maxcnt)
    395685{
    396686        struct aio_extra *aio_ex;
    397         SMB_STRUCT_AIOCB *a;
    398687        size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
    399         int ret;
    400 
    401         /* Ensure aio is initialized. */
    402         if (!initialize_async_io_handler()) {
    403                 return NT_STATUS_RETRY;
    404         }
     688        struct tevent_req *req;
    405689
    406690        if (fsp->base_fsp != NULL) {
    407691                /* No AIO on streams yet */
    408692                DEBUG(10, ("AIO on streams not yet supported\n"));
     693                return NT_STATUS_RETRY;
     694        }
     695
     696        if (fsp->op == NULL) {
     697                /* No AIO on internal opens. */
    409698                return NT_STATUS_RETRY;
    410699        }
     
    425714        }
    426715
    427         if (outstanding_aio_calls >= aio_pending_size) {
    428                 DEBUG(10,("smb2: Already have %d aio "
    429                         "activities outstanding.\n",
    430                         outstanding_aio_calls ));
    431                 return NT_STATUS_RETRY;
    432         }
    433 
    434716        /* Create the out buffer. */
    435717        *preadbuf = data_blob_talloc(ctx, NULL, smb_maxcnt);
     
    441723                return NT_STATUS_NO_MEMORY;
    442724        }
    443         aio_ex->handle_completion = handle_aio_smb2_read_complete;
    444 
    445         init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
     725
     726        init_strict_lock_struct(fsp, fsp->op->global->open_persistent_id,
    446727                (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
    447728                &aio_ex->lock);
     
    453734        }
    454735
    455         a = &aio_ex->acb;
    456 
    457         /* Now set up the aio record for the read call. */
    458 
    459         a->aio_fildes = fsp->fh->fd;
    460         a->aio_buf = preadbuf->data;
    461         a->aio_nbytes = smb_maxcnt;
    462         a->aio_offset = startpos;
    463         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    464         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
    465         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
    466 
    467         ret = SMB_VFS_AIO_READ(fsp, a);
    468         if (ret == -1) {
    469                 DEBUG(0,("smb2: aio_read failed. "
    470                         "Error %s\n", strerror(errno) ));
     736        aio_ex->nbyte = smb_maxcnt;
     737        aio_ex->offset = startpos;
     738
     739        req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
     740                                 preadbuf->data, smb_maxcnt, startpos);
     741        if (req == NULL) {
     742                DEBUG(0, ("smb2: SMB_VFS_PREAD_SEND failed. "
     743                          "Error %s\n", strerror(errno)));
    471744                SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
    472745                TALLOC_FREE(aio_ex);
    473746                return NT_STATUS_RETRY;
    474747        }
    475 
    476         outstanding_aio_calls++;
     748        tevent_req_set_callback(req, aio_pread_smb2_done, aio_ex);
     749
     750        if (!aio_add_req_to_fsp(fsp, req)) {
     751                DEBUG(1, ("Could not add req to fsp\n"));
     752                SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
     753                TALLOC_FREE(aio_ex);
     754                return NT_STATUS_RETRY;
     755        }
     756
    477757        /* We don't need talloc_move here as both aio_ex and
    478758         * smbreq are children of smbreq->smb2req. */
    479759        aio_ex->smbreq = smbreq;
     760        smbreq->async_priv = aio_ex;
    480761
    481762        DEBUG(10,("smb2: scheduled aio_read for file %s, "
     
    486767        return NT_STATUS_OK;
    487768}
     769
     770static void aio_pread_smb2_done(struct tevent_req *req)
     771{
     772        struct aio_extra *aio_ex = tevent_req_callback_data(
     773                req, struct aio_extra);
     774        struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
     775        files_struct *fsp = aio_ex->fsp;
     776        NTSTATUS status;
     777        ssize_t nread;
     778        int err = 0;
     779
     780        nread = SMB_VFS_PREAD_RECV(req, &err);
     781        TALLOC_FREE(req);
     782
     783        DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread,
     784                   (nread == -1) ? strerror(err) : "no error"));
     785
     786        if (fsp == NULL) {
     787                DEBUG(3, ("%s: request cancelled (mid[%ju])\n",
     788                          __func__, (uintmax_t)aio_ex->smbreq->mid));
     789                TALLOC_FREE(aio_ex);
     790                tevent_req_nterror(subreq, NT_STATUS_INTERNAL_ERROR);
     791                return;
     792        }
     793
     794        /* Unlock now we're done. */
     795        SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
     796
     797        /* Common error or success code processing for async or sync
     798           read returns. */
     799
     800        status = smb2_read_complete(subreq, nread, err);
     801
     802        if (nread > 0) {
     803                fsp->fh->pos = aio_ex->offset + nread;
     804                fsp->fh->position_information = fsp->fh->pos;
     805        }
     806
     807        DEBUG(10, ("smb2: scheduled aio_read completed "
     808                   "for file %s, offset %.0f, len = %u "
     809                   "(errcode = %d, NTSTATUS = %s)\n",
     810                   fsp_str_dbg(aio_ex->fsp),
     811                   (double)aio_ex->offset,
     812                   (unsigned int)nread,
     813                   err, nt_errstr(status)));
     814
     815        if (!NT_STATUS_IS_OK(status)) {
     816                tevent_req_nterror(subreq, status);
     817                return;
     818        }
     819        tevent_req_done(subreq);
     820}
     821
     822static void aio_pwrite_smb2_done(struct tevent_req *req);
    488823
    489824/****************************************************************************
     
    499834{
    500835        struct aio_extra *aio_ex = NULL;
    501         SMB_STRUCT_AIOCB *a = NULL;
    502836        size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
    503         int ret;
    504 
    505         /* Ensure aio is initialized. */
    506         if (!initialize_async_io_handler()) {
    507                 return NT_STATUS_RETRY;
    508         }
     837        struct tevent_req *req;
    509838
    510839        if (fsp->base_fsp != NULL) {
    511840                /* No AIO on streams yet */
    512841                DEBUG(10, ("AIO on streams not yet supported\n"));
     842                return NT_STATUS_RETRY;
     843        }
     844
     845        if (fsp->op == NULL) {
     846                /* No AIO on internal opens. */
    513847                return NT_STATUS_RETRY;
    514848        }
     
    529863        }
    530864
    531         if (outstanding_aio_calls >= aio_pending_size) {
    532                 DEBUG(3,("smb2: Already have %d aio "
    533                         "activities outstanding.\n",
    534                         outstanding_aio_calls ));
     865        if (smbreq->unread_bytes) {
     866                /* Can't do async with recvfile. */
    535867                return NT_STATUS_RETRY;
    536868        }
     
    540872        }
    541873
    542         aio_ex->handle_completion = handle_aio_smb2_write_complete;
    543874        aio_ex->write_through = write_through;
    544875
    545         init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
     876        init_strict_lock_struct(fsp, fsp->op->global->open_persistent_id,
    546877                in_offset, (uint64_t)in_data.length, WRITE_LOCK,
    547878                &aio_ex->lock);
     
    553884        }
    554885
    555         a = &aio_ex->acb;
    556 
    557         /* Now set up the aio record for the write call. */
    558 
    559         a->aio_fildes = fsp->fh->fd;
    560         a->aio_buf = in_data.data;
    561         a->aio_nbytes = in_data.length;
    562         a->aio_offset = in_offset;
    563         a->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
    564         a->aio_sigevent.sigev_signo  = RT_SIGNAL_AIO;
    565         a->aio_sigevent.sigev_value.sival_ptr = aio_ex;
    566 
    567         ret = SMB_VFS_AIO_WRITE(fsp, a);
    568         if (ret == -1) {
    569                 DEBUG(3,("smb2: aio_write failed. "
    570                         "Error %s\n", strerror(errno) ));
     886        aio_ex->nbyte = in_data.length;
     887        aio_ex->offset = in_offset;
     888
     889        req = pwrite_fsync_send(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
     890                                in_data.data, in_data.length, in_offset,
     891                                write_through);
     892        if (req == NULL) {
     893                DEBUG(3, ("smb2: SMB_VFS_PWRITE_SEND failed. "
     894                          "Error %s\n", strerror(errno)));
    571895                SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
    572896                TALLOC_FREE(aio_ex);
    573897                return NT_STATUS_RETRY;
    574898        }
    575 
    576         outstanding_aio_calls++;
     899        tevent_req_set_callback(req, aio_pwrite_smb2_done, aio_ex);
     900
     901        if (!aio_add_req_to_fsp(fsp, req)) {
     902                DEBUG(1, ("Could not add req to fsp\n"));
     903                SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
     904                TALLOC_FREE(aio_ex);
     905                return NT_STATUS_RETRY;
     906        }
     907
    577908        /* We don't need talloc_move here as both aio_ex and
    578909        * smbreq are children of smbreq->smb2req. */
    579910        aio_ex->smbreq = smbreq;
     911        smbreq->async_priv = aio_ex;
    580912
    581913        /* This should actually be improved to span the write. */
     
    596928                (unsigned int)in_data.length,
    597929                (unsigned int)aio_ex->smbreq->mid,
    598                 outstanding_aio_calls ));
     930                get_outstanding_aio_calls() ));
    599931
    600932        return NT_STATUS_OK;
    601933}
    602934
    603 /****************************************************************************
    604  Complete the read and return the data or error back to the client.
    605  Returns errno or zero if all ok.
    606 *****************************************************************************/
    607 
    608 static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
    609 {
    610         int outsize;
    611         char *outbuf = (char *)aio_ex->outbuf.data;
    612         char *data = smb_buf(outbuf);
    613         ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
    614 
    615         if (nread < 0) {
    616                 /* We're relying here on the fact that if the fd is
    617                    closed then the aio will complete and aio_return
    618                    will return an error. Hopefully this is
    619                    true.... JRA. */
    620 
    621                 DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d. "
    622                            "Error = %s\n",
    623                            fsp_str_dbg(aio_ex->fsp), (int)nread, strerror(errcode)));
    624 
    625                 ERROR_NT(map_nt_error_from_unix(errcode));
    626                 outsize = srv_set_message(outbuf,0,0,true);
    627         } else {
    628                 outsize = srv_set_message(outbuf,12,nread,False);
    629                 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */
    630                 SSVAL(outbuf,smb_vwv5,nread);
    631                 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
    632                 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
    633                 SSVAL(smb_buf(outbuf),-2,nread);
    634 
    635                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
    636                 aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
    637 
    638                 DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
    639                             "nread=%d\n",
    640                             fsp_str_dbg(aio_ex->fsp),
    641                             (int)aio_ex->acb.aio_nbytes, (int)nread ) );
    642 
    643         }
    644         smb_setlen(outbuf,outsize - 4);
    645         show_msg(outbuf);
    646         if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
    647                         true, aio_ex->smbreq->seqnum+1,
    648                         IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) {
    649                 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
    650                                     "failed.");
    651         }
    652 
    653         DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed "
    654                   "for file %s, offset %.0f, len = %u\n",
    655                   fsp_str_dbg(aio_ex->fsp), (double)aio_ex->acb.aio_offset,
    656                   (unsigned int)nread ));
    657 
    658         return errcode;
    659 }
    660 
    661 /****************************************************************************
    662  Complete the write and return the data or error back to the client.
    663  Returns error code or zero if all ok.
    664 *****************************************************************************/
    665 
    666 static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
    667 {
     935static void aio_pwrite_smb2_done(struct tevent_req *req)
     936{
     937        struct aio_extra *aio_ex = tevent_req_callback_data(
     938                req, struct aio_extra);
     939        ssize_t numtowrite = aio_ex->nbyte;
     940        struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
    668941        files_struct *fsp = aio_ex->fsp;
    669         char *outbuf = (char *)aio_ex->outbuf.data;
    670         ssize_t numtowrite = aio_ex->acb.aio_nbytes;
    671         ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
    672 
    673         if (fsp->aio_write_behind) {
    674                 if (nwritten != numtowrite) {
    675                         if (nwritten == -1) {
    676                                 DEBUG(5,("handle_aio_write_complete: "
    677                                          "aio_write_behind failed ! File %s "
    678                                          "is corrupt ! Error %s\n",
    679                                          fsp_str_dbg(fsp), strerror(errcode)));
    680                         } else {
    681                                 DEBUG(0,("handle_aio_write_complete: "
    682                                          "aio_write_behind failed ! File %s "
    683                                          "is corrupt ! Wanted %u bytes but "
    684                                          "only wrote %d\n", fsp_str_dbg(fsp),
    685                                          (unsigned int)numtowrite,
    686                                          (int)nwritten ));
    687                                 errcode = EIO;
    688                         }
    689                 } else {
    690                         DEBUG(10,("handle_aio_write_complete: "
    691                                   "aio_write_behind completed for file %s\n",
    692                                   fsp_str_dbg(fsp)));
    693                 }
    694                 /* TODO: should no return 0 in case of an error !!! */
    695                 return 0;
    696         }
    697 
    698         /* We don't need outsize or set_message here as we've already set the
    699            fixed size length when we set up the aio call. */
    700 
    701         if(nwritten == -1) {
    702                 DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. "
    703                            "nwritten == %d. Error = %s\n",
    704                            fsp_str_dbg(fsp), (unsigned int)numtowrite,
    705                            (int)nwritten, strerror(errcode) ));
    706 
    707                 ERROR_NT(map_nt_error_from_unix(errcode));
    708                 srv_set_message(outbuf,0,0,true);
    709         } else {
    710                 NTSTATUS status;
    711 
    712                 SSVAL(outbuf,smb_vwv2,nwritten);
    713                 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
    714                 if (nwritten < (ssize_t)numtowrite) {
    715                         SCVAL(outbuf,smb_rcls,ERRHRD);
    716                         SSVAL(outbuf,smb_err,ERRdiskfull);
    717                 }
    718 
    719                 DEBUG(3,("handle_aio_write: fnum=%d num=%d wrote=%d\n",
    720                          fsp->fnum, (int)numtowrite, (int)nwritten));
    721                 status = sync_file(fsp->conn,fsp, aio_ex->write_through);
    722                 if (!NT_STATUS_IS_OK(status)) {
    723                         errcode = errno;
    724                         ERROR_BOTH(map_nt_error_from_unix(errcode),
    725                                    ERRHRD, ERRdiskfull);
    726                         srv_set_message(outbuf,0,0,true);
    727                         DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
    728                                  fsp_str_dbg(fsp), nt_errstr(status)));
    729                 }
    730 
    731                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten;
    732         }
    733 
    734         show_msg(outbuf);
    735         if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
    736                           true, aio_ex->smbreq->seqnum+1,
    737                           IS_CONN_ENCRYPTED(fsp->conn),
    738                           NULL)) {
    739                 exit_server_cleanly("handle_aio_write_complete: "
    740                                     "srv_send_smb failed.");
    741         }
    742 
    743         DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
    744                   "for file %s, offset %.0f, requested %u, written = %u\n",
    745                   fsp_str_dbg(fsp), (double)aio_ex->acb.aio_offset,
    746                   (unsigned int)numtowrite, (unsigned int)nwritten ));
    747 
    748         return errcode;
    749 }
    750 
    751 /****************************************************************************
    752  Complete the read and return the data or error back to the client.
    753  Returns errno or zero if all ok.
    754 *****************************************************************************/
    755 
    756 static int handle_aio_smb2_read_complete(struct aio_extra *aio_ex, int errcode)
    757 {
    758942        NTSTATUS status;
    759         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
    760         ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
    761 
    762         /* Common error or success code processing for async or sync
    763            read returns. */
    764 
    765         status = smb2_read_complete(subreq, nread, errcode);
    766 
    767         if (nread > 0) {
    768                 aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nread;
    769                 aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
    770         }
    771 
    772         DEBUG(10,("smb2: scheduled aio_read completed "
    773                 "for file %s, offset %.0f, len = %u "
    774                 "(errcode = %d, NTSTATUS = %s)\n",
    775                 fsp_str_dbg(aio_ex->fsp),
    776                 (double)aio_ex->acb.aio_offset,
    777                 (unsigned int)nread,
    778                 errcode,
    779                 nt_errstr(status) ));
     943        ssize_t nwritten;
     944        int err = 0;
     945
     946        nwritten = pwrite_fsync_recv(req, &err);
     947        TALLOC_FREE(req);
     948
     949        DEBUG(10, ("pwrite_recv returned %d, err = %s\n", (int)nwritten,
     950                   (nwritten == -1) ? strerror(err) : "no error"));
     951
     952        if (fsp == NULL) {
     953                DEBUG(3, ("%s: request cancelled (mid[%ju])\n",
     954                          __func__, (uintmax_t)aio_ex->smbreq->mid));
     955                TALLOC_FREE(aio_ex);
     956                tevent_req_nterror(subreq, NT_STATUS_INTERNAL_ERROR);
     957                return;
     958        }
     959
     960        /* Unlock now we're done. */
     961        SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
     962
     963        mark_file_modified(fsp);
     964
     965        status = smb2_write_complete_nosync(subreq, nwritten, err);
     966
     967        DEBUG(10, ("smb2: scheduled aio_write completed "
     968                   "for file %s, offset %.0f, requested %u, "
     969                   "written = %u (errcode = %d, NTSTATUS = %s)\n",
     970                   fsp_str_dbg(fsp),
     971                   (double)aio_ex->offset,
     972                   (unsigned int)numtowrite,
     973                   (unsigned int)nwritten,
     974                   err, nt_errstr(status)));
    780975
    781976        if (!NT_STATUS_IS_OK(status)) {
    782977                tevent_req_nterror(subreq, status);
    783                 return errcode;
    784         }
    785 
     978                return;
     979        }
    786980        tevent_req_done(subreq);
    787         return errcode;
    788 }
    789 
    790 /****************************************************************************
    791  Complete the SMB2 write and return the data or error back to the client.
    792  Returns error code or zero if all ok.
    793 *****************************************************************************/
    794 
    795 static int handle_aio_smb2_write_complete(struct aio_extra *aio_ex, int errcode)
    796 {
    797         files_struct *fsp = aio_ex->fsp;
    798         ssize_t numtowrite = aio_ex->acb.aio_nbytes;
    799         ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
    800         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
    801         NTSTATUS status;
    802 
    803         status = smb2_write_complete(subreq, nwritten, errcode);
    804 
    805         DEBUG(10,("smb2: scheduled aio_write completed "
    806                 "for file %s, offset %.0f, requested %u, "
    807                 "written = %u (errcode = %d, NTSTATUS = %s)\n",
    808                 fsp_str_dbg(fsp),
    809                 (double)aio_ex->acb.aio_offset,
    810                 (unsigned int)numtowrite,
    811                 (unsigned int)nwritten,
    812                 errcode,
    813                 nt_errstr(status) ));
    814 
    815         if (!NT_STATUS_IS_OK(status)) {
    816                 tevent_req_nterror(subreq, status);
    817                 return errcode;
    818         }
    819 
    820         tevent_req_done(subreq);
    821         return errcode;
    822 }
    823 
    824 /****************************************************************************
    825  Handle any aio completion. Returns True if finished (and sets *perr if err
    826  was non-zero), False if not.
    827 *****************************************************************************/
    828 
    829 static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr)
    830 {
    831         files_struct *fsp = NULL;
    832         int err;
    833 
    834         if(!aio_ex) {
    835                 DEBUG(3, ("handle_aio_completed: Non-existing aio_ex passed\n"));
    836                 return false;
    837         }
    838 
    839         fsp = aio_ex->fsp;
    840 
    841         /* Ensure the operation has really completed. */
    842         err = SMB_VFS_AIO_ERROR(fsp, &aio_ex->acb);
    843         if (err == EINPROGRESS) {
    844                 DEBUG(10,( "handle_aio_completed: operation mid %llu still in "
    845                         "process for file %s\n",
    846                         (unsigned long long)aio_ex->smbreq->mid,
    847                         fsp_str_dbg(aio_ex->fsp)));
    848                 return False;
    849         }
    850 
    851         /* Unlock now we're done. */
    852         SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
    853 
    854         if (err == ECANCELED) {
    855                 /* If error is ECANCELED then don't return anything to the
    856                  * client. */
    857                 DEBUG(10,( "handle_aio_completed: operation mid %llu"
    858                         " canceled\n",
    859                         (unsigned long long)aio_ex->smbreq->mid));
    860                 return True;
    861         }
    862 
    863         err = aio_ex->handle_completion(aio_ex, err);
    864         if (err) {
    865                 *perr = err; /* Only save non-zero errors. */
    866         }
    867 
    868         return True;
    869 }
    870 
    871 /****************************************************************************
    872  Handle any aio completion inline.
    873 *****************************************************************************/
    874 
    875 void smbd_aio_complete_aio_ex(struct aio_extra *aio_ex)
    876 {
    877         files_struct *fsp = NULL;
    878         int ret = 0;
    879 
    880         outstanding_aio_calls--;
    881 
    882         DEBUG(10,("smbd_aio_complete_mid: mid[%llu]\n",
    883                 (unsigned long long)aio_ex->smbreq->mid));
    884 
    885         fsp = aio_ex->fsp;
    886         if (fsp == NULL) {
    887                 /* file was closed whilst I/O was outstanding. Just
    888                  * ignore. */
    889                 DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
    890                         "aio outstanding (mid[%llu]).\n",
    891                         (unsigned long long)aio_ex->smbreq->mid));
    892                 return;
    893         }
    894 
    895         if (!handle_aio_completed(aio_ex, &ret)) {
    896                 return;
    897         }
    898 }
    899 
    900 /****************************************************************************
    901  We're doing write behind and the client closed the file. Wait up to 30
    902  seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes
    903  completed, errno to return if not.
    904 *****************************************************************************/
    905 
    906 #define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29
    907 
    908 int wait_for_aio_completion(files_struct *fsp)
    909 {
    910         struct aio_extra *aio_ex;
    911         const SMB_STRUCT_AIOCB **aiocb_list;
    912         int aio_completion_count = 0;
    913         time_t start_time = time_mono(NULL);
    914         int seconds_left;
    915 
    916         for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT;
    917              seconds_left >= 0;) {
    918                 int err = 0;
    919                 int i;
    920                 struct timespec ts;
    921 
    922                 aio_completion_count = 0;
    923                 for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
    924                         if (aio_ex->fsp == fsp) {
    925                                 aio_completion_count++;
    926                         }
    927                 }
    928 
    929                 if (!aio_completion_count) {
    930                         return 0;
    931                 }
    932 
    933                 DEBUG(3,("wait_for_aio_completion: waiting for %d aio events "
    934                          "to complete.\n", aio_completion_count ));
    935 
    936                 aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *,
    937                                               aio_completion_count);
    938                 if (!aiocb_list) {
    939                         return ENOMEM;
    940                 }
    941 
    942                 for( i = 0, aio_ex = aio_list_head;
    943                      aio_ex;
    944                      aio_ex = aio_ex->next) {
    945                         if (aio_ex->fsp == fsp) {
    946                                 aiocb_list[i++] = &aio_ex->acb;
    947                         }
    948                 }
    949 
    950                 /* Now wait up to seconds_left for completion. */
    951                 ts.tv_sec = seconds_left;
    952                 ts.tv_nsec = 0;
    953 
    954                 DEBUG(10,("wait_for_aio_completion: %d events, doing a wait "
    955                           "of %d seconds.\n",
    956                           aio_completion_count, seconds_left ));
    957 
    958                 err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list,
    959                                           aio_completion_count, &ts);
    960 
    961                 DEBUG(10,("wait_for_aio_completion: returned err = %d, "
    962                           "errno = %s\n", err, strerror(errno) ));
    963 
    964                 if (err == -1 && errno == EAGAIN) {
    965                         DEBUG(0,("wait_for_aio_completion: aio_suspend timed "
    966                                  "out waiting for %d events after a wait of "
    967                                  "%d seconds\n", aio_completion_count,
    968                                  seconds_left));
    969                         /* Timeout. */
    970                         cancel_aio_by_fsp(fsp);
    971                         SAFE_FREE(aiocb_list);
    972                         return EIO;
    973                 }
    974 
    975                 /* One or more events might have completed - process them if
    976                  * so. */
    977                 for( i = 0; i < aio_completion_count; i++) {
    978                         aio_ex = (struct aio_extra *)aiocb_list[i]->aio_sigevent.sigev_value.sival_ptr;
    979 
    980                         if (!handle_aio_completed(aio_ex, &err)) {
    981                                 continue;
    982                         }
    983                         TALLOC_FREE(aio_ex);
    984                 }
    985 
    986                 SAFE_FREE(aiocb_list);
    987                 seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT
    988                         - (time_mono(NULL) - start_time);
    989         }
    990 
    991         /* We timed out - we don't know why. Return ret if already an error,
    992          * else EIO. */
    993         DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting "
    994                   "for %d events\n",
    995                   aio_completion_count));
    996 
    997         return EIO;
    998 }
    999 
    1000 /****************************************************************************
    1001  Cancel any outstanding aio requests. The client doesn't care about the reply.
    1002 *****************************************************************************/
    1003 
    1004 void cancel_aio_by_fsp(files_struct *fsp)
    1005 {
    1006         struct aio_extra *aio_ex;
    1007 
    1008         for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
    1009                 if (aio_ex->fsp == fsp) {
    1010                         /* Unlock now we're done. */
    1011                         SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
    1012 
    1013                         /* Don't delete the aio_extra record as we may have
    1014                            completed and don't yet know it. Just do the
    1015                            aio_cancel call and return. */
    1016                         SMB_VFS_AIO_CANCEL(fsp, &aio_ex->acb);
    1017                         aio_ex->fsp = NULL; /* fsp will be closed when we
    1018                                              * return. */
    1019                 }
    1020         }
    1021 }
    1022 
    1023 #else
    1024 NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
    1025                              struct smb_request *smbreq,
    1026                              files_struct *fsp, SMB_OFF_T startpos,
    1027                              size_t smb_maxcnt)
    1028 {
    1029         return NT_STATUS_RETRY;
    1030 }
    1031 
    1032 NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
    1033                               struct smb_request *smbreq,
    1034                               files_struct *fsp, char *data,
    1035                               SMB_OFF_T startpos,
    1036                               size_t numtowrite)
    1037 {
    1038         return NT_STATUS_RETRY;
    1039 }
    1040 
    1041 NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
    1042                                 struct smb_request *smbreq,
    1043                                 files_struct *fsp,
    1044                                 TALLOC_CTX *ctx,
    1045                                 DATA_BLOB *preadbuf,
    1046                                 SMB_OFF_T startpos,
    1047                                 size_t smb_maxcnt)
    1048 {
    1049         return NT_STATUS_RETRY;
    1050 }
    1051 
    1052 NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
    1053                                 struct smb_request *smbreq,
    1054                                 files_struct *fsp,
    1055                                 uint64_t in_offset,
    1056                                 DATA_BLOB in_data,
    1057                                 bool write_through)
    1058 {
    1059         return NT_STATUS_RETRY;
    1060 }
    1061 
    1062 void cancel_aio_by_fsp(files_struct *fsp)
    1063 {
    1064 }
    1065 
    1066 int wait_for_aio_completion(files_struct *fsp)
    1067 {
    1068         return 0;
    1069 }
    1070 
    1071 void smbd_aio_complete_mid(uint64_t mid);
    1072 
    1073 #endif
     981}
Note: See TracChangeset for help on using the changeset viewer.