# name : sql_no_fcache.patch # introduced : 12 # maintainer : Oleg # #!!! notice !!! # Any small change to this file in the main branch # should be done or reviewed by the maintainer! --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -143,6 +143,8 @@ static uint opt_protocol= 0; static char *opt_plugin_dir= 0, *opt_default_auth= 0; +static my_bool server_supports_sql_no_fcache= FALSE; + /* Dynamic_string wrapper functions. In this file use these wrappers, they will terminate the process if there is @@ -1496,6 +1498,17 @@ /* Don't switch charsets for 4.1 and earlier. (bug#34192). */ server_supports_switching_charsets= FALSE; } + + /* Check to see if we support SQL_NO_FCACHE on this server. */ + if (mysql_query(mysql, "SELECT SQL_NO_FCACHE NOW()") == 0) + { + MYSQL_RES *res = mysql_store_result(mysql); + if (res) + { + mysql_free_result(res); + } + server_supports_sql_no_fcache= TRUE; + } /* As we're going to set SQL_MODE, it would be lost on reconnect, so we cannot reconnect. @@ -3177,7 +3190,12 @@ /* now build the query string */ - dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '"); + dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ "); + if (server_supports_sql_no_fcache) + { + dynstr_append_checked(&query_string, "/*!50084 SQL_NO_FCACHE */ "); + } + dynstr_append_checked(&query_string, "* INTO OUTFILE '"); dynstr_append_checked(&query_string, filename); dynstr_append_checked(&query_string, "'"); @@ -3227,7 +3245,12 @@ check_io(md_result_file); } - dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM "); + dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ "); + if (server_supports_sql_no_fcache) + { + dynstr_append_checked(&query_string, "/*!50084 SQL_NO_FCACHE */ "); + } + dynstr_append_checked(&query_string, "* FROM "); dynstr_append_checked(&query_string, result_table); if (where) --- /dev/null +++ b/include/flashcache_ioctl.h @@ -0,0 +1,53 @@ +/**************************************************************************** + * flashcache_ioctl.h + * FlashCache: Device mapper target for block-level disk caching + * + * Copyright 2010 Facebook, Inc. + * Author: Mohan Srinivasan (mohan@facebook.com) + * + * Based on DM-Cache: + * Copyright (C) International Business Machines Corp., 2006 + * Author: Ming Zhao (mingzhao@ufl.edu) + * + * 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; under 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, see . + ****************************************************************************/ + +#ifndef FLASHCACHE_IOCTL_H +#define FLASHCACHE_IOCTL_H + +#include + +#define FLASHCACHE_IOCTL 0xfe + +enum { + FLASHCACHEADDNCPID_CMD=200, + FLASHCACHEDELNCPID_CMD, + FLASHCACHEDELNCALL_CMD, + FLASHCACHEADDWHITELIST_CMD, + FLASHCACHEDELWHITELIST_CMD, + FLASHCACHEDELWHITELISTALL_CMD, +}; + +#define FLASHCACHEADDNCPID _IOW(FLASHCACHE_IOCTL, FLASHCACHEADDNCPID_CMD, pid_t) +#define FLASHCACHEDELNCPID _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELNCPID_CMD, pid_t) +#define FLASHCACHEDELNCALL _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELNCALL_CMD, pid_t) + +#define FLASHCACHEADDBLACKLIST FLASHCACHEADDNCPID +#define FLASHCACHEDELBLACKLIST FLASHCACHEDELNCPID +#define FLASHCACHEDELALLBLACKLIST FLASHCACHEDELNCALL + +#define FLASHCACHEADDWHITELIST _IOW(FLASHCACHE_IOCTL, FLASHCACHEADDWHITELIST_CMD, pid_t) +#define FLASHCACHEDELWHITELIST _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELWHITELIST_CMD, pid_t) +#define FLASHCACHEDELALLWHITELIST _IOW(FLASHCACHE_IOCTL, FLASHCACHEDELWHITELISTALL_CMD, pid_t) + +#endif --- /dev/null +++ b/patch_info/sql_no_fcache.info @@ -0,0 +1,6 @@ +File=sql_no_fcache.patch +Name=Support for flashcache including the SQL_NO_FCACHE option that prevents blocks from being cached during a query. +Version=1.0 +Author=Facebook +License=GPL +Comment= --- a/sql/lex.h +++ b/sql/lex.h @@ -516,6 +516,7 @@ { "SQL_CACHE", SYM(SQL_CACHE_SYM)}, { "SQL_CALC_FOUND_ROWS", SYM(SQL_CALC_FOUND_ROWS)}, { "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM)}, + { "SQL_NO_FCACHE", SYM(SQL_NO_FCACHE_SYM)}, { "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT)}, { "SQL_THREAD", SYM(SQL_THREAD)}, { "SQL_TSI_SECOND", SYM(SECOND_SYM)}, --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -195,6 +195,8 @@ extern char language[FN_REFLEN]; extern "C" MYSQL_PLUGIN_IMPORT ulong server_id; extern ulong concurrency; +/* flashcache */ +extern int cachedev_fd; extern time_t server_start_time, flush_status_time; extern char *opt_mysql_tmpdir, mysql_charsets_dir[]; extern int mysql_unpacked_real_data_home_len; --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -86,6 +86,11 @@ #ifdef HAVE_SYS_PRCTL_H #include #endif +#if defined(__linux__) +#include +#include +#include "flashcache_ioctl.h" +#endif//__linux__ #include #include @@ -491,6 +496,11 @@ ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0; ulong max_connections, max_connect_errors; + +/* flashcache */ +int cachedev_fd; +my_bool cachedev_enabled= FALSE; + /* Maximum length of parameter value which can be set through mysql_send_long_data() call. @@ -4102,6 +4112,97 @@ #define decrement_handler_count() #endif /* defined(_WIN32) || defined(HAVE_SMEM) */ +#if defined(__linux__) +/* + * Auto detect if we support flash cache on the host system. + * This needs to be called before we setuid away from root + * to avoid permission problems on opening the device node. + */ +static void init_cachedev(void) +{ + struct statfs stfs_data_home_dir; + struct statfs stfs; + struct mntent *ent; + pid_t pid = getpid(); + FILE *mounts; + const char *error_message= NULL; + + // disabled by default + cachedev_fd = -1; + cachedev_enabled= FALSE; + + if (!mysql_data_home) + { + error_message= "mysql_data_home not set"; + goto epilogue; + } + + if (statfs(mysql_data_home, &stfs_data_home_dir) < 0) + { + error_message= "statfs failed"; + goto epilogue; + } + + mounts = setmntent("/etc/mtab", "r"); + if (mounts == NULL) + { + error_message= "setmntent failed"; + goto epilogue; + } + + while ((ent = getmntent(mounts)) != NULL) + { + if (statfs(ent->mnt_dir, &stfs) < 0) + continue; + if (memcmp(&stfs.f_fsid, &stfs_data_home_dir.f_fsid, sizeof(fsid_t)) == 0) + break; + } + endmntent(mounts); + + if (ent == NULL) + { + error_message= "getmntent loop failed"; + goto epilogue; + } + + cachedev_fd = open(ent->mnt_fsname, O_RDONLY); + if (cachedev_fd < 0) + { + error_message= "open flash device failed"; + goto epilogue; + } + + /* cleanup previous whitelistings */ + if (ioctl(cachedev_fd, FLASHCACHEDELALLWHITELIST, &pid) < 0) + { + close(cachedev_fd); + cachedev_fd = -1; + error_message= "ioctl failed"; + } else { + ioctl(cachedev_fd, FLASHCACHEADDWHITELIST, &pid); + } + +epilogue: + sql_print_information("Flashcache bypass: %s", + (cachedev_fd > 0) ? "enabled" : "disabled"); + if (error_message) + sql_print_information("Flashcache setup error is : %s\n", error_message); + else + cachedev_enabled= TRUE; + +} + +static void cleanup_cachedev(void) +{ + pid_t pid = getpid(); + + if (cachedev_enabled) { + ioctl(cachedev_fd, FLASHCACHEDELWHITELIST, &pid); + close(cachedev_fd); + cachedev_fd = -1; + } +} +#endif//__linux__ #ifndef EMBEDDED_LIBRARY #ifndef DBUG_OFF @@ -4363,6 +4464,10 @@ test_lc_time_sz(); #endif +#if defined(__linux__) + init_cachedev(); +#endif//__linux__ + /* We have enough space for fiddling with the argv, continue */ @@ -4574,6 +4679,10 @@ } #endif clean_up(1); +#if defined(__linux__) + cleanup_cachedev(); +#endif//__linux__ + mysqld_exit(0); } @@ -6421,6 +6530,7 @@ {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG}, {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH}, {"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG}, + {"Flashcache_enabled", (char*) &cachedev_enabled, SHOW_BOOL }, {"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH}, {"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS}, {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS}, --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -390,6 +390,7 @@ lex->describe= 0; lex->subqueries= FALSE; lex->context_analysis_only= 0; + lex->disable_flashcache= FALSE; lex->derived_tables= 0; lex->safe_to_cache_query= 1; lex->leaf_tables_insert= 0; --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2346,6 +2346,7 @@ enum enum_yes_no_unknown tx_chain, tx_release; bool safe_to_cache_query; + bool disable_flashcache; bool subqueries, ignore; st_parsing_options parsing_options; Alter_info alter_info; --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -55,6 +55,12 @@ #define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1)) +#include +#include +#if defined(__linux__) +#include "flashcache_ioctl.h" +#endif//__linux__ + const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref", "MAYBE_REF","ALL","range","index","fulltext", "ref_or_null","unique_subquery","index_subquery", @@ -266,8 +272,17 @@ ulong setup_tables_done_option) { bool res; + pid_t pid; register SELECT_LEX *select_lex = &lex->select_lex; DBUG_ENTER("handle_select"); +#if defined(__linux__) + if(lex->disable_flashcache && cachedev_fd > 0) + { + pid = syscall(SYS_gettid); + ioctl(cachedev_fd, FLASHCACHEADDNCPID, &pid); + } +#endif//__linux__ + MYSQL_SELECT_START(thd->query()); if (select_lex->master_unit()->is_union() || @@ -302,6 +317,12 @@ if (unlikely(res)) result->abort_result_set(); +#if defined(__linux__) + if (lex->disable_flashcache && cachedev_fd > 0) + { + ioctl(cachedev_fd, FLASHCACHEDELNCPID, &pid); + } +#endif//__linux__ MYSQL_SELECT_DONE((int) res, (ulong) thd->limit_found_rows); DBUG_RETURN(res); } --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1284,6 +1284,7 @@ %token SQL_CACHE_SYM %token SQL_CALC_FOUND_ROWS %token SQL_NO_CACHE_SYM +%token SQL_NO_FCACHE_SYM %token SQL_SMALL_RESULT %token SQL_SYM /* SQL-2003-R */ %token SQL_THREAD @@ -7362,6 +7363,10 @@ Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; } } + | SQL_NO_FCACHE_SYM + { + Lex->disable_flashcache= TRUE; + } | SQL_CACHE_SYM { /* --- /dev/null +++ b/mysql-test/r/percona_sql_no_fcache.result @@ -0,0 +1,12 @@ +drop table if exists t1; +create table t (a int not null); +insert into t values (1),(2),(3); +SELECT SQL_NO_FCACHE SLEEP(0); +SLEEP(0) +0 +SELECT /*!40001 SQL_NO_CACHE */ /*!50084 SQL_NO_FCACHE */ * FROM t; +a +1 +2 +3 +DROP TABLE t; --- /dev/null +++ b/mysql-test/t/percona_sql_no_fcache.test @@ -0,0 +1,11 @@ +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t (a int not null); +insert into t values (1),(2),(3); + +SELECT SQL_NO_FCACHE SLEEP(0); +SELECT /*!40001 SQL_NO_CACHE */ /*!50084 SQL_NO_FCACHE */ * FROM t; + +DROP TABLE t;