Commit 120b73a0 authored by Monty's avatar Monty

Speed up writing to encrypted binlogs

MDEV-21604

Added "virtual" low level write function encrypt_or_write that is set
to point to either normal or encrypted write functions.

This patch also fixes a possible memory leak if writing to binary log fails.
parent 91ab42a8
...@@ -5444,7 +5444,10 @@ bool MYSQL_BIN_LOG::write_event(Log_event *ev, binlog_cache_data *cache_data, ...@@ -5444,7 +5444,10 @@ bool MYSQL_BIN_LOG::write_event(Log_event *ev, binlog_cache_data *cache_data,
{ {
Log_event_writer writer(file, 0, &crypto); Log_event_writer writer(file, 0, &crypto);
if (crypto.scheme && file == &log_file) if (crypto.scheme && file == &log_file)
{
writer.ctx= alloca(crypto.ctx_size); writer.ctx= alloca(crypto.ctx_size);
writer.set_encrypted_writer();
}
if (cache_data) if (cache_data)
cache_data->add_status(ev->logged_status()); cache_data->add_status(ev->logged_status());
return writer.write(ev); return writer.write(ev);
...@@ -7242,8 +7245,10 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache) ...@@ -7242,8 +7245,10 @@ int MYSQL_BIN_LOG::write_cache(THD *thd, IO_CACHE *cache)
CacheWriter writer(thd, &log_file, binlog_checksum_options, &crypto); CacheWriter writer(thd, &log_file, binlog_checksum_options, &crypto);
if (crypto.scheme) if (crypto.scheme)
{
writer.ctx= alloca(crypto.ctx_size); writer.ctx= alloca(crypto.ctx_size);
writer.set_encrypted_writer();
}
// while there is just one alg the following must hold: // while there is just one alg the following must hold:
DBUG_ASSERT(binlog_checksum_options == BINLOG_CHECKSUM_ALG_OFF || DBUG_ASSERT(binlog_checksum_options == BINLOG_CHECKSUM_ALG_OFF ||
binlog_checksum_options == BINLOG_CHECKSUM_ALG_CRC32); binlog_checksum_options == BINLOG_CHECKSUM_ALG_CRC32);
......
...@@ -932,6 +932,8 @@ typedef struct st_print_event_info ...@@ -932,6 +932,8 @@ typedef struct st_print_event_info
class Log_event_writer class Log_event_writer
{ {
/* Log_event_writer is updated when ctx is set */
int (Log_event_writer::*encrypt_or_write)(const uchar *pos, size_t len);
public: public:
ulonglong bytes_written; ulonglong bytes_written;
void *ctx; ///< Encryption context or 0 if no encryption is needed void *ctx; ///< Encryption context or 0 if no encryption is needed
...@@ -943,10 +945,13 @@ class Log_event_writer ...@@ -943,10 +945,13 @@ class Log_event_writer
my_off_t pos() { return my_b_safe_tell(file); } my_off_t pos() { return my_b_safe_tell(file); }
void add_status(enum_logged_status status); void add_status(enum_logged_status status);
void set_incident(); void set_incident();
void set_encrypted_writer()
{ encrypt_or_write= &Log_event_writer::encrypt_and_write; }
Log_event_writer(IO_CACHE *file_arg, binlog_cache_data *cache_data_arg, Log_event_writer(IO_CACHE *file_arg, binlog_cache_data *cache_data_arg,
Binlog_crypt_data *cr= 0) Binlog_crypt_data *cr= 0)
: bytes_written(0), ctx(0), :encrypt_or_write(&Log_event_writer::write_internal),
bytes_written(0), ctx(0),
file(file_arg), cache_data(cache_data_arg), crypto(cr) { } file(file_arg), cache_data(cache_data_arg), crypto(cr) { }
private: private:
......
...@@ -798,6 +798,7 @@ my_bool Log_event::need_checksum() ...@@ -798,6 +798,7 @@ my_bool Log_event::need_checksum()
int Log_event_writer::write_internal(const uchar *pos, size_t len) int Log_event_writer::write_internal(const uchar *pos, size_t len)
{ {
DBUG_ASSERT(!ctx || encrypt_or_write == &Log_event_writer::encrypt_and_write);
if (my_b_safe_write(file, pos, len)) if (my_b_safe_write(file, pos, len))
{ {
DBUG_PRINT("error", ("write to log failed: %d", my_errno)); DBUG_PRINT("error", ("write to log failed: %d", my_errno));
...@@ -826,35 +827,37 @@ int Log_event_writer::maybe_write_event_len(uchar *pos, size_t len) ...@@ -826,35 +827,37 @@ int Log_event_writer::maybe_write_event_len(uchar *pos, size_t len)
int Log_event_writer::encrypt_and_write(const uchar *pos, size_t len) int Log_event_writer::encrypt_and_write(const uchar *pos, size_t len)
{ {
uchar *dst= 0; uchar *dst;
size_t dstsize= 0; size_t dstsize;
uint dstlen;
int res; // Safe as res is always set
DBUG_ASSERT(ctx);
if (ctx) if (!len)
{ return 0;
dstsize= encryption_encrypted_length((uint)len, ENCRYPTION_KEY_SYSTEM_DATA,
crypto->key_version);
if (!(dst= (uchar*)my_safe_alloca(dstsize)))
return 1;
uint dstlen; dstsize= encryption_encrypted_length((uint)len, ENCRYPTION_KEY_SYSTEM_DATA,
if (len == 0) crypto->key_version);
dstlen= 0; if (!(dst= (uchar*)my_safe_alloca(dstsize)))
else if (encryption_ctx_update(ctx, pos, (uint)len, dst, &dstlen)) return 1;
goto err;
if (maybe_write_event_len(dst, dstlen)) if (encryption_ctx_update(ctx, pos, (uint)len, dst, &dstlen))
return 1; {
pos= dst; res= 1;
len= dstlen; goto err;
} }
if (write_internal(pos, len))
if (maybe_write_event_len(dst, dstlen))
{
res= 1;
goto err; goto err;
}
res= write_internal(dst, dstlen);
my_safe_afree(dst, dstsize);
return 0;
err: err:
my_safe_afree(dst, dstsize); my_safe_afree(dst, dstsize);
return 1; return res;
} }
int Log_event_writer::write_header(uchar *pos, size_t len) int Log_event_writer::write_header(uchar *pos, size_t len)
...@@ -890,7 +893,7 @@ int Log_event_writer::write_header(uchar *pos, size_t len) ...@@ -890,7 +893,7 @@ int Log_event_writer::write_header(uchar *pos, size_t len)
pos+= 4; pos+= 4;
len-= 4; len-= 4;
} }
DBUG_RETURN(encrypt_and_write(pos, len)); DBUG_RETURN((this->*encrypt_or_write)(pos, len));
} }
int Log_event_writer::write_data(const uchar *pos, size_t len) int Log_event_writer::write_data(const uchar *pos, size_t len)
...@@ -899,7 +902,7 @@ int Log_event_writer::write_data(const uchar *pos, size_t len) ...@@ -899,7 +902,7 @@ int Log_event_writer::write_data(const uchar *pos, size_t len)
if (checksum_len) if (checksum_len)
crc= my_checksum(crc, pos, len); crc= my_checksum(crc, pos, len);
DBUG_RETURN(encrypt_and_write(pos, len)); DBUG_RETURN((this->*encrypt_or_write)(pos, len));
} }
int Log_event_writer::write_footer() int Log_event_writer::write_footer()
...@@ -909,7 +912,7 @@ int Log_event_writer::write_footer() ...@@ -909,7 +912,7 @@ int Log_event_writer::write_footer()
{ {
uchar checksum_buf[BINLOG_CHECKSUM_LEN]; uchar checksum_buf[BINLOG_CHECKSUM_LEN];
int4store(checksum_buf, crc); int4store(checksum_buf, crc);
if (encrypt_and_write(checksum_buf, BINLOG_CHECKSUM_LEN)) if ((this->*encrypt_or_write)(checksum_buf, BINLOG_CHECKSUM_LEN))
DBUG_RETURN(ER_ERROR_ON_WRITE); DBUG_RETURN(ER_ERROR_ON_WRITE);
} }
if (ctx) if (ctx)
......
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