# 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
@@ -141,6 +141,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
@@ -1494,6 +1496,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.
@@ -3175,7 +3188,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, "'");
@@ -3225,7 +3243,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
@@ -194,6 +194,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
@@ -487,6 +492,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.
@@ -4252,6 +4262,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
@@ -4510,6 +4611,10 @@
test_lc_time_sz();
#endif
+#if defined(__linux__)
+ init_cachedev();
+#endif//__linux__
+
/*
We have enough space for fiddling with the argv, continue
*/
@@ -4713,6 +4818,10 @@
}
#endif
clean_up(1);
+#if defined(__linux__)
+ cleanup_cachedev();
+#endif//__linux__
+
mysqld_exit(0);
}
@@ -6557,6 +6666,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
@@ -384,6 +384,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
@@ -2298,6 +2298,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
@@ -7353,6 +7354,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;