mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
6272025ad4
This fix is a follow up on the fix for similar issue 56761. When sanitizing data read from the events_waits_history_long table, the code needs also to sanitize the schema_name / object_name / file_name pointers, because such pointers could also hold invalid values. Checking the string length alone was required but not sufficient. This fix verifies that: - the table schema and table name used in table io events - the file name used in file io events are valid pointers before dereferencing these pointers.
308 lines
8.5 KiB
C++
308 lines
8.5 KiB
C++
/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software Foundation,
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
|
|
|
#ifndef PFS_INSTR_H
|
|
#define PFS_INSTR_H
|
|
|
|
/**
|
|
@file storage/perfschema/pfs_instr.h
|
|
Performance schema instruments (declarations).
|
|
*/
|
|
|
|
#include "pfs_lock.h"
|
|
#include "pfs_instr_class.h"
|
|
#include "pfs_events_waits.h"
|
|
#include "pfs_server.h"
|
|
#include "lf.h"
|
|
|
|
/**
|
|
@addtogroup Performance_schema_buffers
|
|
@{
|
|
*/
|
|
|
|
struct PFS_thread;
|
|
|
|
struct PFS_instr
|
|
{
|
|
/** Internal lock. */
|
|
pfs_lock m_lock;
|
|
/** Instrument wait statistics chain. */
|
|
PFS_single_stat_chain m_wait_stat;
|
|
};
|
|
|
|
/** Instrumented mutex implementation. @see PSI_mutex. */
|
|
struct PFS_mutex : public PFS_instr
|
|
{
|
|
/** Mutex identity, typically a pthread_mutex_t. */
|
|
const void *m_identity;
|
|
/** Mutex class. */
|
|
PFS_mutex_class *m_class;
|
|
/**
|
|
Mutex lock usage statistics chain.
|
|
This statistic is not exposed in user visible tables yet.
|
|
*/
|
|
PFS_single_stat_chain m_lock_stat;
|
|
/** Current owner. */
|
|
PFS_thread *m_owner;
|
|
/**
|
|
Timestamp of the last lock.
|
|
This statistic is not exposed in user visible tables yet.
|
|
*/
|
|
ulonglong m_last_locked;
|
|
};
|
|
|
|
/** Instrumented rwlock implementation. @see PSI_rwlock. */
|
|
struct PFS_rwlock : public PFS_instr
|
|
{
|
|
/** RWLock identity, typically a pthread_rwlock_t. */
|
|
const void *m_identity;
|
|
/** RWLock class. */
|
|
PFS_rwlock_class *m_class;
|
|
/**
|
|
RWLock read lock usage statistics chain.
|
|
This statistic is not exposed in user visible tables yet.
|
|
*/
|
|
PFS_single_stat_chain m_read_lock_stat;
|
|
/**
|
|
RWLock write lock usage statistics chain.
|
|
This statistic is not exposed in user visible tables yet.
|
|
*/
|
|
PFS_single_stat_chain m_write_lock_stat;
|
|
/** Current writer thread. */
|
|
PFS_thread *m_writer;
|
|
/** Current count of readers. */
|
|
uint m_readers;
|
|
/**
|
|
Timestamp of the last write.
|
|
This statistic is not exposed in user visible tables yet.
|
|
*/
|
|
ulonglong m_last_written;
|
|
/**
|
|
Timestamp of the last read.
|
|
This statistic is not exposed in user visible tables yet.
|
|
*/
|
|
ulonglong m_last_read;
|
|
};
|
|
|
|
/** Instrumented cond implementation. @see PSI_cond. */
|
|
struct PFS_cond : public PFS_instr
|
|
{
|
|
/** Condition identity, typically a pthread_cond_t. */
|
|
const void *m_identity;
|
|
/** Condition class. */
|
|
PFS_cond_class *m_class;
|
|
/** Condition instance usage statistics. */
|
|
PFS_cond_stat m_cond_stat;
|
|
};
|
|
|
|
/** Instrumented File and FILE implementation. @see PSI_file. */
|
|
struct PFS_file : public PFS_instr
|
|
{
|
|
/** File name. */
|
|
char m_filename[FN_REFLEN];
|
|
/** File name length in bytes. */
|
|
uint m_filename_length;
|
|
/** File class. */
|
|
PFS_file_class *m_class;
|
|
/** File usage statistics. */
|
|
PFS_file_stat m_file_stat;
|
|
};
|
|
|
|
/** Instrumented table implementation. @see PSI_table. */
|
|
struct PFS_table : public PFS_instr
|
|
{
|
|
/** Table share. */
|
|
PFS_table_share *m_share;
|
|
/** Table identity, typically a handler. */
|
|
const void *m_identity;
|
|
};
|
|
|
|
/**
|
|
@def LOCKER_STACK_SIZE
|
|
Maximum number of nested waits.
|
|
*/
|
|
#define LOCKER_STACK_SIZE 3
|
|
|
|
/**
|
|
@def PFS_MAX_ALLOC_RETRY
|
|
Maximum number of times the code attempts to allocate an item
|
|
from internal buffers, before giving up.
|
|
*/
|
|
#define PFS_MAX_ALLOC_RETRY 1000
|
|
|
|
#define PFS_MAX_SCAN_PASS 2
|
|
|
|
/**
|
|
Helper to scan circular buffers.
|
|
Given a buffer of size [0, max_size - 1],
|
|
and a random starting point in the buffer,
|
|
this helper returns up to two [first, last -1] intervals that:
|
|
- fit into the [0, max_size - 1] range,
|
|
- have a maximum combined length of at most PFS_MAX_ALLOC_RETRY.
|
|
*/
|
|
struct PFS_scan
|
|
{
|
|
public:
|
|
void init(uint random, uint max_size);
|
|
|
|
bool has_pass() const
|
|
{ return (m_pass < m_pass_max); }
|
|
|
|
void next_pass()
|
|
{ m_pass++; }
|
|
|
|
uint first() const
|
|
{ return m_first[m_pass]; }
|
|
|
|
uint last() const
|
|
{ return m_last[m_pass]; }
|
|
|
|
private:
|
|
uint m_pass;
|
|
uint m_pass_max;
|
|
uint m_first[PFS_MAX_SCAN_PASS];
|
|
uint m_last[PFS_MAX_SCAN_PASS];
|
|
};
|
|
|
|
|
|
/** Instrumented thread implementation. @see PSI_thread. */
|
|
struct PFS_thread
|
|
{
|
|
/** Internal lock. */
|
|
pfs_lock m_lock;
|
|
/** Pins for filename_hash. */
|
|
LF_PINS *m_filename_hash_pins;
|
|
/** Pins for table_share_hash. */
|
|
LF_PINS *m_table_share_hash_pins;
|
|
/** Event ID counter */
|
|
ulonglong m_event_id;
|
|
/** Thread instrumentation flag. */
|
|
bool m_enabled;
|
|
/** Internal thread identifier, unique. */
|
|
ulong m_thread_internal_id;
|
|
/** External (SHOW PROCESSLIST) thread identifier, not unique. */
|
|
ulong m_thread_id;
|
|
/** Thread class. */
|
|
PFS_thread_class *m_class;
|
|
/** Size of @c m_wait_locker_stack. */
|
|
uint m_wait_locker_count;
|
|
/**
|
|
Stack of wait lockers.
|
|
This member holds the data for the table
|
|
PERFORMANCE_SCHEMA.EVENTS_WAITS_CURRENT.
|
|
For most locks, only 1 wait locker is used at a given time.
|
|
For composite locks, several records are needed:
|
|
- 1 for a 'logical' wait (for example on the GLOBAL READ LOCK state)
|
|
- 1 for a 'physical' wait (for example on COND_refresh)
|
|
*/
|
|
PFS_wait_locker m_wait_locker_stack[LOCKER_STACK_SIZE];
|
|
/** True if the circular buffer @c m_waits_history is full. */
|
|
bool m_waits_history_full;
|
|
/** Current index in the circular buffer @c m_waits_history. */
|
|
uint m_waits_history_index;
|
|
/**
|
|
Waits history circular buffer.
|
|
This member holds the data for the table
|
|
PERFORMANCE_SCHEMA.EVENTS_WAITS_HISTORY.
|
|
*/
|
|
PFS_events_waits *m_waits_history;
|
|
/**
|
|
Per thread waits aggregated statistics.
|
|
This member holds the data for the table
|
|
PERFORMANCE_SCHEMA.EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME.
|
|
*/
|
|
PFS_single_stat_chain *m_instr_class_wait_stats;
|
|
};
|
|
|
|
PFS_thread *sanitize_thread(PFS_thread *unsafe);
|
|
const char *sanitize_file_name(const char *unsafe);
|
|
|
|
PFS_single_stat_chain*
|
|
find_per_thread_mutex_class_wait_stat(PFS_thread *thread,
|
|
PFS_mutex_class *klass);
|
|
|
|
PFS_single_stat_chain*
|
|
find_per_thread_rwlock_class_wait_stat(PFS_thread *thread,
|
|
PFS_rwlock_class *klass);
|
|
|
|
PFS_single_stat_chain*
|
|
find_per_thread_cond_class_wait_stat(PFS_thread *thread,
|
|
PFS_cond_class *klass);
|
|
|
|
PFS_single_stat_chain*
|
|
find_per_thread_file_class_wait_stat(PFS_thread *thread,
|
|
PFS_file_class *klass);
|
|
|
|
int init_instruments(const PFS_global_param *param);
|
|
void cleanup_instruments();
|
|
int init_file_hash();
|
|
void cleanup_file_hash();
|
|
PFS_mutex* create_mutex(PFS_mutex_class *mutex_class, const void *identity);
|
|
void destroy_mutex(PFS_mutex *pfs);
|
|
PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity);
|
|
void destroy_rwlock(PFS_rwlock *pfs);
|
|
PFS_cond* create_cond(PFS_cond_class *klass, const void *identity);
|
|
void destroy_cond(PFS_cond *pfs);
|
|
|
|
PFS_thread* create_thread(PFS_thread_class *klass, const void *identity,
|
|
ulong thread_id);
|
|
|
|
void destroy_thread(PFS_thread *pfs);
|
|
|
|
PFS_file* find_or_create_file(PFS_thread *thread, PFS_file_class *klass,
|
|
const char *filename, uint len);
|
|
|
|
void release_file(PFS_file *pfs);
|
|
void destroy_file(PFS_thread *thread, PFS_file *pfs);
|
|
PFS_table* create_table(PFS_table_share *share, const void *identity);
|
|
void destroy_table(PFS_table *pfs);
|
|
|
|
/* For iterators and show status. */
|
|
|
|
extern ulong mutex_max;
|
|
extern ulong mutex_lost;
|
|
extern ulong rwlock_max;
|
|
extern ulong rwlock_lost;
|
|
extern ulong cond_max;
|
|
extern ulong cond_lost;
|
|
extern ulong thread_max;
|
|
extern ulong thread_lost;
|
|
extern ulong file_max;
|
|
extern ulong file_lost;
|
|
extern long file_handle_max;
|
|
extern ulong file_handle_lost;
|
|
extern ulong table_max;
|
|
extern ulong table_lost;
|
|
extern ulong events_waits_history_per_thread;
|
|
extern ulong instr_class_per_thread;
|
|
extern ulong locker_lost;
|
|
|
|
/* Exposing the data directly, for iterators. */
|
|
|
|
extern PFS_mutex *mutex_array;
|
|
extern PFS_rwlock *rwlock_array;
|
|
extern PFS_cond *cond_array;
|
|
extern PFS_thread *thread_array;
|
|
extern PFS_file *file_array;
|
|
extern PFS_file **file_handle_array;
|
|
extern PFS_table *table_array;
|
|
|
|
void reset_events_waits_by_instance();
|
|
void reset_per_thread_wait_stat();
|
|
void reset_file_instance_io();
|
|
|
|
/** @} */
|
|
#endif
|
|
|