Commit dc1607c2 authored by Guilhem Bichot's avatar Guilhem Bichot

_ma_bitmap_unpin_all() needs to unpin not-locked pages which were pinned by other threads

in write_changed_bitmap(), and page cache forbids that. Here we make the page
cache more relaxed. Original patch by Sanja, simplified by me as limited to
not-locked. See comment of ma_bitmap.c.
With that, maria_stress.yy runs until hitting BUG 39665.

storage/maria/ma_bitmap.c:
  A thread which unpins bitmap pages in _ma_bitmap_unpin_all() sometimes
  hit an assertion in the page cache (info!=0 in remove_pin()) which states
  that you can unpin/unlock only what *you* have pinned/locked.
  Fixed by setting the new last parameter of pagecache_unlock_by_link()
  to TRUE in _ma_bitmap_unpin_all().
storage/maria/ma_blockrec.c:
  new prototype and splitting assertion in three (3rd one fires: BUG 39665)
storage/maria/ma_check.c:
  new prototype
storage/maria/ma_key_recover.c:
  new prototype
storage/maria/ma_loghandler.c:
  new prototype
storage/maria/ma_pagecache.c:
  Allow a thread to unpin, with pagecache_unlock_by_link(), a non-locked page pinned by others.
  This is a hack for _ma_bitmap_unpin_all() which needs to unpin pages which were
  pinned by other threads in write_changed_bitmap().
storage/maria/ma_pagecache.h:
  new prototype
storage/maria/ma_preload.c:
  new prototype
storage/maria/unittest/ma_pagecache_rwconsist.c:
  new prototype
storage/maria/unittest/ma_pagecache_single.c:
  new prototype
