diff options
author | Monty <monty@mariadb.org> | 2017-12-29 13:22:34 +0200 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2017-12-29 13:38:55 +0200 |
commit | afbb72b3b6988f4c5242d46588754517724b2950 (patch) | |
tree | 7a437137688a9c0b64f54b767a8a6fd2d56c17bf /mysys | |
parent | e64184134a19579dbe5bf98fc54f0f6236aabbcd (diff) | |
download | mariadb-git-afbb72b3b6988f4c5242d46588754517724b2950.tar.gz |
Made IO_CACHE safe for reading big blocks (> 2G)
The reason for adding this was that while testing mysqlbinlog on
a replication event with 3G event output, Linux failed reading
the whole file in memory with one read (only got 2G on first read
even if file had just been written).
- Don't reset info->error on write error in IO_CACHE.
- In case of write_error in IO_CACHE , always return -1
- Fixed wrong result from my_read when using MY_FULL_IO. Also don't give
an error in case of retry.
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/mf_iocache.c | 11 | ||||
-rw-r--r-- | mysys/my_read.c | 40 |
2 files changed, 29 insertions, 22 deletions
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index a52ea2c5c40..4dd0f7500aa 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -115,6 +115,7 @@ init_functions(IO_CACHE* info) DBUG_ASSERT(!(info->myflags & MY_ENCRYPT)); info->read_function = info->share ? _my_b_cache_read_r : _my_b_cache_read; info->write_function = info->share ? _my_b_cache_write_r : _my_b_cache_write; + info->myflags&= ~MY_FULL_IO; break; case TYPE_NOT_SET: DBUG_ASSERT(0); @@ -455,6 +456,8 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, { info->read_end=info->write_pos; info->end_of_file=my_b_tell(info); + /* Ensure we will read all data */ + info->myflags|= MY_FULL_IO; /* Trigger a new seek only if we have a valid file handle. @@ -469,6 +472,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, info->seek_not_done=1; } info->end_of_file = ~(my_off_t) 0; + info->myflags&= ~MY_FULL_IO; } pos=info->request_pos+(seek_offset-info->pos_in_file); if (type == WRITE_CACHE) @@ -1917,13 +1921,12 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock) { if (append_cache) { - if (mysql_file_write(info->file, info->write_buffer, length, info->myflags | MY_NABP)) + { info->error= -1; - else - info->error= 0; - + DBUG_RETURN(-1); + } info->end_of_file+= info->write_pos - info->append_read_pos; info->append_read_pos= info->write_buffer; DBUG_ASSERT(info->end_of_file == mysql_file_tell(info->file, MYF(0))); diff --git a/mysys/my_read.c b/mysys/my_read.c index 922da5a7e95..89b368e9800 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -35,11 +35,10 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) { - size_t readbytes, save_count; + size_t readbytes, save_count= 0; DBUG_ENTER("my_read"); DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %lu", Filedes, Buffer, (ulong) Count, MyFlags)); - save_count= Count; if (!(MyFlags & (MY_WME | MY_FAE | MY_FNABP))) MyFlags|= my_global_flags; @@ -61,47 +60,52 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) if (readbytes != Count) { - my_errno= errno; - if (errno == 0 || (readbytes != (size_t) -1 && - (MyFlags & (MY_NABP | MY_FNABP)))) - my_errno= HA_ERR_FILE_TOO_SHORT; + int got_errno= my_errno= errno; DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d", (int) readbytes, (ulong) Count, Filedes, - my_errno)); + got_errno)); + + if (got_errno == 0 || (readbytes != (size_t) -1 && + (MyFlags & (MY_NABP | MY_FNABP)))) + my_errno= HA_ERR_FILE_TOO_SHORT; - if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR) + if ((readbytes == 0 || (int) readbytes == -1) && got_errno == EINTR) { DBUG_PRINT("debug", ("my_read() was interrupted and returned %ld", (long) readbytes)); continue; /* Interrupted */ } + /* Do a read retry if we didn't get enough data on first read */ + if (readbytes != (size_t) -1 && readbytes != 0 && + (MyFlags & MY_FULL_IO)) + { + Buffer+= readbytes; + Count-= readbytes; + save_count+= readbytes; + continue; + } + if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { if (readbytes == (size_t) -1) my_error(EE_READ, MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), - my_filename(Filedes),my_errno); + my_filename(Filedes), got_errno); else if (MyFlags & (MY_NABP | MY_FNABP)) my_error(EE_EOFERR, MYF(ME_BELL | ME_WAITTANG | (MyFlags & (ME_JUST_INFO | ME_NOREFRESH))), - my_filename(Filedes),my_errno); + my_filename(Filedes), got_errno); } if (readbytes == (size_t) -1 || ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO))) DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ - if (readbytes != (size_t) -1 && (MyFlags & MY_FULL_IO)) - { - Buffer+= readbytes; - Count-= readbytes; - continue; - } } if (MyFlags & (MY_NABP | MY_FNABP)) readbytes= 0; /* Ok on read */ - else if (MyFlags & MY_FULL_IO) - readbytes= save_count; + else + readbytes+= save_count; break; } DBUG_RETURN(readbytes); |