A fix for Bug#7209 "Client error with "Access Denied" on updates

when high concurrency": remove HASH::current_record and make it
an external search parameter, so that it can not be the cause of a 
race condition under high concurrent load.
The bug was in a race condition in table_hash_search,
when column_priv_hash.current_record was overwritten simultaneously
by multiple threads, causing the search for a suitable grant record
to fail.
No test case as the bug is repeatable only under concurrent load.


include/hash.h:
  - remove current_record from HASH, instead modify hash_first,
  hash_next to accept HASH_SEARCH_STATE as an IN/OUT parameter
mysys/hash.c:
  - remove HASH::current_record
  - change declarations of functions that use HASH in read-only mode
    to accept const HASH * instead of HASH *. 
  - implement hash_search; move the old implementation of hash_search
  to hash_first
mysys/testhash.c:
  - adjust the test case to changed function declarations
sql/lock.cc:
  - adjust to changed declarations of hash_search, hash_next
sql/sql_acl.cc:
  - adjust to changed declarations of hash_search, hash_next
sql/sql_base.cc:
  - adjust to changed declarations of hash_search, hash_nex
sql/sql_cache.cc:
  - adjust to a changed declaration of hash_replace
This commit is contained in:
unknown 2006-01-04 17:35:30 +03:00
commit f577d864cd
7 changed files with 79 additions and 50 deletions

View file

@ -641,6 +641,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
char key[MAX_DBKEY_LENGTH];
char *db= table_list->db;
uint key_length;
HASH_SEARCH_STATE state;
DBUG_ENTER("lock_table_name");
DBUG_PRINT("enter",("db: %s name: %s", db, table_list->real_name));
@ -651,9 +652,9 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
/* Only insert the table if we haven't insert it already */
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
for (table=(TABLE*) hash_first(&open_cache, (byte*)key, key_length, &state);
table ;
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
table = (TABLE*) hash_next(&open_cache, (byte*)key, key_length, &state))
if (table->in_use == thd)
DBUG_RETURN(0);