mariadb/storage/innobase/include/btr0scrub.h
Marko Mäkelä 38ca9be4de MDEV-13684 InnoDB race condition between fil_crypt_thread and btr_scrub_init
There is a race condition in InnoDB startup. A number of
fil_crypt_thread are created by fil_crypt_threads_init(). These threads
may call btr_scrub_complete_space() before btr_scrub_init() was called.
Those too early calls would be accessing an uninitialized scrub_stat_mutex.

innobase_start_or_create_for_mysql(): Invoke btr_scrub_init() before
fil_crypt_threads_init().

fil_crypt_complete_rotate_space(): Only invoke btr_scrub_complete_space()
if scrubbing is enabled. There is no need to update the statistics if
it is not enabled.
2017-08-31 11:08:43 +03:00

163 lines
4.6 KiB
C

// Copyright 2014 Google
#ifndef btr0scrub_h
#define btr0scrub_h
#include "univ.i"
#include "dict0dict.h"
#include "data0data.h"
#include "page0cur.h"
#include "mtr0mtr.h"
#include "btr0types.h"
/**
* enum describing page allocation status
*/
enum btr_scrub_page_allocation_status_t {
BTR_SCRUB_PAGE_FREE,
BTR_SCRUB_PAGE_ALLOCATED,
BTR_SCRUB_PAGE_ALLOCATION_UNKNOWN
};
/**
* constants returned by btr_page_needs_scrubbing & btr_scrub_recheck_page
*/
#define BTR_SCRUB_PAGE 1 /* page should be scrubbed */
#define BTR_SCRUB_SKIP_PAGE 2 /* no scrub & no action */
#define BTR_SCRUB_SKIP_PAGE_AND_CLOSE_TABLE 3 /* no scrub & close table */
#define BTR_SCRUB_SKIP_PAGE_AND_COMPLETE_SPACE 4 /* no scrub & complete space */
#define BTR_SCRUB_TURNED_OFF 5 /* we detected that scrubbing
was disabled by global
variable */
/**************************************************************//**
struct for keeping scrub statistics. */
struct btr_scrub_stat_t {
/* page reorganizations */
ulint page_reorganizations;
/* page splits */
ulint page_splits;
/* scrub failures */
ulint page_split_failures_underflow;
ulint page_split_failures_out_of_filespace;
ulint page_split_failures_missing_index;
ulint page_split_failures_unknown;
};
/**************************************************************//**
struct for thread local scrub state. */
struct btr_scrub_t {
/* current space */
ulint space;
/* is scrubbing enabled for this space */
bool scrubbing;
/* is current space compressed */
bool compressed;
dict_table_t* current_table;
dict_index_t* current_index;
/* savepoint for X_LATCH of block */
ulint savepoint;
/* statistic counters */
btr_scrub_stat_t scrub_stat;
};
/*********************************************************************
Init scrub global variables */
UNIV_INTERN
void
btr_scrub_init();
/*********************************************************************
Cleanup scrub globals */
UNIV_INTERN
void
btr_scrub_cleanup();
/***********************************************************************
Return crypt statistics */
UNIV_INTERN
void
btr_scrub_total_stat(
/*==================*/
btr_scrub_stat_t *stat); /*!< out: stats to update */
/**************************************************************//**
Check if a page needs scrubbing
* @return BTR_SCRUB_PAGE if page should be scrubbed
* else btr_scrub_skip_page should be called
* with this return value (and without any latches held)
*/
UNIV_INTERN
int
btr_page_needs_scrubbing(
/*=====================*/
btr_scrub_t* scrub_data, /*!< in: scrub data */
buf_block_t* block, /*!< in: block to check, latched */
btr_scrub_page_allocation_status_t allocated); /*!< in: is block
allocated, free or
unknown */
/****************************************************************
Recheck if a page needs scrubbing, and if it does load appropriate
table and index
* @return BTR_SCRUB_PAGE if page should be scrubbed
* else btr_scrub_skip_page should be called
* with this return value (and without any latches held)
*/
UNIV_INTERN
int
btr_scrub_recheck_page(
/*====================*/
btr_scrub_t* scrub_data, /*!< inut: scrub data */
buf_block_t* block, /*!< in: block */
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
allocated or free */
mtr_t* mtr); /*!< in: mtr */
/****************************************************************
Perform actual scrubbing of page */
UNIV_INTERN
int
btr_scrub_page(
/*============*/
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
buf_block_t* block, /*!< in: block */
btr_scrub_page_allocation_status_t allocated, /*!< in: is block
allocated or free */
mtr_t* mtr); /*!< in: mtr */
/****************************************************************
Perform cleanup needed for a page not needing scrubbing */
UNIV_INTERN
void
btr_scrub_skip_page(
/*============*/
btr_scrub_t* scrub_data, /*!< in/out: scrub data */
int needs_scrubbing); /*!< in: return value from
btr_page_needs_scrubbing or
btr_scrub_recheck_page which encodes what kind
of cleanup is needed */
/****************************************************************
Start iterating a space
* @return true if scrubbing is turned on */
UNIV_INTERN
bool
btr_scrub_start_space(
/*===================*/
ulint space, /*!< in: space */
btr_scrub_t* scrub_data); /*!< in/out: scrub data */
/** Complete iterating a space.
@param[in,out] scrub_data scrub data */
UNIV_INTERN
void
btr_scrub_complete_space(btr_scrub_t* scrub_data);
#endif