1 /*
2    Copyright (c) 2000, 2011, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software Foundation,
15    51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
16 
17 
18 /**
19   @file
20 
21   Locking functions for mysql.
22 
23   Because of the new concurrent inserts, we must first get external locks
24   before getting internal locks.  If we do it in the other order, the status
25   information is not up to date when called from the lock handler.
26 
27   GENERAL DESCRIPTION OF LOCKING
28 
29   When not using LOCK TABLES:
30 
31   - For each SQL statement mysql_lock_tables() is called for all involved
32     tables.
33     - mysql_lock_tables() will call
34       table_handler->external_lock(thd,locktype) for each table.
35       This is followed by a call to thr_multi_lock() for all tables.
36 
37   - When statement is done, we call mysql_unlock_tables().
38     table_handler->external_lock(thd, F_UNLCK) followed by
39     thr_multi_unlock() for each table.
40 
41   - Note that mysql_unlock_tables() may be called several times as
42     MySQL in some cases can free some tables earlier than others.
43 
44   - The above is true both for normal and temporary tables.
45 
46   - Temporary non transactional tables are never passed to thr_multi_lock()
47     and we never call external_lock(thd, F_UNLOCK) on these.
48 
49   When using LOCK TABLES:
50 
51   - LOCK TABLE will call mysql_lock_tables() for all tables.
52     mysql_lock_tables() will call
53     table_handler->external_lock(thd,locktype) for each table.
54     This is followed by a call to thr_multi_lock() for all tables.
55 
56   - For each statement, we will call table_handler->start_stmt(THD)
57     to inform the table handler that we are using the table.
58 
59     The tables used can only be tables used in LOCK TABLES or a
60     temporary table.
61 
62   - When statement is done, we will call ha_commit_stmt(thd);
63 
64   - When calling UNLOCK TABLES we call mysql_unlock_tables() for all
65     tables used in LOCK TABLES
66 
67   If table_handler->external_lock(thd, locktype) fails, we call
68   table_handler->external_lock(thd, F_UNLCK) for each table that was locked,
69   excluding one that caused failure. That means handler must cleanup itself
70   in case external_lock() fails.
71 */
72 
73 #include "mariadb.h"
74 #include "sql_priv.h"
75 #include "debug_sync.h"
76 #include "lock.h"
77 #include "sql_base.h"                       // close_tables_for_reopen
78 #include "sql_parse.h"                     // is_log_table_write_query
79 #include "sql_acl.h"                       // SUPER_ACL
80 #include <hash.h>
81 #include "wsrep_mysqld.h"
82 
83 /**
84   @defgroup Locking Locking
85   @{
86 */
87 
88 extern HASH open_cache;
89 
90 static int lock_external(THD *thd, TABLE **table,uint count);
91 static int unlock_external(THD *thd, TABLE **table,uint count);
92 
93 
94 /* Map the return value of thr_lock to an error from errmsg.txt */
95 static int thr_lock_errno_to_mysql[]=
96 { 0, ER_LOCK_ABORTED, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
97 
98 /**
99   Perform semantic checks for mysql_lock_tables.
100   @param thd The current thread
101   @param tables The tables to lock
102   @param count The number of tables to lock
103   @param flags Lock flags
104   @return 0 if all the check passed, non zero if a check failed.
105 */
106 
107 static int
lock_tables_check(THD * thd,TABLE ** tables,uint count,uint flags)108 lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags)
109 {
110   uint system_count, i;
111   bool is_superuser, log_table_write_query;
112 
113   DBUG_ENTER("lock_tables_check");
114 
115   system_count= 0;
116   is_superuser= thd->security_ctx->master_access & SUPER_ACL;
117   log_table_write_query= (is_log_table_write_query(thd->lex->sql_command)
118                          || ((flags & MYSQL_LOCK_LOG_TABLE) != 0));
119 
120   for (i=0 ; i<count; i++)
121   {
122     TABLE *t= tables[i];
123 
124     /* Protect against 'fake' partially initialized TABLE_SHARE */
125     DBUG_ASSERT(t->s->table_category != TABLE_UNKNOWN_CATEGORY);
126 
127     /*
128       Table I/O to performance schema tables is performed
129       only internally by the server implementation.
130       When a user is requesting a lock, the following
131       constraints are enforced:
132     */
133     if (t->s->require_write_privileges() &&
134         ! log_table_write_query)
135     {
136       /*
137         A user should not be able to prevent writes,
138         or hold any type of lock in a session,
139         since this would be a DOS attack.
140       */
141       if ((t->reginfo.lock_type >= TL_READ_NO_INSERT)
142           || (thd->lex->sql_command == SQLCOM_LOCK_TABLES))
143       {
144         my_error(ER_CANT_LOCK_LOG_TABLE, MYF(0));
145         DBUG_RETURN(1);
146       }
147     }
148 
149     if (t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE)
150     {
151       if (t->s->table_category == TABLE_CATEGORY_SYSTEM)
152         system_count++;
153 
154       if (t->db_stat & HA_READ_ONLY)
155       {
156         my_error(ER_OPEN_AS_READONLY, MYF(0), t->alias.c_ptr_safe());
157         DBUG_RETURN(1);
158       }
159     }
160 
161     /*
162       If we are going to lock a non-temporary table we must own metadata
163       lock of appropriate type on it (I.e. for table to be locked for
164       write we must own metadata lock of MDL_SHARED_WRITE or stronger
165       type. For table to be locked for read we must own metadata lock
166       of MDL_SHARED_READ or stronger type).
167     */
168     DBUG_ASSERT(t->s->tmp_table ||
169                 thd->mdl_context.is_lock_owner(MDL_key::TABLE,
170                                  t->s->db.str, t->s->table_name.str,
171                                  t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE ?
172                                  MDL_SHARED_WRITE : MDL_SHARED_READ));
173 
174     /*
175       Prevent modifications to base tables if READ_ONLY is activated.
176       In any case, read only does not apply to temporary tables.
177     */
178     if (!(flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY) && !t->s->tmp_table)
179     {
180       if (t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE &&
181           !is_superuser && opt_readonly && !thd->slave_thread)
182       {
183         my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
184         DBUG_RETURN(1);
185       }
186     }
187   }
188 
189   /*
190     Locking of system tables is restricted:
191     locking a mix of system and non-system tables in the same lock
192     is prohibited, to prevent contention.
193   */
194   if ((system_count > 0) && (system_count < count))
195   {
196     my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
197     DBUG_RETURN(1);
198   }
199 
200   DBUG_RETURN(0);
201 }
202 
203 /**
204   Reset lock type in lock data
205 
206   @param mysql_lock             Lock structures to reset.
207   @param unlock			If set, then set lock type to TL_UNLOCK,
208   				otherwise set to original lock type from
209 				get_store_lock().
210 
211   @note After a locking error we want to quit the locking of the table(s).
212         The test case in the bug report for Bug #18544 has the following
213         cases: 1. Locking error in lock_external() due to InnoDB timeout.
214         2. Locking error in get_lock_data() due to missing write permission.
215         3. Locking error in wait_if_global_read_lock() due to lock conflict.
216 
217   @note In all these cases we have already set the lock type into the lock
218         data of the open table(s). If the table(s) are in the open table
219         cache, they could be reused with the non-zero lock type set. This
220         could lead to ignoring a different lock type with the next lock.
221 
222   @note Clear the lock type of all lock data. This ensures that the next
223         lock request will set its lock type properly.
224 */
225 
226 
reset_lock_data(MYSQL_LOCK * sql_lock,bool unlock)227 void reset_lock_data(MYSQL_LOCK *sql_lock, bool unlock)
228 {
229   THR_LOCK_DATA **ldata, **ldata_end;
230   DBUG_ENTER("reset_lock_data");
231 
232   /* Clear the lock type of all lock data to avoid reusage. */
233   for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
234        ldata < ldata_end;
235        ldata++)
236     (*ldata)->type= unlock ? TL_UNLOCK : (*ldata)->org_type;
237   DBUG_VOID_RETURN;
238 }
239 
240 
241 /**
242   Scan array of tables for access types; update transaction tracker
243   accordingly.
244 
245    @param thd          The current thread.
246    @param tables       An array of pointers to the tables to lock.
247    @param count        The number of tables to lock.
248 */
249 
250 #ifndef EMBEDDED_LIBRARY
track_table_access(THD * thd,TABLE ** tables,size_t count)251 static void track_table_access(THD *thd, TABLE **tables, size_t count)
252 {
253   if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
254   {
255     while (count--)
256     {
257       if (TABLE *t= tables[count])
258         thd->session_tracker.transaction_info.add_trx_state(thd,
259           t->reginfo.lock_type, t->file->has_transaction_manager());
260     }
261   }
262 }
263 #else
264 #define track_table_access(A,B,C)
265 #endif //EMBEDDED_LIBRARY
266 
267 
268 
269 /**
270    Lock tables.
271 
272    @param thd          The current thread.
273    @param tables       An array of pointers to the tables to lock.
274    @param count        The number of tables to lock.
275    @param flags        Options:
276                  MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY Ignore SET GLOBAL READ_ONLY
277                  MYSQL_LOCK_IGNORE_TIMEOUT          Use maximum timeout value.
278 
279    @retval  A lock structure pointer on success.
280    @retval  NULL if an error or if wait on a lock was killed.
281 */
282 
mysql_lock_tables(THD * thd,TABLE ** tables,uint count,uint flags)283 MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
284 {
285   MYSQL_LOCK *sql_lock;
286   uint gld_flags= GET_LOCK_STORE_LOCKS;
287   DBUG_ENTER("mysql_lock_tables(tables)");
288 
289   if (lock_tables_check(thd, tables, count, flags))
290     DBUG_RETURN(NULL);
291 
292   if (!(thd->variables.option_bits & OPTION_TABLE_LOCK) &&
293       !(flags & MYSQL_LOCK_USE_MALLOC))
294     gld_flags|= GET_LOCK_ON_THD;
295 
296   if (! (sql_lock= get_lock_data(thd, tables, count, gld_flags)))
297     DBUG_RETURN(NULL);
298 
299   if (mysql_lock_tables(thd, sql_lock, flags))
300   {
301     /* Clear the lock type of all lock data to avoid reusage. */
302     reset_lock_data(sql_lock, 1);
303     if (!(gld_flags & GET_LOCK_ON_THD))
304       my_free(sql_lock);
305     sql_lock= 0;
306   }
307 
308   track_table_access(thd, tables, count);
309 
310   DBUG_RETURN(sql_lock);
311 }
312 
313 /**
314    Lock tables based on a MYSQL_LOCK structure.
315 
316    mysql_lock_tables()
317 
318    @param thd			The current thread.
319    @param sql_lock		Tables that should be locked
320    @param flags			See mysql_lock_tables() above
321 
322    @return 0   ok
323    @return 1  error
324 */
325 
mysql_lock_tables(THD * thd,MYSQL_LOCK * sql_lock,uint flags)326 bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags)
327 {
328   int rc= 1;
329   ulong timeout= (flags & MYSQL_LOCK_IGNORE_TIMEOUT) ?
330     LONG_TIMEOUT : thd->variables.lock_wait_timeout;
331   PSI_stage_info org_stage;
332   DBUG_ENTER("mysql_lock_tables(sql_lock)");
333 
334   thd->backup_stage(&org_stage);
335   THD_STAGE_INFO(thd, stage_system_lock);
336   if (sql_lock->table_count && lock_external(thd, sql_lock->table,
337                                              sql_lock->table_count))
338     goto end;
339 
340   THD_STAGE_INFO(thd, stage_table_lock);
341 
342   /* Copy the lock data array. thr_multi_lock() reorders its contents. */
343   memmove(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
344           sql_lock->lock_count * sizeof(*sql_lock->locks));
345 
346   /* Lock on the copied half of the lock data array. */
347   rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
348                                                    sql_lock->lock_count,
349                                                    sql_lock->lock_count,
350                                                    &thd->lock_info, timeout)];
351   if (rc && sql_lock->table_count)
352     (void) unlock_external(thd, sql_lock->table, sql_lock->table_count);
353 
354 end:
355   THD_STAGE_INFO(thd, org_stage);
356 
357   if (thd->killed)
358   {
359     thd->send_kill_message();
360     if (!rc)
361     {
362       mysql_unlock_tables(thd, sql_lock, 0);
363       THD_STAGE_INFO(thd, stage_after_table_lock);
364     }
365     rc= 1;
366   }
367   else if (rc > 1)
368     my_error(rc, MYF(0));
369 
370   thd->set_time_after_lock();
371   DBUG_RETURN(rc);
372 }
373 
374 
lock_external(THD * thd,TABLE ** tables,uint count)375 static int lock_external(THD *thd, TABLE **tables, uint count)
376 {
377   uint i;
378   int lock_type,error;
379   DBUG_ENTER("lock_external");
380 
381   DBUG_PRINT("info", ("count %d", count));
382   for (i=1 ; i <= count ; i++, tables++)
383   {
384     DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
385     lock_type=F_WRLCK;				/* Lock exclusive */
386     if ((*tables)->db_stat & HA_READ_ONLY ||
387 	((*tables)->reginfo.lock_type >= TL_READ &&
388 	 (*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
389       lock_type=F_RDLCK;
390 
391     if (unlikely((error=(*tables)->file->ha_external_lock(thd,lock_type))))
392     {
393       (*tables)->file->print_error(error, MYF(0));
394       while (--i)
395       {
396         tables--;
397 	(*tables)->file->ha_external_lock(thd, F_UNLCK);
398 	(*tables)->current_lock=F_UNLCK;
399       }
400       DBUG_RETURN(error);
401     }
402     else
403     {
404       (*tables)->current_lock= lock_type;
405     }
406   }
407   DBUG_RETURN(0);
408 }
409 
410 
mysql_unlock_tables(THD * thd,MYSQL_LOCK * sql_lock)411 void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
412 {
413   mysql_unlock_tables(thd, sql_lock,
414                       (thd->variables.option_bits & OPTION_TABLE_LOCK) ||
415                       !(sql_lock->flags & GET_LOCK_ON_THD));
416 }
417 
418 
mysql_unlock_tables(THD * thd,MYSQL_LOCK * sql_lock,bool free_lock)419 void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock)
420 {
421   bool errors= thd->is_error();
422   PSI_stage_info org_stage;
423   DBUG_ENTER("mysql_unlock_tables");
424 
425   thd->backup_stage(&org_stage);
426   THD_STAGE_INFO(thd, stage_unlocking_tables);
427 
428   if (sql_lock->table_count)
429     unlock_external(thd, sql_lock->table, sql_lock->table_count);
430   if (sql_lock->lock_count)
431     thr_multi_unlock(sql_lock->locks, sql_lock->lock_count, 0);
432   if (free_lock)
433   {
434     DBUG_ASSERT(!(sql_lock->flags & GET_LOCK_ON_THD));
435     my_free(sql_lock);
436   }
437   if (likely(!errors))
438     thd->clear_error();
439   THD_STAGE_INFO(thd, org_stage);
440   DBUG_VOID_RETURN;
441 }
442 
443 /**
444   Unlock some of the tables locked by mysql_lock_tables.
445 
446   This will work even if get_lock_data fails (next unlock will free all)
447 */
448 
mysql_unlock_some_tables(THD * thd,TABLE ** table,uint count,uint flag)449 void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count, uint flag)
450 {
451   MYSQL_LOCK *sql_lock=
452     get_lock_data(thd, table, count, GET_LOCK_UNLOCK | GET_LOCK_ON_THD | flag);
453   if (sql_lock)
454     mysql_unlock_tables(thd, sql_lock, 0);
455 }
456 
457 
458 /**
459   unlock all tables locked for read.
460 */
461 
mysql_unlock_read_tables(THD * thd,MYSQL_LOCK * sql_lock)462 void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock)
463 {
464   uint i,found;
465   DBUG_ENTER("mysql_unlock_read_tables");
466 
467   /* Call external lock for all tables to be unlocked */
468 
469   /* Move all write locked tables first */
470   TABLE **table=sql_lock->table;
471   for (i=found=0 ; i < sql_lock->table_count ; i++)
472   {
473     DBUG_ASSERT(sql_lock->table[i]->lock_position == i);
474     if ((uint) sql_lock->table[i]->reginfo.lock_type > TL_WRITE_ALLOW_WRITE)
475     {
476       swap_variables(TABLE *, *table, sql_lock->table[i]);
477       table++;
478       found++;
479     }
480   }
481   /* Unlock all read locked tables */
482   if (i != found)
483   {
484     (void) unlock_external(thd,table,i-found);
485     sql_lock->table_count=found;
486   }
487 
488   /* Call thr_unlock() for all tables to be unlocked */
489 
490   /* Move all write locks first */
491   THR_LOCK_DATA **lock=sql_lock->locks;
492   for (i=found=0 ; i < sql_lock->lock_count ; i++)
493   {
494     if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_WRITE)
495     {
496       swap_variables(THR_LOCK_DATA *, *lock, sql_lock->locks[i]);
497       lock++;
498       found++;
499     }
500   }
501   /* unlock the read locked tables */
502   if (i != found)
503   {
504     thr_multi_unlock(lock, i-found, 0);
505     sql_lock->lock_count= found;
506   }
507 
508   /* Fix the lock positions in TABLE */
509   table= sql_lock->table;
510   found= 0;
511   for (i= 0; i < sql_lock->table_count; i++)
512   {
513     TABLE *tbl= *table;
514     tbl->lock_position= (uint) (table - sql_lock->table);
515     tbl->lock_data_start= found;
516     found+= tbl->lock_count;
517     table++;
518   }
519   DBUG_VOID_RETURN;
520 }
521 
522 
523 /**
524   Try to find the table in the list of locked tables.
525   In case of success, unlock the table and remove it from this list.
526   If a table has more than one lock instance, removes them all.
527 
528   @param  thd             thread context
529   @param  locked          list of locked tables
530   @param  table           the table to unlock
531 */
532 
mysql_lock_remove(THD * thd,MYSQL_LOCK * locked,TABLE * table)533 void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table)
534 {
535   if (locked)
536   {
537     uint i;
538     for (i=0; i < locked->table_count; i++)
539     {
540       if (locked->table[i] == table)
541       {
542         uint  j, removed_locks, old_tables;
543         TABLE *tbl;
544         uint lock_data_end;
545 
546         DBUG_ASSERT(table->lock_position == i);
547 
548         /* Unlock the table. */
549         mysql_unlock_some_tables(thd, &table, /* table count */ 1, 0);
550 
551         /* Decrement table_count in advance, making below expressions easier */
552         old_tables= --locked->table_count;
553 
554         /* The table has 'removed_locks' lock data elements in locked->locks */
555         removed_locks= table->lock_count;
556 
557         /* Move down all table pointers above 'i'. */
558 	bmove((char*) (locked->table+i),
559 	      (char*) (locked->table+i+1),
560 	      (old_tables - i) * sizeof(TABLE*));
561 
562         lock_data_end= table->lock_data_start + table->lock_count;
563         /* Move down all lock data pointers above 'table->lock_data_end-1' */
564         bmove((char*) (locked->locks + table->lock_data_start),
565               (char*) (locked->locks + lock_data_end),
566               (locked->lock_count - lock_data_end) *
567               sizeof(THR_LOCK_DATA*));
568 
569         /*
570           Fix moved table elements.
571           lock_position is the index in the 'locked->table' array,
572           it must be fixed by one.
573           table->lock_data_start is pointer to the lock data for this table
574           in the 'locked->locks' array, they must be fixed by 'removed_locks',
575           the lock data count of the removed table.
576         */
577         for (j= i ; j < old_tables; j++)
578         {
579           tbl= locked->table[j];
580           tbl->lock_position--;
581           DBUG_ASSERT(tbl->lock_position == j);
582           tbl->lock_data_start-= removed_locks;
583         }
584 
585         /* Finally adjust lock_count. */
586         locked->lock_count-= removed_locks;
587 	break;
588       }
589     }
590   }
591 }
592 
593 
594 /**
595   Abort one thread / table combination.
596 
597   @param thd	   Thread handler
598   @param table	   Table that should be removed from lock queue
599 
600   @retval
601     0  Table was not locked by another thread
602   @retval
603     1  Table was locked by at least one other thread
604 */
605 
mysql_lock_abort_for_thread(THD * thd,TABLE * table)606 bool mysql_lock_abort_for_thread(THD *thd, TABLE *table)
607 {
608   MYSQL_LOCK *locked;
609   bool result= FALSE;
610   DBUG_ENTER("mysql_lock_abort_for_thread");
611 
612   if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK | GET_LOCK_ON_THD)))
613   {
614     for (uint i=0; i < locked->lock_count; i++)
615     {
616       if (thr_abort_locks_for_thread(locked->locks[i]->lock,
617                                      table->in_use->thread_id))
618         result= TRUE;
619     }
620   }
621   DBUG_RETURN(result);
622 }
623 
624 
625 /**
626   Merge two thr_lock:s
627   mysql_lock_merge()
628 
629   @param a	Original locks
630   @param b	New locks
631 
632   @retval	New lock structure that contains a and b
633 
634   @note
635   a and b are freed with my_free()
636 */
637 
mysql_lock_merge(MYSQL_LOCK * a,MYSQL_LOCK * b)638 MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
639 {
640   MYSQL_LOCK *sql_lock;
641   TABLE **table, **end_table;
642   DBUG_ENTER("mysql_lock_merge");
643   DBUG_PRINT("enter", ("a->lock_count: %u  b->lock_count: %u",
644                        a->lock_count, b->lock_count));
645 
646   if (!(sql_lock= (MYSQL_LOCK*)
647 	my_malloc(sizeof(*sql_lock)+
648 		  sizeof(THR_LOCK_DATA*)*((a->lock_count+b->lock_count)*2) +
649 		  sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
650     DBUG_RETURN(0);				// Fatal error
651   sql_lock->lock_count=a->lock_count+b->lock_count;
652   sql_lock->table_count=a->table_count+b->table_count;
653   sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
654   sql_lock->table=(TABLE**) (sql_lock->locks+sql_lock->lock_count*2);
655   sql_lock->flags= 0;
656   memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
657   memcpy(sql_lock->locks+a->lock_count,b->locks,
658 	 b->lock_count*sizeof(*b->locks));
659   memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
660   memcpy(sql_lock->table+a->table_count,b->table,
661 	 b->table_count*sizeof(*b->table));
662 
663   /*
664     Now adjust lock_position and lock_data_start for all objects that was
665     moved in 'b' (as there is now all objects in 'a' before these).
666   */
667   for (table= sql_lock->table + a->table_count,
668          end_table= table + b->table_count;
669        table < end_table;
670        table++)
671   {
672     (*table)->lock_position+=   a->table_count;
673     (*table)->lock_data_start+= a->lock_count;
674   }
675 
676   /*
677     Ensure that locks of the same tables share same data structures if we
678     reopen a table that is already open. This can happen for example with
679     MERGE tables.
680   */
681 
682   /* Copy the lock data array. thr_merge_lock() reorders its content */
683   memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
684          sql_lock->lock_count * sizeof(*sql_lock->locks));
685   thr_merge_locks(sql_lock->locks + sql_lock->lock_count,
686                   a->lock_count, b->lock_count);
687 
688   /* Delete old, not needed locks */
689   my_free(a);
690   my_free(b);
691   DBUG_RETURN(sql_lock);
692 }
693 
694 
695 /** Unlock a set of external. */
696 
unlock_external(THD * thd,TABLE ** table,uint count)697 static int unlock_external(THD *thd, TABLE **table,uint count)
698 {
699   int error,error_code;
700   DBUG_ENTER("unlock_external");
701 
702   error_code=0;
703   do
704   {
705     if ((*table)->current_lock != F_UNLCK)
706     {
707       (*table)->current_lock = F_UNLCK;
708       if (unlikely((error=(*table)->file->ha_external_lock(thd, F_UNLCK))))
709       {
710         error_code= error;
711         (*table)->file->print_error(error, MYF(0));
712       }
713     }
714     table++;
715   } while (--count);
716   DBUG_RETURN(error_code);
717 }
718 
719 
720 /**
721   Get lock structures from table structs and initialize locks.
722 
723   @param thd		    Thread handler
724   @param table_ptr	    Pointer to tables that should be locks
725   @param flags		    One of:
726            - GET_LOCK_UNLOCK      : If we should send TL_IGNORE to store lock
727            - GET_LOCK_STORE_LOCKS : Store lock info in TABLE
728            - GET_LOCK_SKIP_SEQUENCES : Ignore sequences (for temporary unlock)
729            - GET_LOCK_ON_THD      : Store lock in thd->mem_root
730 
731   Temporary tables are not locked (as these are single user), except for
732   TRANSACTIONAL_TMP_TABLES as locking is needed to handle transactions.
733 */
734 
get_lock_data(THD * thd,TABLE ** table_ptr,uint count,uint flags)735 MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
736 {
737   uint i,lock_count,table_count;
738   MYSQL_LOCK *sql_lock;
739   THR_LOCK_DATA **locks, **locks_buf;
740   TABLE **to, **table_buf;
741   DBUG_ENTER("get_lock_data");
742 
743   DBUG_PRINT("info", ("count %d", count));
744 
745   for (i=lock_count=table_count=0 ; i < count ; i++)
746   {
747     TABLE *t= table_ptr[i];
748 
749     if ((likely(!t->s->tmp_table) ||
750          (t->s->tmp_table == TRANSACTIONAL_TMP_TABLE)) &&
751         (!(flags & GET_LOCK_SKIP_SEQUENCES) || t->s->sequence == 0))
752     {
753       lock_count+= t->file->lock_count();
754       table_count++;
755     }
756   }
757 
758   /*
759     Allocating twice the number of pointers for lock data for use in
760     thr_multi_lock(). This function reorders the lock data, but cannot
761     update the table values. So the second part of the array is copied
762     from the first part immediately before calling thr_multi_lock().
763   */
764   size_t amount= sizeof(*sql_lock) +
765                  sizeof(THR_LOCK_DATA*) * lock_count * 2 +
766                  sizeof(table_ptr) * table_count;
767   if (!(sql_lock= (MYSQL_LOCK*) (flags & GET_LOCK_ON_THD ?
768                                  thd->alloc(amount) :
769                                  my_malloc(amount, MYF(0)))))
770     DBUG_RETURN(0);
771   locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
772   to= table_buf= sql_lock->table= (TABLE**) (locks + lock_count * 2);
773   sql_lock->table_count= table_count;
774   sql_lock->flags= flags;
775 
776   for (i=0 ; i < count ; i++)
777   {
778     TABLE *table= table_ptr[i];
779     enum thr_lock_type lock_type;
780     THR_LOCK_DATA **locks_start;
781 
782     if (!((likely(!table->s->tmp_table) ||
783            (table->s->tmp_table == TRANSACTIONAL_TMP_TABLE)) &&
784           (!(flags & GET_LOCK_SKIP_SEQUENCES) || table->s->sequence == 0)))
785       continue;
786     lock_type= table->reginfo.lock_type;
787     DBUG_ASSERT(lock_type != TL_WRITE_DEFAULT && lock_type != TL_READ_DEFAULT);
788     locks_start= locks;
789     locks= table->file->store_lock(thd, locks,
790              (flags & GET_LOCK_ACTION_MASK) == GET_LOCK_UNLOCK ? TL_IGNORE :
791              lock_type);
792     if ((flags & GET_LOCK_ACTION_MASK) == GET_LOCK_STORE_LOCKS)
793     {
794       table->lock_position=   (uint) (to - table_buf);
795       table->lock_data_start= (uint) (locks_start - locks_buf);
796       table->lock_count=      (uint) (locks - locks_start);
797     }
798     *to++= table;
799     if (locks)
800     {
801       for ( ; locks_start != locks ; locks_start++)
802       {
803 	(*locks_start)->debug_print_param= (void *) table;
804         (*locks_start)->m_psi= table->file->m_psi;
805 	(*locks_start)->lock->name=         table->alias.c_ptr();
806 	(*locks_start)->org_type=           (*locks_start)->type;
807       }
808     }
809   }
810   /*
811     We do not use 'lock_count', because there are cases where store_lock()
812     returns less locks than lock_count() claimed. This can happen when
813     a FLUSH TABLES tries to abort locks from a MERGE table of another
814     thread. When that thread has just opened the table, but not yet
815     attached its children, it cannot return the locks. lock_count()
816     always returns the number of locks that an attached table has.
817     This is done to avoid the reverse situation: If lock_count() would
818     return 0 for a non-attached MERGE table, and that table becomes
819     attached between the calls to lock_count() and store_lock(), then
820     we would have allocated too little memory for the lock data. Now
821     we may allocate too much, but better safe than memory overrun.
822     And in the FLUSH case, the memory is released quickly anyway.
823   */
824   sql_lock->lock_count= (uint)(locks - locks_buf);
825   DBUG_ASSERT(sql_lock->lock_count <= lock_count);
826   DBUG_PRINT("info", ("sql_lock->table_count %d sql_lock->lock_count %d",
827                       sql_lock->table_count, sql_lock->lock_count));
828   DBUG_RETURN(sql_lock);
829 }
830 
831 
832 /**
833   Obtain an exclusive metadata lock on a schema name.
834 
835   @param thd         Thread handle.
836   @param db          The database name.
837 
838   To avoid deadlocks, we do not try to obtain exclusive metadata
839   locks in LOCK TABLES mode, since in this mode there may be
840   other metadata locks already taken by the current connection,
841   and we must not wait for MDL locks while holding locks.
842 
843   @retval FALSE  Success.
844   @retval TRUE   Failure: we're in LOCK TABLES mode, or out of memory,
845                  or this connection was killed.
846 */
847 
lock_schema_name(THD * thd,const char * db)848 bool lock_schema_name(THD *thd, const char *db)
849 {
850   MDL_request_list mdl_requests;
851   MDL_request global_request;
852   MDL_request mdl_request;
853 
854   if (thd->locked_tables_mode)
855   {
856     my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
857                ER_THD(thd, ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
858     return TRUE;
859   }
860 
861   if (thd->global_read_lock.can_acquire_protection())
862     return TRUE;
863   global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
864                       MDL_STATEMENT);
865   mdl_request.init(MDL_key::SCHEMA, db, "", MDL_EXCLUSIVE, MDL_TRANSACTION);
866 
867   mdl_requests.push_front(&mdl_request);
868   mdl_requests.push_front(&global_request);
869 
870   if (thd->mdl_context.acquire_locks(&mdl_requests,
871                                      thd->variables.lock_wait_timeout))
872     return TRUE;
873 
874   DEBUG_SYNC(thd, "after_wait_locked_schema_name");
875   return FALSE;
876 }
877 
878 
879 /**
880   Obtain an exclusive metadata lock on an object name.
881 
882   @param thd         Thread handle.
883   @param mdl_type    Object type (currently functions, procedures
884                      and events can be name-locked).
885   @param db          The schema the object belongs to.
886   @param name        Object name in the schema.
887 
888   This function assumes that no metadata locks were acquired
889   before calling it. It is enforced by asserts in MDL_context::acquire_locks().
890   To avoid deadlocks, we do not try to obtain exclusive metadata
891   locks in LOCK TABLES mode, since in this mode there may be
892   other metadata locks already taken by the current connection,
893   and we must not wait for MDL locks while holding locks.
894 
895   @retval FALSE  Success.
896   @retval TRUE   Failure: we're in LOCK TABLES mode, or out of memory,
897                  or this connection was killed.
898 */
899 
lock_object_name(THD * thd,MDL_key::enum_mdl_namespace mdl_type,const char * db,const char * name)900 bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type,
901                        const char *db, const char *name)
902 {
903   MDL_request_list mdl_requests;
904   MDL_request global_request;
905   MDL_request schema_request;
906   MDL_request mdl_request;
907 
908   DBUG_SLOW_ASSERT(ok_for_lower_case_names(db));
909 
910   if (thd->locked_tables_mode)
911   {
912     my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
913                ER_THD(thd, ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
914     return TRUE;
915   }
916 
917   DBUG_ASSERT(name);
918   DEBUG_SYNC(thd, "before_wait_locked_pname");
919 
920   if (thd->global_read_lock.can_acquire_protection())
921     return TRUE;
922   global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE,
923                       MDL_STATEMENT);
924   schema_request.init(MDL_key::SCHEMA, db, "", MDL_INTENTION_EXCLUSIVE,
925                       MDL_TRANSACTION);
926   mdl_request.init(mdl_type, db, name, MDL_EXCLUSIVE, MDL_TRANSACTION);
927 
928   mdl_requests.push_front(&mdl_request);
929   mdl_requests.push_front(&schema_request);
930   mdl_requests.push_front(&global_request);
931 
932   if (thd->mdl_context.acquire_locks(&mdl_requests,
933                                      thd->variables.lock_wait_timeout))
934     return TRUE;
935 
936   DEBUG_SYNC(thd, "after_wait_locked_pname");
937   return FALSE;
938 }
939 
940 
941 /****************************************************************************
942   Handling of global read locks
943 
944   Global read lock is implemented using metadata lock infrastructure.
945 
946   Taking the global read lock is TWO steps (2nd step is optional; without
947   it, COMMIT of existing transactions will be allowed):
948   lock_global_read_lock() THEN make_global_read_lock_block_commit().
949 
950   How blocking of threads by global read lock is achieved: that's
951   semi-automatic. We assume that any statement which should be blocked
952   by global read lock will either open and acquires write-lock on tables
953   or acquires metadata locks on objects it is going to modify. For any
954   such statement global IX metadata lock is automatically acquired for
955   its duration (in case of LOCK TABLES until end of LOCK TABLES mode).
956   And lock_global_read_lock() simply acquires global S metadata lock
957   and thus prohibits execution of statements which modify data (unless
958   they modify only temporary tables). If deadlock happens it is detected
959   by MDL subsystem and resolved in the standard fashion (by backing-off
960   metadata locks acquired so far and restarting open tables process
961   if possible).
962 
963   Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used
964   to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary
965   log.
966 
967   Why getting the global read lock is two steps and not one. Because FLUSH
968   TABLES WITH READ LOCK needs to insert one other step between the two:
969   flushing tables. So the order is
970   1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls
971   all new updates)
972   2) close_cached_tables() (the FLUSH TABLES), which will wait for tables
973   currently opened and being updated to close (so it's possible that there is
974   a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
975   READ LOCK is, too).
976   3) make_global_read_lock_block_commit().
977   If we have merged 1) and 3) into 1), we would have had this deadlock:
978   imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
979   table t.
980   thd1: SELECT * FROM t FOR UPDATE;
981   thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1
982   thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
983   table instance of thd2
984   thd1: COMMIT; # blocked by thd3.
985   thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
986 
987   Note that we need to support that one thread does
988   FLUSH TABLES WITH READ LOCK; and then COMMIT;
989   (that's what innobackup does, for some good reason).
990   So in this exceptional case the COMMIT should not be blocked by the FLUSH
991   TABLES WITH READ LOCK.
992 
993 ****************************************************************************/
994 
995 /**
996   Take global read lock, wait if there is protection against lock.
997 
998   If the global read lock is already taken by this thread, then nothing is done.
999 
1000   See also "Handling of global read locks" above.
1001 
1002   @param thd     Reference to thread.
1003 
1004   @retval False  Success, global read lock set, commits are NOT blocked.
1005   @retval True   Failure, thread was killed.
1006 */
1007 
lock_global_read_lock(THD * thd)1008 bool Global_read_lock::lock_global_read_lock(THD *thd)
1009 {
1010   DBUG_ENTER("lock_global_read_lock");
1011 
1012   if (!m_state)
1013   {
1014     MDL_request mdl_request;
1015 
1016     DBUG_ASSERT(! thd->mdl_context.is_lock_owner(MDL_key::GLOBAL, "", "",
1017                                                  MDL_SHARED));
1018     mdl_request.init(MDL_key::GLOBAL, "", "", MDL_SHARED, MDL_EXPLICIT);
1019 
1020     if (thd->mdl_context.acquire_lock(&mdl_request,
1021                                       thd->variables.lock_wait_timeout))
1022       DBUG_RETURN(1);
1023 
1024     m_mdl_global_shared_lock= mdl_request.ticket;
1025     m_state= GRL_ACQUIRED;
1026   }
1027   /*
1028     We DON'T set global_read_lock_blocks_commit now, it will be set after
1029     tables are flushed (as the present function serves for FLUSH TABLES WITH
1030     READ LOCK only). Doing things in this order is necessary to avoid
1031     deadlocks (we must allow COMMIT until all tables are closed; we should not
1032     forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
1033     UPDATE and one does FLUSH TABLES WITH READ LOCK).
1034   */
1035   DBUG_RETURN(0);
1036 }
1037 
1038 
1039 /**
1040   Unlock global read lock.
1041 
1042   Commits may or may not be blocked when this function is called.
1043 
1044   See also "Handling of global read locks" above.
1045 
1046   @param thd    Reference to thread.
1047 */
1048 
unlock_global_read_lock(THD * thd)1049 void Global_read_lock::unlock_global_read_lock(THD *thd)
1050 {
1051   DBUG_ENTER("unlock_global_read_lock");
1052 
1053   DBUG_ASSERT(m_mdl_global_shared_lock && m_state);
1054 
1055   if (thd->global_disable_checkpoint)
1056   {
1057     thd->global_disable_checkpoint= 0;
1058     if (!--global_disable_checkpoint)
1059     {
1060       ha_checkpoint_state(0);                   // Enable checkpoints
1061     }
1062   }
1063 
1064   if (m_mdl_blocks_commits_lock)
1065   {
1066     thd->mdl_context.release_lock(m_mdl_blocks_commits_lock);
1067     m_mdl_blocks_commits_lock= NULL;
1068 #ifdef WITH_WSREP
1069     if (WSREP(thd) || wsrep_node_is_donor())
1070     {
1071       wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
1072       wsrep->resume(wsrep);
1073       /* resync here only if we did implicit desync earlier */
1074       if (!wsrep_desync && wsrep_node_is_synced())
1075       {
1076         int ret = wsrep->resync(wsrep);
1077         if (ret != WSREP_OK)
1078         {
1079           WSREP_WARN("resync failed %d for FTWRL: db: %s, query: %s",
1080                      ret, thd->get_db(), thd->query());
1081           DBUG_VOID_RETURN;
1082         }
1083       }
1084     }
1085 #endif /* WITH_WSREP */
1086   }
1087   thd->mdl_context.release_lock(m_mdl_global_shared_lock);
1088   m_mdl_global_shared_lock= NULL;
1089   m_state= GRL_NONE;
1090 
1091   DBUG_VOID_RETURN;
1092 }
1093 
1094 
1095 /**
1096   Make global read lock also block commits.
1097 
1098   The scenario is:
1099    - This thread has the global read lock.
1100    - Global read lock blocking of commits is not set.
1101 
1102   See also "Handling of global read locks" above.
1103 
1104   @param thd     Reference to thread.
1105 
1106   @retval False  Success, global read lock set, commits are blocked.
1107   @retval True   Failure, thread was killed.
1108 */
1109 
make_global_read_lock_block_commit(THD * thd)1110 bool Global_read_lock::make_global_read_lock_block_commit(THD *thd)
1111 {
1112   MDL_request mdl_request;
1113   DBUG_ENTER("make_global_read_lock_block_commit");
1114   /*
1115     If we didn't succeed lock_global_read_lock(), or if we already succeeded
1116     make_global_read_lock_block_commit(), do nothing.
1117   */
1118 
1119   if (m_state != GRL_ACQUIRED)
1120     DBUG_RETURN(0);
1121 
1122 #ifdef WITH_WSREP
1123   if (WSREP(thd) && m_mdl_blocks_commits_lock)
1124   {
1125     WSREP_DEBUG("GRL was in block commit mode when entering "
1126 		"make_global_read_lock_block_commit");
1127     DBUG_RETURN(FALSE);
1128   }
1129 #endif /* WITH_WSREP */
1130 
1131   mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT);
1132 
1133   if (thd->mdl_context.acquire_lock(&mdl_request,
1134                                     thd->variables.lock_wait_timeout))
1135     DBUG_RETURN(TRUE);
1136 
1137   m_mdl_blocks_commits_lock= mdl_request.ticket;
1138   m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT;
1139 
1140 #ifdef WITH_WSREP
1141   /* Native threads should bail out before wsrep oprations to follow.
1142      Donor servicing thread is an exception, it should pause provider but not desync,
1143      as it is already desynced in donor state
1144   */
1145   if (!WSREP(thd) && !wsrep_node_is_donor())
1146   {
1147     DBUG_RETURN(FALSE);
1148   }
1149 
1150   /* if already desynced or donor, avoid double desyncing
1151      if not in PC and synced, desyncing is not possible either
1152   */
1153   if (wsrep_desync || !wsrep_node_is_synced())
1154   {
1155     WSREP_DEBUG("desync set upfont, skipping implicit desync for FTWRL: %d",
1156                 wsrep_desync);
1157   }
1158   else
1159   {
1160     int rcode;
1161     WSREP_DEBUG("running implicit desync for node");
1162     rcode = wsrep->desync(wsrep);
1163     if (rcode != WSREP_OK)
1164     {
1165       WSREP_WARN("FTWRL desync failed %d for schema: %s, query: %s",
1166                  rcode, thd->get_db(), thd->query());
1167       my_message(ER_LOCK_DEADLOCK, "wsrep desync failed for FTWRL", MYF(0));
1168       DBUG_RETURN(TRUE);
1169     }
1170   }
1171 
1172   long long ret = wsrep->pause(wsrep);
1173   if (ret >= 0)
1174   {
1175     wsrep_locked_seqno= ret;
1176   }
1177   else if (ret != -ENOSYS) /* -ENOSYS - no provider */
1178   {
1179     long long ret = wsrep->pause(wsrep);
1180     if (ret >= 0)
1181     {
1182       wsrep_locked_seqno= ret;
1183     }
1184     else if (ret != -ENOSYS) /* -ENOSYS - no provider */
1185     {
1186       WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret));
1187 
1188       DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL);
1189       wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED;
1190       my_error(ER_LOCK_DEADLOCK, MYF(0));
1191       DBUG_RETURN(TRUE);
1192      }
1193   }
1194 #endif /* WITH_WSREP */
1195   DBUG_RETURN(FALSE);
1196 }
1197 
1198 
1199 /**
1200   Set explicit duration for metadata locks which are used to implement GRL.
1201 
1202   @param thd     Reference to thread.
1203 */
1204 
set_explicit_lock_duration(THD * thd)1205 void Global_read_lock::set_explicit_lock_duration(THD *thd)
1206 {
1207   if (m_mdl_global_shared_lock)
1208     thd->mdl_context.set_lock_duration(m_mdl_global_shared_lock, MDL_EXPLICIT);
1209   if (m_mdl_blocks_commits_lock)
1210     thd->mdl_context.set_lock_duration(m_mdl_blocks_commits_lock, MDL_EXPLICIT);
1211 }
1212 
1213 /**
1214   @} (end of group Locking)
1215 */
1216