summaryrefslogtreecommitdiff
path: root/storage/innobase/include/os0file.h
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/os0file.h')
-rw-r--r--storage/innobase/include/os0file.h203
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 */