From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/smbd/aio.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 161 insertions(+), 20 deletions(-) (limited to 'source3/smbd/aio.c') diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 49855796b7..6ee0fe16e1 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -48,10 +48,8 @@ static struct aio_extra *aio_list_head; of the aio_read call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_read(files_struct *fsp, - size_t buflen, - uint16 mid, - const uint8 *inbuf) +static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, + uint16 mid) { struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); @@ -67,14 +65,6 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp, SAFE_FREE(aio_ex); return NULL; } - /* Save the first 8 bytes of inbuf for possible enc data. */ - aio_ex->inbuf = SMB_MALLOC_ARRAY(char, 8); - if (!aio_ex->inbuf) { - SAFE_FREE(aio_ex->outbuf); - SAFE_FREE(aio_ex); - return NULL; - } - memcpy(aio_ex->inbuf, inbuf, 8); DLIST_ADD(aio_list_head, aio_ex); aio_ex->fsp = fsp; aio_ex->read_req = True; @@ -240,14 +230,13 @@ BOOL schedule_aio_read_and_X(connection_struct *conn, bufsize = smb_size + 12 * 2 + smb_maxcnt; - if (!(aio_ex = create_aio_ex_read(fsp, bufsize, req->mid, - req->inbuf))) { + if ((aio_ex = create_aio_ex_read(fsp, bufsize, req->mid)) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } construct_reply_common((char *)req->inbuf, aio_ex->outbuf); - set_message((char *)req->inbuf, aio_ex->outbuf, 12, 0, True); + set_message(aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; @@ -292,6 +281,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, struct aio_extra *aio_ex; SMB_STRUCT_AIOCB *a; size_t inbufsize, outbufsize; + BOOL write_through = BITSETW(req->inbuf+smb_vwv7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); if (!min_aio_write_size || (numtowrite < min_aio_write_size)) { @@ -359,7 +349,22 @@ BOOL schedule_aio_write_and_X(connection_struct *conn, return False; } - srv_defer_sign_response(aio_ex->mid); + if (!write_through && !lp_syncalways(SNUM(fsp->conn)) + && fsp->aio_write_behind) { + /* Lie to the client and immediately claim we finished the + * write. */ + SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite); + SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1); + show_msg(aio_ex->outbuf); + if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) { + exit_server_cleanly("handle_aio_write: send_smb " + "failed."); + } + DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " + "behind for file %s\n", fsp->fsp_name )); + } else { + srv_defer_sign_response(aio_ex->mid); + } outstanding_aio_calls++; DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " @@ -382,7 +387,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) int ret = 0; int outsize; char *outbuf = aio_ex->outbuf; - char *inbuf = aio_ex->inbuf; char *data = smb_buf(outbuf); ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb); @@ -406,7 +410,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) outsize = (UNIXERROR(ERRDOS,ERRnoaccess)); ret = errno; } else { - outsize = set_message(inbuf,outbuf,12,nread,False); + outsize = set_message(outbuf,12,nread,False); SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */ SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); @@ -419,7 +423,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } - smb_setlen(inbuf,outbuf,outsize - 4); + smb_setlen(outbuf,outsize - 4); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) { exit_server_cleanly("handle_aio_read_complete: send_smb " @@ -444,10 +448,34 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) int ret = 0; files_struct *fsp = aio_ex->fsp; char *outbuf = aio_ex->outbuf; - char *inbuf = aio_ex->inbuf; ssize_t numtowrite = aio_ex->acb.aio_nbytes; ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb); + if (fsp->aio_write_behind) { + if (nwritten != numtowrite) { + if (nwritten == -1) { + DEBUG(5,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Error %s\n", + fsp->fsp_name, strerror(errno) )); + ret = errno; + } else { + DEBUG(0,("handle_aio_write_complete: " + "aio_write_behind failed ! File %s " + "is corrupt ! Wanted %u bytes but " + "only wrote %d\n", fsp->fsp_name, + (unsigned int)numtowrite, + (int)nwritten )); + ret = EIO; + } + } else { + DEBUG(10,("handle_aio_write_complete: " + "aio_write_behind completed for file %s\n", + fsp->fsp_name )); + } + return 0; + } + /* We don't need outsize or set_message here as we've already set the fixed size length when we set up the aio call. */ @@ -589,6 +617,115 @@ int process_aio_queue(void) return ret; } +/**************************************************************************** + We're doing write behind and the client closed the file. Wait up to 30 + seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes + completed, errno to return if not. +*****************************************************************************/ + +#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29 + +int wait_for_aio_completion(files_struct *fsp) +{ + struct aio_extra *aio_ex; + const SMB_STRUCT_AIOCB **aiocb_list; + int aio_completion_count = 0; + time_t start_time = time(NULL); + int seconds_left; + + for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT; + seconds_left >= 0;) { + int err = 0; + int i; + struct timespec ts; + + aio_completion_count = 0; + for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aio_completion_count++; + } + } + + if (!aio_completion_count) { + return 0; + } + + DEBUG(3,("wait_for_aio_completion: waiting for %d aio events " + "to complete.\n", aio_completion_count )); + + aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *, + aio_completion_count); + if (!aiocb_list) { + return ENOMEM; + } + + for( i = 0, aio_ex = aio_list_head; + aio_ex; + aio_ex = aio_ex->next) { + if (aio_ex->fsp == fsp) { + aiocb_list[i++] = &aio_ex->acb; + } + } + + /* Now wait up to seconds_left for completion. */ + ts.tv_sec = seconds_left; + ts.tv_nsec = 0; + + DEBUG(10,("wait_for_aio_completion: %d events, doing a wait " + "of %d seconds.\n", + aio_completion_count, seconds_left )); + + err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list, + aio_completion_count, &ts); + + DEBUG(10,("wait_for_aio_completion: returned err = %d, " + "errno = %s\n", err, strerror(errno) )); + + if (err == -1 && errno == EAGAIN) { + DEBUG(0,("wait_for_aio_completion: aio_suspend timed " + "out waiting for %d events after a wait of " + "%d seconds\n", aio_completion_count, + seconds_left)); + /* Timeout. */ + cancel_aio_by_fsp(fsp); + SAFE_FREE(aiocb_list); + return EIO; + } + + /* One or more events might have completed - process them if + * so. */ + for( i = 0; i < aio_completion_count; i++) { + uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int; + + aio_ex = find_aio_ex(mid); + + if (!aio_ex) { + DEBUG(0, ("wait_for_aio_completion: mid %u " + "doesn't match an aio record\n", + (unsigned int)mid )); + continue; + } + + if (!handle_aio_completed(aio_ex, &err)) { + continue; + } + delete_aio_ex(aio_ex); + } + + SAFE_FREE(aiocb_list); + seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT + - (time(NULL) - start_time); + } + + /* We timed out - we don't know why. Return ret if already an error, + * else EIO. */ + DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting " + "for %d events\n", + aio_completion_count)); + + return EIO; +} + /**************************************************************************** Cancel any outstanding aio requests. The client doesn't care about the reply. *****************************************************************************/ @@ -645,4 +782,8 @@ void cancel_aio_by_fsp(files_struct *fsp) { } +BOOL wait_for_aio_completion(files_struct *fsp) +{ + return True; +} #endif -- cgit