mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Remove mmap(2) based copying; it is slower
This commit is contained in:
@@ -73,48 +73,7 @@ using tpool::pwrite;
|
||||
# include <sys/types.h>
|
||||
# include <dirent.h>
|
||||
# include <sys/mman.h>
|
||||
/**
|
||||
Copy a file using a memory mapping.
|
||||
@tparam stream true=write to a stream, false=pwrite to a file
|
||||
@param p map to source file
|
||||
@param out_fd destination
|
||||
@param o start offset
|
||||
@param end last offset (exclusive)
|
||||
@return error code
|
||||
@retval 0 on success
|
||||
@retval 1 if a memory mapping failed
|
||||
*/
|
||||
template<bool stream>
|
||||
static ssize_t mmap_copy(const void *p, int out_fd, uint64_t o, uint64_t end)
|
||||
{
|
||||
size_t c= size_t(end - o);
|
||||
ssize_t ret;
|
||||
for (const char *b= static_cast<const char*>(p) + o;;
|
||||
b+= ret, o+= uint64_t(ret))
|
||||
{
|
||||
const size_t size{std::min(c, size_t(INT_MAX >> 20 << 20))};
|
||||
if (stream)
|
||||
{
|
||||
if ((ret= backup_stream_write(out_fd, b, size)))
|
||||
break;
|
||||
ret= size;
|
||||
}
|
||||
else if ((ret= pwrite(out_fd, b, size, off_t(o))) < 0)
|
||||
break;
|
||||
c-= ret;
|
||||
if (!c)
|
||||
{
|
||||
ret= 0;
|
||||
break;
|
||||
}
|
||||
if (!ret)
|
||||
{
|
||||
ret= -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -198,20 +157,7 @@ int copy_entire_file(int src, int dst) noexcept
|
||||
ret= int(copy_file_shortcut(src, dst, 0, end));
|
||||
if (ret == 1)
|
||||
# endif
|
||||
{
|
||||
# ifdef copy_file_mmap
|
||||
void *p= mmap(nullptr, size_t{end}, PROT_READ, MAP_SHARED, src, 0);
|
||||
if (p != MAP_FAILED)
|
||||
{
|
||||
ret= int(copy_file_mmap(p, dst, 0, end));
|
||||
munmap(p, size_t{end});
|
||||
}
|
||||
else
|
||||
# endif
|
||||
{
|
||||
ret= backup::copy(src, dst, 0, end);
|
||||
}
|
||||
}
|
||||
ret= backup::copy(src, dst, 0, end);
|
||||
#ifdef POSIX_FADV_DONTNEED
|
||||
std::ignore= posix_fadvise(src, 0, 0, POSIX_FADV_DONTNEED);
|
||||
#endif
|
||||
@@ -424,9 +370,15 @@ int append(handle src, backup_fd stream, uint64_t start, uint64_t end) noexcept
|
||||
that the receiving end of the pipe has consumed everything before
|
||||
our caller re-enables writes to this src region.
|
||||
|
||||
On Linux, even for MAP_PRIVATE, the following has been documented:
|
||||
For Linux mmap(2), even for MAP_PRIVATE, the following is documented:
|
||||
It is unspecified whether changes made to the file after the
|
||||
mmap() call are visible in the mapped region.
|
||||
mmap(2) call are visible in the mapped region.
|
||||
|
||||
Similarly, for Linux sendfile(2): If out_fd refers to a socket or
|
||||
pipe with zero-copy support, callers must ensure the transferred
|
||||
portions of the file referred to by in_fd remain unmodified until
|
||||
the reader on the other end of out_fd has consumed the
|
||||
transferred data.
|
||||
*/
|
||||
# ifdef __linux__
|
||||
const int pipe_size{fcntl(stream, F_GETPIPE_SZ)};
|
||||
@@ -483,7 +435,7 @@ int backup_stream_zeropad(backup_fd stream, size_t written) noexcept
|
||||
@param end last offset to copy (exclusive)
|
||||
@return error code (non-positive)
|
||||
@retval 0 on success
|
||||
@retval 1 if a fallback to copy_mmap() or backup::copy() is needed
|
||||
@retval 1 if a fallback to backup::copy() is needed
|
||||
*/
|
||||
int copy_file_range_try(int src, int dst, uint64_t start, uint64_t end)
|
||||
noexcept
|
||||
@@ -497,22 +449,6 @@ int copy_file_range_try(int src, int dst, uint64_t start, uint64_t end)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef copy_file_mmap
|
||||
/**
|
||||
Copy from a memory mapping to a file.
|
||||
@param map source file mapping
|
||||
@param dst target to append map to
|
||||
@param start first offset to copy
|
||||
@param end last offset to copy (exclusive)
|
||||
@return error code (non-positive)
|
||||
@retval 0 on success
|
||||
*/
|
||||
int copy_mmap(const void *map, int dst, uint64_t start, uint64_t end) noexcept
|
||||
{
|
||||
return int(mmap_copy<false>(map, dst, start, end));
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Append to the configuration file.
|
||||
@param target backup target directory
|
||||
@param config the configuration file snippet to append
|
||||
@@ -1698,15 +1634,6 @@ int backup_stream_append_async(int src, int stream,
|
||||
# ifdef __linux__
|
||||
return int(stepwise<send_step,true>(src, stream, off_t(start), off_t(end)));
|
||||
# else
|
||||
# if SIZEOF_SIZE_T > 4
|
||||
void *p= mmap(nullptr, size_t{end}, PROT_READ, MAP_SHARED, src, 0);
|
||||
if (p != MAP_FAILED)
|
||||
{
|
||||
ssize_t ret= mmap_copy<true>(p, stream, start, end);
|
||||
munmap(p, size_t{end});
|
||||
return int(ret);
|
||||
}
|
||||
# endif
|
||||
return int(pread_write<true>(src, stream, start, end));
|
||||
# endif
|
||||
}
|
||||
|
||||
@@ -174,24 +174,7 @@ int append(handle src, backup_fd stream, uint64_t start, uint64_t end)
|
||||
noexcept;
|
||||
}
|
||||
|
||||
#if defined _WIN32 || defined __FreeBSD__
|
||||
/* There is no special variant of backup::copy(). */
|
||||
#else
|
||||
# if SIZEOF_SIZE_T > 4
|
||||
/**
|
||||
Copy from a memory mapping to a file.
|
||||
@param map source file mapping
|
||||
@param dst target to append map to
|
||||
@param start first offset to copy
|
||||
@param end last offset to copy (exclusive)
|
||||
@return error code (non-positive)
|
||||
@retval 0 on success
|
||||
*/
|
||||
int copy_mmap(const void *map, int dst, uint64_t start, uint64_t end) noexcept;
|
||||
# define copy_file_mmap copy_mmap
|
||||
# endif
|
||||
|
||||
# ifdef __linux__
|
||||
#ifdef __linux__
|
||||
/**
|
||||
Try to copy a portion of a file via copy_file_range(2).
|
||||
@param src source file descriptor
|
||||
@@ -200,12 +183,11 @@ int copy_mmap(const void *map, int dst, uint64_t start, uint64_t end) noexcept;
|
||||
@param end last offset to copy (exclusive)
|
||||
@return error code (non-positive)
|
||||
@retval 0 on success
|
||||
@retval 1 if a fallback to copy_mmap() or backup::copy() is needed
|
||||
@retval 1 if a fallback to backup::copy() is needed
|
||||
*/
|
||||
int copy_file_range_try(int src, int dst, uint64_t start, uint64_t end)
|
||||
noexcept;
|
||||
# define copy_file_shortcut copy_file_range_try
|
||||
# endif
|
||||
# define copy_file_shortcut copy_file_range_try
|
||||
#endif
|
||||
|
||||
/** Append to the configuration file.
|
||||
|
||||
@@ -800,6 +800,37 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PMEM
|
||||
/**
|
||||
Copy a file using a memory mapping.
|
||||
@param p map to source file
|
||||
@param dst destination
|
||||
@param o start offset
|
||||
@param end last offset (exclusive)
|
||||
@return error code (non-positive)
|
||||
@retval 0 on success
|
||||
*/
|
||||
static int mmap_copy(const void *p, int dst, uint64_t o, uint64_t end)
|
||||
noexcept
|
||||
{
|
||||
size_t c= size_t(end - o);
|
||||
ssize_t ret;
|
||||
for (const char *b= static_cast<const char*>(p) + o;;
|
||||
b+= ret, o+= uint64_t(ret))
|
||||
{
|
||||
const size_t size{std::min(c, size_t(INT_MAX >> 20 << 20))};
|
||||
if ((ret= pwrite(dst, b, size, off_t(o))) < 0)
|
||||
return int(ret);
|
||||
c-= ret;
|
||||
if (!c)
|
||||
break;
|
||||
if (!ret)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Copy the log in real time.
|
||||
@return error code (never positive)
|
||||
@@ -874,7 +905,7 @@ public:
|
||||
const uint64_t begin{prev - first}, end{lsn - first};
|
||||
#ifdef HAVE_PMEM
|
||||
if (log_sys.is_mmap())
|
||||
err= copy_file_mmap(tracked.buf, ctx.log_dst, begin, end);
|
||||
err= mmap_copy(tracked.buf, ctx.log_dst, begin, end);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
@@ -2305,84 +2336,41 @@ int InnoDB_backup::backup(IF_WIN(const char *,int) target, fil_node_t *node,
|
||||
#endif
|
||||
{
|
||||
const uint32_t BACKUP_BATCH_SIZE{innodb_backup.ctx.BACKUP_BATCH_SIZE};
|
||||
#ifdef copy_file_mmap
|
||||
const size_t c{size_t{final_limit ? final_limit : limit} * page_size};
|
||||
void *p= mmap(nullptr, c, PROT_READ, MAP_SHARED, node->handle, 0);
|
||||
if (p != MAP_FAILED)
|
||||
for (uint32_t page{0};;)
|
||||
{
|
||||
for (uint32_t page{0};;)
|
||||
while (page < limit)
|
||||
{
|
||||
while (page < limit)
|
||||
start+= BACKUP_BATCH_SIZE;
|
||||
buf_page_t **end= backup_batch_start(blocks, node->space, start);
|
||||
if (end)
|
||||
{
|
||||
start+= BACKUP_BATCH_SIZE;
|
||||
buf_page_t **end= backup_batch_start(blocks, node->space, start);
|
||||
if (end)
|
||||
{
|
||||
const uint64_t o{uint64_t{page} * page_size};
|
||||
page= std::min(limit, page + BACKUP_BATCH_SIZE);
|
||||
/* TODO: avoid copying freed page ranges, or pages that were
|
||||
allocated after the backup started */
|
||||
err= copy_file_mmap(p, f, o, uint64_t{page} * page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
end= blocks;
|
||||
err= 2;
|
||||
}
|
||||
backup_batch_stop(node->space, blocks, end);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
if (final_limit != 0 && !err && page == buf_dblwr.begin())
|
||||
{
|
||||
/* Copy the rest after the doublewrite buffer. */
|
||||
ut_ad(start == page);
|
||||
limit= final_limit;
|
||||
start= page+= buf_dblwr.size();
|
||||
const uint64_t o{uint64_t{page} * page_size};
|
||||
page= std::min(limit, page + BACKUP_BATCH_SIZE);
|
||||
/* TODO: avoid copying freed page ranges, or pages that were
|
||||
allocated after the backup started */
|
||||
err=
|
||||
backup::copy(node->handle, f, o, uint64_t{page} * page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
end= blocks;
|
||||
err= 2;
|
||||
}
|
||||
backup_batch_stop(node->space, blocks, end);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
munmap(p, c);
|
||||
|
||||
if (final_limit != 0 && !err && page == buf_dblwr.begin())
|
||||
{
|
||||
/* Copy the rest after the doublewrite buffer. */
|
||||
ut_ad(start == page);
|
||||
limit= final_limit;
|
||||
start= page+= buf_dblwr.size();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
for (uint32_t page{0};;)
|
||||
{
|
||||
while (page < limit)
|
||||
{
|
||||
start+= BACKUP_BATCH_SIZE;
|
||||
buf_page_t **end= backup_batch_start(blocks, node->space, start);
|
||||
if (end)
|
||||
{
|
||||
const uint64_t o{uint64_t{page} * page_size};
|
||||
page= std::min(limit, page + BACKUP_BATCH_SIZE);
|
||||
/* TODO: avoid copying freed page ranges, or pages that were
|
||||
allocated after the backup started */
|
||||
err=
|
||||
backup::copy(node->handle, f, o, uint64_t{page} * page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
end= blocks;
|
||||
err= 2;
|
||||
}
|
||||
backup_batch_stop(node->space, blocks, end);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
if (final_limit != 0 && !err && page == buf_dblwr.begin())
|
||||
{
|
||||
/* Copy the rest after the doublewrite buffer. */
|
||||
ut_ad(start == page);
|
||||
limit= final_limit;
|
||||
start= page+= buf_dblwr.size();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IF_WIN(!CloseHandle,close)(f) | err)
|
||||
|
||||
Reference in New Issue
Block a user