diff options
Diffstat (limited to 'storage/innobase/include/os0file.h')
-rw-r--r-- | storage/innobase/include/os0file.h | 203 |
1 files changed, 177 insertions, 26 deletions
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 57ee015dfdd..6a97ff3aa53 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -36,7 +36,8 @@ Created 10/21/1995 Heikki Tuuri #ifndef os0file_h #define os0file_h -#include "univ.i" +#include "page0size.h" +#include "os0api.h" #ifndef _WIN32 #include <dirent.h> @@ -46,8 +47,10 @@ Created 10/21/1995 Heikki Tuuri /** File node of a tablespace or the log data space */ struct fil_node_t; +struct fil_space_t; extern bool os_has_said_disk_full; +extern my_bool srv_use_trim; /** Number of pending read operations */ extern ulint os_n_pending_reads; @@ -177,6 +180,8 @@ static const ulint OS_FILE_ERROR_MAX = 200; #define IORequestLogRead IORequest(IORequest::LOG | IORequest::READ) #define IORequestLogWrite IORequest(IORequest::LOG | IORequest::WRITE) + + /** The IO Context that is passed down to the low level IO code */ class IORequest { @@ -211,12 +216,16 @@ public: /** Ignore failed reads of non-existent pages */ IGNORE_MISSING = 128, + + /** Use punch hole if available*/ + PUNCH_HOLE = 256, }; /** Default constructor */ IORequest() : - m_block_size(UNIV_SECTOR_SIZE), + m_bpage(NULL), + m_fil_node(NULL), m_type(READ) { /* No op */ @@ -227,9 +236,32 @@ public: ORed from the above enum */ explicit IORequest(ulint type) : - m_block_size(UNIV_SECTOR_SIZE), + m_bpage(NULL), + m_fil_node(NULL), + m_type(static_cast<uint16_t>(type)) + { + if (!is_punch_hole_supported() || !srv_use_trim) { + clear_punch_hole(); + } + } + + /** + @param[in] type Request type, can be a value that is + ORed from the above enum + @param[in] bpage Page to be written */ + IORequest(ulint type, buf_page_t* bpage) + : + m_bpage(bpage), + m_fil_node(NULL), m_type(static_cast<uint16_t>(type)) { + if (bpage && buf_page_should_punch_hole(bpage)) { + set_punch_hole(); + } + + if (!is_punch_hole_supported() || !srv_use_trim) { + clear_punch_hole(); + } } /** Destructor */ @@ -270,6 +302,12 @@ public: return((m_type & DO_NOT_WAKE) == 0); } + /** Clear the punch hole flag */ + void clear_punch_hole() + { + m_type &= ~PUNCH_HOLE; + } + /** @return true if partial read warning disabled */ bool is_partial_io_warning_disabled() const MY_ATTRIBUTE((warn_unused_result)) @@ -291,6 +329,13 @@ public: return(ignore_missing(m_type)); } + /** @return true if punch hole should be used */ + bool punch_hole() const + MY_ATTRIBUTE((warn_unused_result)) + { + return((m_type & PUNCH_HOLE) == PUNCH_HOLE); + } + /** @return true if the read should be validated */ bool validate() const MY_ATTRIBUTE((warn_unused_result)) @@ -298,24 +343,30 @@ public: return(is_read() ^ is_write()); } + /** Set the punch hole flag */ + void set_punch_hole() + { + if (is_punch_hole_supported() && srv_use_trim) { + m_type |= PUNCH_HOLE; + } + } + /** Clear the do not wake flag */ void clear_do_not_wake() { m_type &= ~DO_NOT_WAKE; } - /** @return the block size to use for IO */ - ulint block_size() const - MY_ATTRIBUTE((warn_unused_result)) + /** Set the pointer to file node for IO + @param[in] node File node */ + void set_fil_node(fil_node_t* node) { - return(m_block_size); - } + if (!srv_use_trim || + (node && !fil_node_should_punch_hole(node))) { + clear_punch_hole(); + } - /** Set the block size for IO - @param[in] block_size Block size to set */ - void block_size(ulint block_size) - { - m_block_size = static_cast<uint32_t>(block_size); + m_fil_node = node; } /** Compare two requests @@ -338,9 +389,59 @@ public: return((m_type & DBLWR_RECOVER) == DBLWR_RECOVER); } + /** @return true if punch hole is supported */ + static bool is_punch_hole_supported() + { + + /* In this debugging mode, we act as if punch hole is supported, + and then skip any calls to actually punch a hole here. + In this way, Transparent Page Compression is still being tested. */ + DBUG_EXECUTE_IF("ignore_punch_hole", + return(true); + ); + +#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32) + return(true); +#else + return(false); +#endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || _WIN32 */ + } + + ulint get_trim_length(ulint write_length) const + { + return (m_bpage ? + buf_page_get_trim_length(m_bpage, write_length) + : 0); + } + + bool should_punch_hole() const { + return (m_fil_node ? + fil_node_should_punch_hole(m_fil_node) + : false); + } + + void space_no_punch_hole() const { + if (m_fil_node) { + fil_space_set_punch_hole(m_fil_node, false); + } + } + + /** Punch a hole in the file if it was a write + @param[in] fh Open file handle + @param[in] len Compressed buffer length for write + @return DB_SUCCESS or error code */ + + dberr_t punch_hole( + os_file_t fh, + ulint offset, + ulint len); + private: - /* File system best block size */ - uint32_t m_block_size; + /** Page to be written on write operation. */ + buf_page_t* m_bpage; + + /** File node */ + fil_node_t* m_fil_node; /** Request type bit flags */ uint16_t m_type; @@ -706,10 +807,10 @@ The wrapper functions have the prefix of "innodb_". */ # define os_file_close(file) \ pfs_os_file_close_func(file, __FILE__, __LINE__) -# define os_aio(type, mode, name, file, buf, offset, \ - n, read_only, message1, message2, wsize) \ - pfs_os_aio_func(type, mode, name, file, buf, offset, \ - n, read_only, message1, message2, wsize, \ +# define os_aio(type, mode, name, file, buf, offset, \ + n, read_only, message1, message2) \ + pfs_os_aio_func(type, mode, name, file, buf, offset, \ + n, read_only, message1, message2, \ __FILE__, __LINE__) # define os_file_read(type, file, buf, offset, n) \ @@ -721,7 +822,7 @@ The wrapper functions have the prefix of "innodb_". */ # define os_file_write(type, name, file, buf, offset, n) \ pfs_os_file_write_func(type, name, file, buf, offset, \ - n, __FILE__, __LINE__) + n,__FILE__, __LINE__) # define os_file_flush(file) \ pfs_os_file_flush_func(file, __FILE__, __LINE__) @@ -926,7 +1027,6 @@ pfs_os_aio_func( bool read_only, fil_node_t* m1, void* m2, - ulint* wsize, const char* src_file, ulint src_line); @@ -1051,9 +1151,9 @@ to original un-instrumented file I/O APIs */ # define os_file_close(file) os_file_close_func(file) # define os_aio(type, mode, name, file, buf, offset, \ - n, read_only, message1, message2, wsize) \ + n, read_only, message1, message2) \ os_aio_func(type, mode, name, file, buf, offset, \ - n, read_only, message1, message2, wsize) + n, read_only, message1, message2) # define os_file_read(type, file, buf, offset, n) \ os_file_read_func(type, file, buf, offset, n) @@ -1061,7 +1161,7 @@ to original un-instrumented file I/O APIs */ # define os_file_read_no_error_handling(type, file, buf, offset, n, o) \ os_file_read_no_error_handling_func(type, file, buf, offset, n, o) -# define os_file_write(type, name, file, buf, offset, n) \ +# define os_file_write(type, name, file, buf, offset, n) \ os_file_write_func(type, name, file, buf, offset, n) # define os_file_flush(file) os_file_flush_func(file) @@ -1324,8 +1424,7 @@ os_aio_func( ulint n, bool read_only, fil_node_t* m1, - void* m2, - ulint* wsize); + void* m2); /** Wakes up all async i/o threads so that they know to exit themselves in shutdown. */ @@ -1427,6 +1526,48 @@ innobase_mysql_tmpfile( void os_file_set_umask(ulint umask); +/** Check if the file system supports sparse files. + +Warning: On POSIX systems we try and punch a hole from offset 0 to +the system configured page size. This should only be called on an empty +file. + +Note: On Windows we use the name and on Unices we use the file handle. + +@param[in] name File name +@param[in] fh File handle for the file - if opened +@return true if the file system supports sparse files */ +bool +os_is_sparse_file_supported( + const char* path, + os_file_t fh) + MY_ATTRIBUTE((warn_unused_result)); + +/** Free storage space associated with a section of the file. +@param[in] fh Open file handle +@param[in] off Starting offset (SEEK_SET) +@param[in] len Size of the hole +@return DB_SUCCESS or error code */ +dberr_t +os_file_punch_hole( + IORequest& type, + os_file_t fh, + os_offset_t off, + os_offset_t len) + MY_ATTRIBUTE((warn_unused_result)); + +/** Free storage space associated with a section of the file. +@param[in] fh Open file handle +@param[in] off Starting offset (SEEK_SET) +@param[in] len Size of the hole +@return DB_SUCCESS or error code */ +dberr_t +os_file_punch_hole( + os_file_t fh, + os_offset_t off, + os_offset_t len) + MY_ATTRIBUTE((warn_unused_result)); + /** Normalizes a directory path for the current OS: On Windows, we convert '/' to '\', else we convert '\' to '/'. @param[in,out] str A null-terminated directory and file path */ @@ -1454,6 +1595,16 @@ is_absolute_path( return(false); } +/***********************************************************************//** +Try to get number of bytes per sector from file system. +@return file block size */ +UNIV_INTERN +ulint +os_file_get_block_size( +/*===================*/ + os_file_t file, /*!< in: handle to a file */ + const char* name); /*!< in: file name */ + #ifndef UNIV_NONINL #include "os0file.ic" #endif /* UNIV_NONINL */ |