parent e1c00c8b
...@@ -418,7 +418,7 @@ static void _ma_bitmap_unpin_all(MARIA_SHARE *share) ...@@ -418,7 +418,7 @@ static void _ma_bitmap_unpin_all(MARIA_SHARE *share)
while (pinned_page-- != page_link) while (pinned_page-- != page_link)
pagecache_unlock_by_link(share->pagecache, pinned_page->link, pagecache_unlock_by_link(share->pagecache, pinned_page->link,
pinned_page->unlock, PAGECACHE_UNPIN, pinned_page->unlock, PAGECACHE_UNPIN,
LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, TRUE); LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, TRUE, TRUE);
bitmap->pinned_pages.elements= 0; bitmap->pinned_pages.elements= 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -1964,7 +1964,7 @@ static my_bool write_tail(MARIA_HA *info, ...@@ -1964,7 +1964,7 @@ static my_bool write_tail(MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link->link, pagecache_unlock_by_link(share->pagecache, page_link->link,
PAGECACHE_LOCK_WRITE_TO_READ, PAGECACHE_LOCK_WRITE_TO_READ,
PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 1); LSN_IMPOSSIBLE, 1, FALSE);
DBUG_ASSERT(page_link->changed); DBUG_ASSERT(page_link->changed);
page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK; page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK;
res= 0; res= 0;
...@@ -3026,7 +3026,7 @@ static my_bool write_block_record(MARIA_HA *info, ...@@ -3026,7 +3026,7 @@ static my_bool write_block_record(MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link->link, pagecache_unlock_by_link(share->pagecache, page_link->link,
PAGECACHE_LOCK_WRITE_TO_READ, PAGECACHE_LOCK_WRITE_TO_READ,
PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 1); LSN_IMPOSSIBLE, 1, FALSE);
page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK; page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK;
page_link->changed= 1; page_link->changed= 1;
} }
...@@ -4025,7 +4025,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info, ...@@ -4025,7 +4025,7 @@ static my_bool delete_head_or_tail(MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
lock_at_write, lock_at_write,
PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE, PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 1); LSN_IMPOSSIBLE, 1, FALSE);
page_link.unlock= lock_at_unpin; page_link.unlock= lock_at_unpin;
set_dynamic(&info->pinned_pages, (void*) &page_link, set_dynamic(&info->pinned_pages, (void*) &page_link,
info->pinned_pages.elements-1); info->pinned_pages.elements-1);
...@@ -5143,7 +5143,9 @@ int _ma_scan_block_record(MARIA_HA *info, uchar *record, ...@@ -5143,7 +5143,9 @@ int _ma_scan_block_record(MARIA_HA *info, uchar *record,
if (end_of_data > info->scan.dir_end || if (end_of_data > info->scan.dir_end ||
offset < PAGE_HEADER_SIZE || length < share->base.min_block_length) offset < PAGE_HEADER_SIZE || length < share->base.min_block_length)
{ {
DBUG_ASSERT(0); DBUG_ASSERT(!(end_of_data > info->scan.dir_end));
DBUG_ASSERT(!(offset < PAGE_HEADER_SIZE));
DBUG_ASSERT(!(length < share->base.min_block_length));
goto err; goto err;
} }
#endif #endif
...@@ -6035,7 +6037,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -6035,7 +6037,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -6125,7 +6127,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -6125,7 +6127,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
_ma_mark_file_crashed(share); _ma_mark_file_crashed(share);
DBUG_RETURN((my_errno= error)); DBUG_RETURN((my_errno= error));
} }
...@@ -6195,7 +6197,7 @@ uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -6195,7 +6197,7 @@ uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -6223,7 +6225,7 @@ uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -6223,7 +6225,7 @@ uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
_ma_mark_file_crashed(share); _ma_mark_file_crashed(share);
DBUG_RETURN((my_errno= error)); DBUG_RETURN((my_errno= error));
...@@ -6327,7 +6329,7 @@ uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -6327,7 +6329,7 @@ uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
goto err; goto err;
} }
if (lsn_korr(buff) >= lsn) if (lsn_korr(buff) >= lsn)
...@@ -6336,7 +6338,7 @@ uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -6336,7 +6338,7 @@ uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
} }
else else
{ {
...@@ -6476,7 +6478,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, ...@@ -6476,7 +6478,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
goto err; goto err;
} }
/* /*
...@@ -6496,7 +6498,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info, ...@@ -6496,7 +6498,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
continue; continue;
} }
} }
......
...@@ -3184,7 +3184,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, ...@@ -3184,7 +3184,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
_ma_check_print_error(param, _ma_check_print_error(param,
"Page %9s: Got error %d when reading index file", "Page %9s: Got error %d when reading index file",
llstr(pos, llbuff), my_errno); llstr(pos, llbuff), my_errno);
...@@ -3218,7 +3218,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info, ...@@ -3218,7 +3218,7 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 1); LSN_IMPOSSIBLE, 1, FALSE);
} }
if (flush_pagecache_blocks(share->pagecache, &share->kfile, if (flush_pagecache_blocks(share->pagecache, &share->kfile,
FLUSH_FORCE_WRITE)) FLUSH_FORCE_WRITE))
...@@ -3342,7 +3342,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info, ...@@ -3342,7 +3342,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 1); LSN_IMPOSSIBLE, 1, FALSE);
} }
DBUG_RETURN(_ma_bitmap_flush(share) || DBUG_RETURN(_ma_bitmap_flush(share) ||
flush_pagecache_blocks(share->pagecache, &info->dfile, flush_pagecache_blocks(share->pagecache, &info->dfile,
...@@ -3352,7 +3352,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info, ...@@ -3352,7 +3352,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
......
...@@ -70,7 +70,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn) ...@@ -70,7 +70,7 @@ void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn)
pagecache_unlock_by_link(info->s->pagecache, pinned_page->link, pagecache_unlock_by_link(info->s->pagecache, pinned_page->link,
pinned_page->unlock, PAGECACHE_UNPIN, pinned_page->unlock, PAGECACHE_UNPIN,
info->trn->rec_lsn, undo_lsn, info->trn->rec_lsn, undo_lsn,
pinned_page->changed); pinned_page->changed, FALSE);
} }
info->pinned_pages.elements= 0; info->pinned_pages.elements= 0;
...@@ -700,7 +700,7 @@ uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn, ...@@ -700,7 +700,7 @@ uint _ma_apply_redo_index_new_page(MARIA_HA *info, LSN lsn,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
DBUG_RETURN(result); DBUG_RETURN(result);
} }
...@@ -779,7 +779,7 @@ uint _ma_apply_redo_index_free_page(MARIA_HA *info, ...@@ -779,7 +779,7 @@ uint _ma_apply_redo_index_free_page(MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
DBUG_RETURN(result); DBUG_RETURN(result);
} }
...@@ -1047,7 +1047,7 @@ uint _ma_apply_redo_index(MARIA_HA *info, ...@@ -1047,7 +1047,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
pagecache_unlock_by_link(share->pagecache, page_link.link, pagecache_unlock_by_link(share->pagecache, page_link.link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, LSN_IMPOSSIBLE, PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, 0, FALSE);
if (result) if (result)
_ma_mark_file_crashed(share); _ma_mark_file_crashed(share);
DBUG_RETURN(result); DBUG_RETURN(result);
......
...@@ -3028,7 +3028,7 @@ static void translog_free_link(PAGECACHE_BLOCK_LINK *direct_link) ...@@ -3028,7 +3028,7 @@ static void translog_free_link(PAGECACHE_BLOCK_LINK *direct_link)
if (direct_link) if (direct_link)
pagecache_unlock_by_link(log_descriptor.pagecache, direct_link, pagecache_unlock_by_link(log_descriptor.pagecache, direct_link,
PAGECACHE_LOCK_READ_UNLOCK, PAGECACHE_UNPIN, PAGECACHE_LOCK_READ_UNLOCK, PAGECACHE_UNPIN,
LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0); LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0, FALSE);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -267,16 +267,21 @@ static void info_unlink(PAGECACHE_PIN_INFO *node) ...@@ -267,16 +267,21 @@ static void info_unlink(PAGECACHE_PIN_INFO *node)
list the list where to find the thread list the list where to find the thread
thread thread ID (reference to the st_my_thread_var thread thread ID (reference to the st_my_thread_var
of the thread) of the thread)
any return any thread of the list
RETURN RETURN
0 - the thread was not found 0 - the thread was not found
pointer to the information node of the thread in the list pointer to the information node of the thread in the list, or, if 'any',
to any thread of the list.
*/ */
static PAGECACHE_PIN_INFO *info_find(PAGECACHE_PIN_INFO *list, static PAGECACHE_PIN_INFO *info_find(PAGECACHE_PIN_INFO *list,
struct st_my_thread_var *thread) struct st_my_thread_var *thread,
my_bool any)
{ {
register PAGECACHE_PIN_INFO *i= list; register PAGECACHE_PIN_INFO *i= list;
if (any)
return i;
for(; i != 0; i= i->next) for(; i != 0; i= i->next)
if (i->thread == thread) if (i->thread == thread)
return i; return i;
...@@ -2150,18 +2155,22 @@ static void add_pin(PAGECACHE_BLOCK_LINK *block) ...@@ -2150,18 +2155,22 @@ static void add_pin(PAGECACHE_BLOCK_LINK *block)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
static void remove_pin(PAGECACHE_BLOCK_LINK *block) static void remove_pin(PAGECACHE_BLOCK_LINK *block, my_bool any
#ifdef DBUG_OFF
__attribute__((unused))
#endif
)
{ {
DBUG_ENTER("remove_pin"); DBUG_ENTER("remove_pin");
DBUG_PRINT("enter", ("block: 0x%lx pins: %u", DBUG_PRINT("enter", ("block: 0x%lx pins: %u any: %d",
(ulong) block, (ulong) block,
block->pins)); block->pins, (int)any));
PCBLOCK_INFO(block); PCBLOCK_INFO(block);
DBUG_ASSERT(block->pins > 0); DBUG_ASSERT(block->pins > 0);
block->pins--; block->pins--;
#ifndef DBUG_OFF #ifndef DBUG_OFF
{ {
PAGECACHE_PIN_INFO *info= info_find(block->pin_list, my_thread_var); PAGECACHE_PIN_INFO *info= info_find(block->pin_list, my_thread_var, any);
DBUG_ASSERT(info != 0); DBUG_ASSERT(info != 0);
info_unlink(info); info_unlink(info);
my_free((uchar*) info, MYF(0)); my_free((uchar*) info, MYF(0));
...@@ -2183,7 +2192,7 @@ static void info_remove_lock(PAGECACHE_BLOCK_LINK *block) ...@@ -2183,7 +2192,7 @@ static void info_remove_lock(PAGECACHE_BLOCK_LINK *block)
{ {
PAGECACHE_LOCK_INFO *info= PAGECACHE_LOCK_INFO *info=
(PAGECACHE_LOCK_INFO *)info_find((PAGECACHE_PIN_INFO *)block->lock_list, (PAGECACHE_LOCK_INFO *)info_find((PAGECACHE_PIN_INFO *)block->lock_list,
my_thread_var); my_thread_var, FALSE);
DBUG_ASSERT(info != 0); DBUG_ASSERT(info != 0);
info_unlink((PAGECACHE_PIN_INFO *)info); info_unlink((PAGECACHE_PIN_INFO *)info);
my_free((uchar*)info, MYF(0)); my_free((uchar*)info, MYF(0));
...@@ -2192,7 +2201,7 @@ static void info_change_lock(PAGECACHE_BLOCK_LINK *block, my_bool wl) ...@@ -2192,7 +2201,7 @@ static void info_change_lock(PAGECACHE_BLOCK_LINK *block, my_bool wl)
{ {
PAGECACHE_LOCK_INFO *info= PAGECACHE_LOCK_INFO *info=
(PAGECACHE_LOCK_INFO *)info_find((PAGECACHE_PIN_INFO *)block->lock_list, (PAGECACHE_LOCK_INFO *)info_find((PAGECACHE_PIN_INFO *)block->lock_list,
my_thread_var); my_thread_var, FALSE);
DBUG_ASSERT(info != 0); DBUG_ASSERT(info != 0);
DBUG_ASSERT(info->write_lock != wl); DBUG_ASSERT(info->write_lock != wl);
info->write_lock= wl; info->write_lock= wl;
...@@ -2448,6 +2457,8 @@ static void release_rdlock(PAGECACHE_BLOCK_LINK *block) ...@@ -2448,6 +2457,8 @@ static void release_rdlock(PAGECACHE_BLOCK_LINK *block)
@param lock lock change mode @param lock lock change mode
@param pin pinchange mode @param pin pinchange mode
@param file File handler requesting pin @param file File handler requesting pin
@param any allow unpinning block pinned by any thread; possible
only if not locked, see pagecache_unlock_by_link()
@retval 0 OK @retval 0 OK
@retval 1 Try to lock the block failed @retval 1 Try to lock the block failed
...@@ -2456,7 +2467,8 @@ static void release_rdlock(PAGECACHE_BLOCK_LINK *block) ...@@ -2456,7 +2467,8 @@ static void release_rdlock(PAGECACHE_BLOCK_LINK *block)
static my_bool make_lock_and_pin(PAGECACHE *pagecache, static my_bool make_lock_and_pin(PAGECACHE *pagecache,
PAGECACHE_BLOCK_LINK *block, PAGECACHE_BLOCK_LINK *block,
enum pagecache_page_lock lock, enum pagecache_page_lock lock,
enum pagecache_page_pin pin) enum pagecache_page_pin pin,
my_bool any)
{ {
DBUG_ENTER("make_lock_and_pin"); DBUG_ENTER("make_lock_and_pin");
...@@ -2465,16 +2477,20 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache, ...@@ -2465,16 +2477,20 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache,
if (block) if (block)
{ {
DBUG_PRINT("enter", ("block: 0x%lx (%u) wrlocks: %u rdlocks: %u " DBUG_PRINT("enter", ("block: 0x%lx (%u) wrlocks: %u rdlocks: %u "
"rdlocks_q: %u pins: %u lock: %s pin: %s", "rdlocks_q: %u pins: %u lock: %s pin: %s any %d",
(ulong)block, PCBLOCK_NUMBER(pagecache, block), (ulong)block, PCBLOCK_NUMBER(pagecache, block),
block->wlocks, block->rlocks, block->rlocks_queue, block->wlocks, block->rlocks, block->rlocks_queue,
block->pins, block->pins,
page_cache_page_lock_str[lock], page_cache_page_lock_str[lock],
page_cache_page_pin_str[pin])); page_cache_page_pin_str[pin], (int)any));
PCBLOCK_INFO(block); PCBLOCK_INFO(block);
} }
#endif #endif
DBUG_ASSERT(!any ||
((lock == PAGECACHE_LOCK_LEFT_UNLOCKED) &&
(pin == PAGECACHE_UNPIN)));
switch (lock) { switch (lock) {
case PAGECACHE_LOCK_WRITE: /* free -> write */ case PAGECACHE_LOCK_WRITE: /* free -> write */
/* Writelock and pin the buffer */ /* Writelock and pin the buffer */
...@@ -2500,7 +2516,7 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache, ...@@ -2500,7 +2516,7 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache,
case PAGECACHE_LOCK_LEFT_READLOCKED: /* read -> read */ case PAGECACHE_LOCK_LEFT_READLOCKED: /* read -> read */
if (pin == PAGECACHE_UNPIN) if (pin == PAGECACHE_UNPIN)
{ {
remove_pin(block); remove_pin(block, FALSE);
} }
if (lock == PAGECACHE_LOCK_WRITE_TO_READ) if (lock == PAGECACHE_LOCK_WRITE_TO_READ)
{ {
...@@ -2529,7 +2545,7 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache, ...@@ -2529,7 +2545,7 @@ static my_bool make_lock_and_pin(PAGECACHE *pagecache,
case PAGECACHE_LOCK_LEFT_UNLOCKED: /* free -> free */ case PAGECACHE_LOCK_LEFT_UNLOCKED: /* free -> free */
if (pin == PAGECACHE_UNPIN) if (pin == PAGECACHE_UNPIN)
{ {
remove_pin(block); remove_pin(block, any);
} }
/* fall through */ /* fall through */
case PAGECACHE_LOCK_LEFT_WRITELOCKED: /* write -> write */ case PAGECACHE_LOCK_LEFT_WRITELOCKED: /* write -> write */
...@@ -2793,7 +2809,7 @@ void pagecache_unlock(PAGECACHE *pagecache, ...@@ -2793,7 +2809,7 @@ void pagecache_unlock(PAGECACHE *pagecache,
(ulong) block)); (ulong) block));
} }
if (make_lock_and_pin(pagecache, block, lock, pin)) if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
{ {
DBUG_ASSERT(0); /* should not happend */ DBUG_ASSERT(0); /* should not happend */
} }
...@@ -2863,7 +2879,7 @@ void pagecache_unpin(PAGECACHE *pagecache, ...@@ -2863,7 +2879,7 @@ void pagecache_unpin(PAGECACHE *pagecache,
*/ */
if (make_lock_and_pin(pagecache, block, if (make_lock_and_pin(pagecache, block,
PAGECACHE_LOCK_LEFT_READLOCKED, PAGECACHE_LOCK_LEFT_READLOCKED,
PAGECACHE_UNPIN)) PAGECACHE_UNPIN, FALSE))
DBUG_ASSERT(0); /* should not happend */ DBUG_ASSERT(0); /* should not happend */
remove_reader(block); remove_reader(block);
...@@ -2886,15 +2902,22 @@ void pagecache_unpin(PAGECACHE *pagecache, ...@@ -2886,15 +2902,22 @@ void pagecache_unpin(PAGECACHE *pagecache,
@brief Unlock/unpin page and put LSN stamp if it need @brief Unlock/unpin page and put LSN stamp if it need
(uses direct block/page pointer) (uses direct block/page pointer)
@param pagecache pointer to a page cache data structure @param pagecache pointer to a page cache data structure
@param link direct link to page (returned by read or write) @param link direct link to page (returned by read or write)
@param lock lock change @param lock lock change
@param pin pin page @param pin pin page
@param first_REDO_LSN_for_page do not set it if it is LSN_IMPOSSIBLE (0) @param first_REDO_LSN_for_page do not set it if it is LSN_IMPOSSIBLE (0)
@param lsn if it is not LSN_IMPOSSIBLE and it is bigger then @param lsn if it is not LSN_IMPOSSIBLE and it is bigger then
LSN on the page it will be written on the page LSN on the page it will be written on the page
@param was_changed should be true if the page was write locked with @param was_changed should be true if the page was write locked with
direct link giving and the page was changed direct link giving and the page was changed
@param any allow unpinning block pinned by any thread; possible
only if not locked
@note 'any' is a hack so that _ma_bitmap_unpin_all() is allowed to unpin
non-locked bitmap pages pinned by other threads. Because it always uses
PAGECACHE_LOCK_LEFT_UNLOCKED and PAGECACHE_UNPIN
(see write_changed_bitmap()), the hack is limited to these conditions.
*/ */
void pagecache_unlock_by_link(PAGECACHE *pagecache, void pagecache_unlock_by_link(PAGECACHE *pagecache,
...@@ -2902,7 +2925,8 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, ...@@ -2902,7 +2925,8 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache,
enum pagecache_page_lock lock, enum pagecache_page_lock lock,
enum pagecache_page_pin pin, enum pagecache_page_pin pin,
LSN first_REDO_LSN_for_page, LSN first_REDO_LSN_for_page,
LSN lsn, my_bool was_changed) LSN lsn, my_bool was_changed,
my_bool any)
{ {
DBUG_ENTER("pagecache_unlock_by_link"); DBUG_ENTER("pagecache_unlock_by_link");
DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu changed: %d %s %s", DBUG_PRINT("enter", ("block: 0x%lx fd: %u page: %lu changed: %d %s %s",
...@@ -2922,7 +2946,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, ...@@ -2922,7 +2946,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache,
if (pin == PAGECACHE_PIN_LEFT_UNPINNED && if (pin == PAGECACHE_PIN_LEFT_UNPINNED &&
lock == PAGECACHE_LOCK_READ_UNLOCK) lock == PAGECACHE_LOCK_READ_UNLOCK)
{ {
if (make_lock_and_pin(pagecache, block, lock, pin)) if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
DBUG_ASSERT(0); /* should not happend */ DBUG_ASSERT(0); /* should not happend */
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2976,7 +3000,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache, ...@@ -2976,7 +3000,7 @@ void pagecache_unlock_by_link(PAGECACHE *pagecache,
(ulong) block)); (ulong) block));
} }
if (make_lock_and_pin(pagecache, block, lock, pin)) if (make_lock_and_pin(pagecache, block, lock, pin, any))
DBUG_ASSERT(0); /* should not happend */ DBUG_ASSERT(0); /* should not happend */
/* /*
...@@ -3039,7 +3063,7 @@ void pagecache_unpin_by_link(PAGECACHE *pagecache, ...@@ -3039,7 +3063,7 @@ void pagecache_unpin_by_link(PAGECACHE *pagecache,
*/ */
if (make_lock_and_pin(pagecache, block, if (make_lock_and_pin(pagecache, block,
PAGECACHE_LOCK_LEFT_READLOCKED, PAGECACHE_LOCK_LEFT_READLOCKED,
PAGECACHE_UNPIN)) PAGECACHE_UNPIN, FALSE))
DBUG_ASSERT(0); /* should not happend */ DBUG_ASSERT(0); /* should not happend */
/* /*
...@@ -3190,7 +3214,7 @@ uchar *pagecache_read(PAGECACHE *pagecache, ...@@ -3190,7 +3214,7 @@ uchar *pagecache_read(PAGECACHE *pagecache,
block->type == PAGECACHE_EMPTY_PAGE) block->type == PAGECACHE_EMPTY_PAGE)
block->type= type; block->type= type;
if (make_lock_and_pin(pagecache, block, lock, pin)) if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
{ {
/* /*
We failed to write lock the block, cache is unlocked, We failed to write lock the block, cache is unlocked,
...@@ -3334,7 +3358,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache, ...@@ -3334,7 +3358,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache,
/* Cache is locked, so we can relese page before freeing it */ /* Cache is locked, so we can relese page before freeing it */
if (make_lock_and_pin(pagecache, block, if (make_lock_and_pin(pagecache, block,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN)) PAGECACHE_UNPIN, FALSE))
DBUG_ASSERT(0); DBUG_ASSERT(0);
DBUG_ASSERT(block->hash_link->requests > 0); DBUG_ASSERT(block->hash_link->requests > 0);
page_link->requests--; page_link->requests--;
...@@ -3396,7 +3420,7 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache, ...@@ -3396,7 +3420,7 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache,
make_lock_and_pin() can't fail here, because we are keeping pin on the make_lock_and_pin() can't fail here, because we are keeping pin on the
block and it can't be evicted (which is cause of lock fail and retry) block and it can't be evicted (which is cause of lock fail and retry)
*/ */
if (make_lock_and_pin(pagecache, block, lock, pin)) if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
DBUG_ASSERT(0); DBUG_ASSERT(0);
/* /*
...@@ -3514,7 +3538,7 @@ my_bool pagecache_delete(PAGECACHE *pagecache, ...@@ -3514,7 +3538,7 @@ my_bool pagecache_delete(PAGECACHE *pagecache,
if (pin == PAGECACHE_PIN) if (pin == PAGECACHE_PIN)
reg_requests(pagecache, block, 1); reg_requests(pagecache, block, 1);
DBUG_ASSERT(block != 0); DBUG_ASSERT(block != 0);
if (make_lock_and_pin(pagecache, block, lock, pin)) if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
{ {
/* /*
We failed to writelock the block, cache is unlocked, and last write We failed to writelock the block, cache is unlocked, and last write
...@@ -3736,7 +3760,7 @@ my_bool pagecache_write_part(PAGECACHE *pagecache, ...@@ -3736,7 +3760,7 @@ my_bool pagecache_write_part(PAGECACHE *pagecache,
write_lock_change_table[lock].new_lock, write_lock_change_table[lock].new_lock,
(need_lock_change ? (need_lock_change ?
write_pin_change_table[pin].new_pin : write_pin_change_table[pin].new_pin :
pin))) pin), FALSE))
{ {
/* /*
We failed to writelock the block, cache is unlocked, and last write We failed to writelock the block, cache is unlocked, and last write
...@@ -3823,7 +3847,7 @@ my_bool pagecache_write_part(PAGECACHE *pagecache, ...@@ -3823,7 +3847,7 @@ my_bool pagecache_write_part(PAGECACHE *pagecache,
*/ */
if (make_lock_and_pin(pagecache, block, if (make_lock_and_pin(pagecache, block,
write_lock_change_table[lock].unlock_lock, write_lock_change_table[lock].unlock_lock,
write_pin_change_table[pin].unlock_pin)) write_pin_change_table[pin].unlock_pin, FALSE))
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
...@@ -4034,7 +4058,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, ...@@ -4034,7 +4058,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache,
DBUG_ASSERT(block->wlocks == 0); DBUG_ASSERT(block->wlocks == 0);
DBUG_ASSERT(block->pins == 0); DBUG_ASSERT(block->pins == 0);
if (make_lock_and_pin(pagecache, block, if (make_lock_and_pin(pagecache, block,
PAGECACHE_LOCK_WRITE, PAGECACHE_PIN)) PAGECACHE_LOCK_WRITE, PAGECACHE_PIN, FALSE))
DBUG_ASSERT(0); DBUG_ASSERT(0);
DBUG_ASSERT(block->pins == 1); DBUG_ASSERT(block->pins == 1);
...@@ -4068,7 +4092,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache, ...@@ -4068,7 +4092,7 @@ static int flush_cached_blocks(PAGECACHE *pagecache,
if (make_lock_and_pin(pagecache, block, if (make_lock_and_pin(pagecache, block,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN)) PAGECACHE_UNPIN, FALSE))
DBUG_ASSERT(0); DBUG_ASSERT(0);
pagecache->global_cache_write++; pagecache->global_cache_write++;
......
...@@ -242,7 +242,8 @@ extern void pagecache_unlock_by_link(PAGECACHE *pagecache, ...@@ -242,7 +242,8 @@ extern void pagecache_unlock_by_link(PAGECACHE *pagecache,
enum pagecache_page_lock lock, enum pagecache_page_lock lock,
enum pagecache_page_pin pin, enum pagecache_page_pin pin,
LSN first_REDO_LSN_for_page, LSN first_REDO_LSN_for_page,
LSN lsn, my_bool was_changed); LSN lsn, my_bool was_changed,
my_bool any);
extern void pagecache_unpin(PAGECACHE *pagecache, extern void pagecache_unpin(PAGECACHE *pagecache,
PAGECACHE_FILE *file, PAGECACHE_FILE *file,
pgcache_page_no_t pageno, pgcache_page_no_t pageno,
......
...@@ -104,7 +104,7 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves) ...@@ -104,7 +104,7 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves)
else /* otherwise it stays in cache: */ else /* otherwise it stays in cache: */
pagecache_unlock_by_link(share->pagecache, page_link, pagecache_unlock_by_link(share->pagecache, page_link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN,
LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, FALSE); LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, FALSE, FALSE);
} }
my_free(buff, MYF(0)); my_free(buff, MYF(0));
......
...@@ -114,7 +114,7 @@ void reader(int num) ...@@ -114,7 +114,7 @@ void reader(int num)
check_page(buff, num); check_page(buff, num);
pagecache_unlock_by_link(&pagecache, link, pagecache_unlock_by_link(&pagecache, link,
PAGECACHE_LOCK_READ_UNLOCK, PAGECACHE_LOCK_READ_UNLOCK,
PAGECACHE_UNPIN, 0, 0, 0); PAGECACHE_UNPIN, 0, 0, 0, FALSE);
{ {
int lim= rand() % read_sleep_limit; int lim= rand() % read_sleep_limit;
int j; int j;
...@@ -149,7 +149,7 @@ void writer(int num) ...@@ -149,7 +149,7 @@ void writer(int num)
check_page(buff, num); check_page(buff, num);
pagecache_unlock_by_link(&pagecache, link, pagecache_unlock_by_link(&pagecache, link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_UNPIN, 0, 0, 1); PAGECACHE_UNPIN, 0, 0, 1, FALSE);
SLEEP; SLEEP;
} }
} }
......
...@@ -391,7 +391,7 @@ int simple_pin_no_lock_test() ...@@ -391,7 +391,7 @@ int simple_pin_no_lock_test()
&link, LSN_IMPOSSIBLE); &link, LSN_IMPOSSIBLE);
pagecache_unlock_by_link(&pagecache, link, pagecache_unlock_by_link(&pagecache, link,
PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_LOCK_WRITE_UNLOCK,
PAGECACHE_PIN_LEFT_PINNED, 0, 0, 1); PAGECACHE_PIN_LEFT_PINNED, 0, 0, 1, FALSE);
if (!flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE)) if (!flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
{ {
diag("Did not get error in flush_pagecache_blocks 3\n"); diag("Did not get error in flush_pagecache_blocks 3\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment