Changeset 988 for vendor/current/source3/smbd/aio.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/smbd/aio.c
r746 r988 23 23 #include "smbd/globals.h" 24 24 #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 32 static int outstanding_aio_calls; 33 34 int get_outstanding_aio_calls(void) 35 { 36 return outstanding_aio_calls; 37 } 38 39 void increment_outstanding_aio_calls(void) 40 { 41 outstanding_aio_calls++; 42 } 43 44 void decrement_outstanding_aio_calls(void) 45 { 46 outstanding_aio_calls--; 47 } 39 48 40 49 /**************************************************************************** … … 43 52 44 53 struct aio_extra { 45 struct aio_extra *next, *prev;46 SMB_STRUCT_AIOCB acb;47 54 files_struct *fsp; 48 55 struct smb_request *smbreq; 49 56 DATA_BLOB outbuf; 50 57 struct lock_struct lock; 58 size_t nbyte; 59 off_t offset; 51 60 bool write_through; 52 int (*handle_completion)(struct aio_extra *ex, int errcode);53 61 }; 54 62 55 63 /**************************************************************************** 56 Initialize the signal handler for aio read/write.64 Accessor function to return write_through state. 57 65 *****************************************************************************/ 58 66 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); 67 bool aio_write_through_requested(struct aio_extra *aio_ex) 68 { 69 return aio_ex->write_through; 70 } 104 71 105 72 static int aio_extra_destructor(struct aio_extra *aio_ex) 106 73 { 107 DLIST_REMOVE(aio_list_head, aio_ex);74 decrement_outstanding_aio_calls(); 108 75 return 0; 109 76 } … … 118 85 size_t buflen) 119 86 { 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); 121 88 122 89 if (!aio_ex) { … … 135 102 } 136 103 } 137 DLIST_ADD(aio_list_head, aio_ex);138 104 talloc_set_destructor(aio_ex, aio_extra_destructor); 139 105 aio_ex->fsp = fsp; 106 increment_outstanding_aio_calls(); 140 107 return aio_ex; 141 108 } 109 110 struct aio_req_fsp_link { 111 files_struct *fsp; 112 struct tevent_req *req; 113 }; 114 115 static 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 139 bool 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 172 static void aio_pread_smb1_done(struct tevent_req *req); 142 173 143 174 /**************************************************************************** … … 147 178 NTSTATUS schedule_aio_read_and_X(connection_struct *conn, 148 179 struct smb_request *smbreq, 149 files_struct *fsp, SMB_OFF_Tstartpos,180 files_struct *fsp, off_t startpos, 150 181 size_t smb_maxcnt) 151 182 { 152 183 struct aio_extra *aio_ex; 153 SMB_STRUCT_AIOCB *a;154 184 size_t bufsize; 155 185 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; 162 187 163 188 if (fsp->base_fsp != NULL) { … … 183 208 } 184 209 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 192 210 /* The following is safe from integer wrap as we've already checked 193 211 smb_maxcnt is 128k or less. Wct is 12 for read replies */ 194 212 195 bufsize = smb_size + 12 * 2 + smb_maxcnt ;213 bufsize = smb_size + 12 * 2 + smb_maxcnt + 1 /* padding byte */; 196 214 197 215 if ((aio_ex = create_aio_extra(NULL, fsp, bufsize)) == NULL) { … … 199 217 return NT_STATUS_NO_MEMORY; 200 218 } 201 aio_ex->handle_completion = handle_aio_read_complete;202 219 203 220 construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data); 204 221 srv_set_message((char *)aio_ex->outbuf.data, 12, 0, True); 205 222 SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */ 223 SCVAL(smb_buf(aio_ex->outbuf.data), 0, 0); /* padding byte */ 206 224 207 225 init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid, … … 215 233 } 216 234 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) { 231 243 DEBUG(0,("schedule_aio_read_and_X: aio_read failed. " 232 244 "Error %s\n", strerror(errno) )); … … 235 247 return NT_STATUS_RETRY; 236 248 } 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 239 258 aio_ex->smbreq = talloc_move(aio_ex, &smbreq); 240 259 … … 247 266 } 248 267 268 static 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 337 struct pwrite_fsync_state { 338 struct tevent_context *ev; 339 files_struct *fsp; 340 bool write_through; 341 ssize_t nwritten; 342 }; 343 344 static void pwrite_fsync_write_done(struct tevent_req *subreq); 345 static void pwrite_fsync_sync_done(struct tevent_req *subreq); 346 347 static 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 373 static 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 404 static 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 419 static 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 430 static void aio_pwrite_smb1_done(struct tevent_req *req); 431 249 432 /**************************************************************************** 250 433 Set up an aio request from a SMBwriteX call. … … 253 436 NTSTATUS schedule_aio_write_and_X(connection_struct *conn, 254 437 struct smb_request *smbreq, 255 files_struct *fsp, c har *data,256 SMB_OFF_Tstartpos,438 files_struct *fsp, const char *data, 439 off_t startpos, 257 440 size_t numtowrite) 258 441 { 259 442 struct aio_extra *aio_ex; 260 SMB_STRUCT_AIOCB *a;261 443 size_t bufsize; 262 444 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; 269 446 270 447 if (fsp->base_fsp != NULL) { … … 290 467 } 291 468 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 305 469 bufsize = smb_size + 6*2; 306 470 … … 309 473 return NT_STATUS_NO_MEMORY; 310 474 } 311 aio_ex->handle_completion = handle_aio_write_complete;312 475 aio_ex->write_through = BITSETW(smbreq->vwv+7,0); 313 476 … … 326 489 } 327 490 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) { 342 498 DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. " 343 499 "Error %s\n", strerror(errno) )); … … 346 502 return NT_STATUS_RETRY; 347 503 } 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 350 513 aio_ex->smbreq = talloc_move(aio_ex, &smbreq); 351 514 … … 354 517 contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE); 355 518 356 if (!aio_ex->write_through && !lp_sync always(SNUM(fsp->conn))519 if (!aio_ex->write_through && !lp_sync_always(SNUM(fsp->conn)) 357 520 && fsp->aio_write_behind) { 358 521 /* Lie to the client and immediately claim we finished the … … 361 524 SSVAL(aio_ex->outbuf.data,smb_vwv4,(numtowrite>>16)&1); 362 525 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, 364 527 (char *)aio_ex->outbuf.data, 365 528 true, aio_ex->smbreq->seqnum+1, … … 377 540 "outstanding_aio_calls = %d\n", 378 541 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() )); 380 544 381 545 return NT_STATUS_OK; 382 546 } 547 548 static 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 645 bool 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 672 static void aio_pread_smb2_done(struct tevent_req *req); 383 673 384 674 /**************************************************************************** … … 391 681 TALLOC_CTX *ctx, 392 682 DATA_BLOB *preadbuf, 393 SMB_OFF_Tstartpos,683 off_t startpos, 394 684 size_t smb_maxcnt) 395 685 { 396 686 struct aio_extra *aio_ex; 397 SMB_STRUCT_AIOCB *a;398 687 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; 405 689 406 690 if (fsp->base_fsp != NULL) { 407 691 /* No AIO on streams yet */ 408 692 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. */ 409 698 return NT_STATUS_RETRY; 410 699 } … … 425 714 } 426 715 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 434 716 /* Create the out buffer. */ 435 717 *preadbuf = data_blob_talloc(ctx, NULL, smb_maxcnt); … … 441 723 return NT_STATUS_NO_MEMORY; 442 724 } 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, 446 727 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK, 447 728 &aio_ex->lock); … … 453 734 } 454 735 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))); 471 744 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock); 472 745 TALLOC_FREE(aio_ex); 473 746 return NT_STATUS_RETRY; 474 747 } 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 477 757 /* We don't need talloc_move here as both aio_ex and 478 758 * smbreq are children of smbreq->smb2req. */ 479 759 aio_ex->smbreq = smbreq; 760 smbreq->async_priv = aio_ex; 480 761 481 762 DEBUG(10,("smb2: scheduled aio_read for file %s, " … … 486 767 return NT_STATUS_OK; 487 768 } 769 770 static 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 822 static void aio_pwrite_smb2_done(struct tevent_req *req); 488 823 489 824 /**************************************************************************** … … 499 834 { 500 835 struct aio_extra *aio_ex = NULL; 501 SMB_STRUCT_AIOCB *a = NULL;502 836 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; 509 838 510 839 if (fsp->base_fsp != NULL) { 511 840 /* No AIO on streams yet */ 512 841 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. */ 513 847 return NT_STATUS_RETRY; 514 848 } … … 529 863 } 530 864 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. */ 535 867 return NT_STATUS_RETRY; 536 868 } … … 540 872 } 541 873 542 aio_ex->handle_completion = handle_aio_smb2_write_complete;543 874 aio_ex->write_through = write_through; 544 875 545 init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,876 init_strict_lock_struct(fsp, fsp->op->global->open_persistent_id, 546 877 in_offset, (uint64_t)in_data.length, WRITE_LOCK, 547 878 &aio_ex->lock); … … 553 884 } 554 885 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))); 571 895 SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock); 572 896 TALLOC_FREE(aio_ex); 573 897 return NT_STATUS_RETRY; 574 898 } 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 577 908 /* We don't need talloc_move here as both aio_ex and 578 909 * smbreq are children of smbreq->smb2req. */ 579 910 aio_ex->smbreq = smbreq; 911 smbreq->async_priv = aio_ex; 580 912 581 913 /* This should actually be improved to span the write. */ … … 596 928 (unsigned int)in_data.length, 597 929 (unsigned int)aio_ex->smbreq->mid, 598 outstanding_aio_calls));930 get_outstanding_aio_calls() )); 599 931 600 932 return NT_STATUS_OK; 601 933 } 602 934 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 { 935 static 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; 668 941 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 the699 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 {758 942 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))); 780 975 781 976 if (!NT_STATUS_IS_OK(status)) { 782 977 tevent_req_nterror(subreq, status); 783 return errcode; 784 } 785 978 return; 979 } 786 980 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.