Commit b731a5bc authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

Innodb : Refactor os_file_set_size() to be compatible 10.1

The last parameter to this function is now,"bool is_sparse", like in 10.1
rather than the  unused/useless "bool is_readonly", merged from MySQL 5.7

Like in 10.1, this function now supports sparse files, and efficient
platform specific mechanisms for file extension

os_file_set_size() is now consistenly used in all places where
innodb files are extended.
parent 0b5a5258
......@@ -4022,8 +4022,7 @@ xb_space_create_file(
}
ret = os_file_set_size(path, *file,
FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE,
false);
FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE);
if (!ret) {
msg("xtrabackup: cannot set size for file %s\n", path);
os_file_close(*file);
......
......@@ -1061,139 +1061,28 @@ fil_space_extend_must_retry(
const page_size_t pageSize(space->flags);
const ulint page_size = pageSize.physical();
#ifdef _WIN32
os_offset_t new_file_size =
std::max(
os_offset_t(size - file_start_page_no) * page_size,
os_offset_t(FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE));
/* os_file_change_size_win32() handles both compressed(sparse)
and normal files correctly.
It allocates physical storage for normal files and "virtual"
storage for sparse ones.*/
*success = os_file_change_size_win32(node->name,
node->handle, new_file_size);
/* fil_read_first_page() expects UNIV_PAGE_SIZE bytes.
fil_node_open_file() expects at least 4 * UNIV_PAGE_SIZE bytes.*/
os_offset_t new_size = std::max(
os_offset_t(size - file_start_page_no) * page_size,
os_offset_t(FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE));
*success = os_file_set_size(node->name, node->handle, new_size,
FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags));
os_has_said_disk_full = *success;
if (*success) {
last_page_no = size;
} else {
ib::error() << "extending file '" << node->name
<< " to size " << new_file_size << " failed";
}
#else
/* We will logically extend the file with ftruncate() if
page_compression is enabled, because the file is expected to
be sparse in that case. Make sure that ftruncate() can deal
with large files. */
const bool is_sparse = sizeof(off_t) >= 8
&& FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags);
if (is_sparse) {
/* fil_read_first_page() expects UNIV_PAGE_SIZE bytes.
fil_node_open_file() expects at least 4 * UNIV_PAGE_SIZE bytes.
Do not shrink short ROW_FORMAT=COMPRESSED files. */
off_t s = std::max(off_t(size - file_start_page_no)
* off_t(page_size),
off_t(FIL_IBD_FILE_INITIAL_SIZE
* UNIV_PAGE_SIZE));
*success = !ftruncate(node->handle, s);
if (!*success) {
ib::error() << "ftruncate of file '" << node->name
<< "' from "
<< os_offset_t(last_page_no
- file_start_page_no)
* page_size << " to " << os_offset_t(s)
<< " bytes failed with " << errno;
} else {
last_page_no = size;
}
} else {
const os_offset_t start_offset
= os_offset_t(last_page_no - file_start_page_no)
* page_size;
const ulint n_pages = size - last_page_no;
const os_offset_t len = os_offset_t(n_pages) * page_size;
# ifdef HAVE_POSIX_FALLOCATE
int err;
do {
err = posix_fallocate(node->handle, start_offset, len);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
if (err != EINVAL) {
*success = !err;
if (!*success) {
ib::error() << "extending file '" << node->name
<< "' from "
<< start_offset
<< " to " << len + start_offset
<< " bytes failed with: " << err;
}
} else
# endif /* HAVE_POSIX_FALLOCATE */
{
/* Extend at most 1 megabyte pages at a time */
ulint n_bytes = std::min(ulint(1) << 20, n_pages)
* page_size;
byte* buf2 = static_cast<byte*>(
calloc(1, n_bytes + page_size));
*success = buf2 != NULL;
if (!buf2) {
ib::error() << "Cannot allocate "
<< n_bytes + page_size
<< " bytes to extend file";
}
byte* const buf = static_cast<byte*>(
ut_align(buf2, page_size));
IORequest request(IORequest::WRITE);
os_offset_t offset = start_offset;
const os_offset_t end = start_offset + len;
const bool read_only_mode = space->purpose
== FIL_TYPE_TEMPORARY && srv_read_only_mode;
while (*success && offset < end) {
dberr_t err = os_aio(
request, OS_AIO_SYNC, node->name,
node->handle, buf, offset, n_bytes,
read_only_mode, NULL, NULL);
if (err != DB_SUCCESS) {
*success = false;
ib::error() << "writing zeroes to file '"
<< node->name << "' from "
<< offset << " to " << offset + n_bytes
<< " bytes failed with: "
<< ut_strerr(err);
break;
}
offset += n_bytes;
n_bytes = std::min(n_bytes,
static_cast<ulint>(end - offset));
}
free(buf2);
}
/* Let us measure the size of the file
to determine how much we were able to
extend it */
os_offset_t fsize = os_file_get_size(node->handle);
ut_a(fsize != os_offset_t(-1));
os_has_said_disk_full = *success;
if (*success) {
last_page_no = size;
} else {
/* Let us measure the size of the file
to determine how much we were able to
extend it */
os_offset_t fsize = os_file_get_size(node->handle);
ut_a(fsize != os_offset_t(-1));
last_page_no = ulint(fsize / page_size)
+ file_start_page_no;
}
last_page_no = ulint(fsize / page_size)
+ file_start_page_no;
}
#endif
mutex_enter(&fil_system->mutex);
ut_a(node->being_extended);
......@@ -1206,11 +1095,7 @@ fil_space_extend_must_retry(
const ulint pages_in_MiB = node->size
& ~((1 << (20 - UNIV_PAGE_SIZE_SHIFT)) - 1);
fil_node_complete_io(node,
#ifndef _WIN32
!is_sparse ? IORequestWrite :
#endif /* _WIN32 */
IORequestRead);
fil_node_complete_io(node,IORequestRead);
/* Keep the last data file size info up to date, rounded to
full megabytes */
......@@ -3237,10 +3122,11 @@ fil_truncate_tablespace(
bool success = os_file_truncate(node->name, node->handle, 0);
if (success) {
os_offset_t size = size_in_pages * UNIV_PAGE_SIZE;
os_offset_t size = os_offset_t(size_in_pages) * UNIV_PAGE_SIZE;
success = os_file_set_size(
node->name, node->handle, size, srv_read_only_mode);
node->name, node->handle, size,
FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags));
if (success) {
space->stop_new_ops = false;
......@@ -3835,72 +3721,18 @@ fil_ibd_create(
return(DB_ERROR);
}
bool punch_hole = false;
bool is_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(flags);
#ifdef _WIN32
if (FSP_FLAGS_HAS_PAGE_COMPRESSION(flags)) {
punch_hole = os_file_set_sparse_win32(file);
}
success = os_file_change_size_win32(path, file, size * UNIV_PAGE_SIZE);
#else
success= false;
#ifdef HAVE_POSIX_FALLOCATE
/*
Extend the file using posix_fallocate(). This is required by
FusionIO HW/Firmware but should also be the prefered way to extend
a file.
*/
int ret;
do {
ret = posix_fallocate(file, 0, size * UNIV_PAGE_SIZE);
} while (ret == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
if (ret == 0) {
success = true;
} else if (ret != EINVAL) {
ib::error() <<
"posix_fallocate(): Failed to preallocate"
" data for file " << path
<< ", desired size "
<< size * UNIV_PAGE_SIZE
<< " Operating system error number " << ret
<< ". Check"
" that the disk is not full or a disk quota"
" exceeded. Some operating system error"
" numbers are described at " REFMAN
"operating-system-error-codes.html";
}
#endif /* HAVE_POSIX_FALLOCATE */
if (!success) {
success = os_file_set_size(
path, file, size * UNIV_PAGE_SIZE, srv_read_only_mode);
}
/* Note: We are actually punching a hole, previous contents will
be lost after this call, if it succeeds. In this case the file
should be full of NULs. */
punch_hole = os_is_sparse_file_supported(file);
if (punch_hole) {
dberr_t punch_err;
punch_err = os_file_punch_hole(file, 0, size * UNIV_PAGE_SIZE);
if (punch_err != DB_SUCCESS) {
punch_hole = false;
}
if (is_compressed) {
os_file_set_sparse_win32(file);
}
#endif
ulint block_size = os_file_get_block_size(file, path);
success = os_file_set_size(path, file,
os_offset_t(size)*UNIV_PAGE_SIZE,
FSP_FLAGS_HAS_PAGE_COMPRESSION(flags));
if (!success) {
os_file_close(file);
......@@ -3908,6 +3740,10 @@ fil_ibd_create(
return(DB_OUT_OF_FILE_SPACE);
}
bool punch_hole = os_is_sparse_file_supported(file);
ulint block_size = os_file_get_block_size(file, path);
/* We have to write the space id to the file immediately and flush the
file to disk. This is because in crash recovery we must be aware what
tablespaces exist and what are their space id's, so that we can apply
......
......@@ -410,8 +410,7 @@ SysTablespace::set_size(
bool success = os_file_set_size(
file.m_filepath, file.m_handle,
static_cast<os_offset_t>(file.m_size << UNIV_PAGE_SIZE_SHIFT),
m_ignore_read_only ? false : srv_read_only_mode);
static_cast<os_offset_t>(file.m_size) << UNIV_PAGE_SIZE_SHIFT);
if (success) {
ib::info() << "File '" << file.filepath() << "' size is now "
......
......@@ -1232,19 +1232,27 @@ os_file_get_size(
os_file_t file)
MY_ATTRIBUTE((warn_unused_result));
/** Write the specified number of zeros to a newly created file.
@param[in] name name of the file or path as a null-terminated
string
@param[in] file handle to a file
@param[in] size file size
@param[in] read_only Enable read-only checks if true
@return true if success */
/** Extend a file.
On Windows, extending a file allocates blocks for the file,
unless the file is sparse.
On Unix, we will extend the file with ftruncate(), if
file needs to be sparse. Otherwise posix_fallocate() is used
when available, and if not, binary zeroes are added to the end
of file.
@param[in] name file name
@param[in] file file handle
@param[in] size desired file size
@param[in] sparse whether to create a sparse file (no preallocating)
@return whether the operation succeeded */
bool
os_file_set_size(
const char* name,
os_file_t file,
os_offset_t size,
bool read_only)
bool is_sparse = false)
MY_ATTRIBUTE((warn_unused_result));
/** Truncates a file at its current position.
......
......@@ -5319,23 +5319,56 @@ os_file_set_nocache(
#endif /* _WIN32 */
/** Write the specified number of zeros to a newly created file.
@param[in] name name of the file or path as a null-terminated
string
@param[in] file handle to a file
@param[in] size file size
@param[in] read_only Enable read-only checks if true
@return true if success */
/** Extend a file.
On Windows, extending a file allocates blocks for the file,
unless the file is sparse.
On Unix, we will extend the file with ftruncate(), if
file needs to be sparse. Otherwise posix_fallocate() is used
when available, and if not, binary zeroes are added to the end
of file.
@param[in] name file name
@param[in] file file handle
@param[in] size desired file size
@param[in] sparse whether to create a sparse file (no preallocating)
@return whether the operation succeeded */
bool
os_file_set_size(
const char* name,
os_file_t file,
os_offset_t size,
bool read_only)
bool is_sparse)
{
#ifdef _WIN32
return os_file_change_size_win32(name, file, size);
#endif
#else
if (is_sparse) {
bool success = !ftruncate(file, size);
if (!success) {
ib::error() << "ftruncate of file " << name <<
" to " << size << " bytes failed with error " << errno;
}
return(success);
}
# ifdef HAVE_POSIX_FALLOCATE
int err;
do {
err = posix_fallocate(file, 0, size);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
if (err) {
ib::error() <<
"preallocating " << size << " bytes for" <<
"file " << name << "failed with error " << err;
}
errno = err;
return(!err);
# endif /* HAVE_POSIX_ALLOCATE */
/* Write up to 1 megabyte at a time. */
ulint buf_size = ut_min(
static_cast<ulint>(64),
......@@ -5358,7 +5391,7 @@ os_file_set_size(
ib::info() << "Progress in MB:";
}
os_offset_t current_size = 0;
os_offset_t current_size = os_file_get_size(file);
while (current_size < size) {
ulint n_bytes;
......@@ -5401,6 +5434,7 @@ os_file_set_size(
ut_free(buf2);
return(os_file_flush(file));
#endif /* !WIN32 */
}
/** Truncates a file to a specified size in bytes.
......
......@@ -378,8 +378,7 @@ create_log_file(
ib::info() << "Setting log file " << name << " size to "
<< srv_log_file_size << " bytes";
ret = os_file_set_size(name, *file, srv_log_file_size,
srv_read_only_mode);
ret = os_file_set_size(name, *file, srv_log_file_size);
if (!ret) {
ib::error() << "Cannot set log file " << name << " size to "
<< srv_log_file_size << " bytes";
......@@ -658,8 +657,7 @@ srv_undo_tablespace_create(
<< "wait...";
ret = os_file_set_size(
name, fh, size << UNIV_PAGE_SIZE_SHIFT,
srv_read_only_mode);
name, fh, os_offset_t(size) << UNIV_PAGE_SIZE_SHIFT);
if (!ret) {
ib::info() << "Error in creating " << name
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment