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