Commit 7a6342c2 authored by unknown's avatar unknown

Fixed problem of deleting blocks which are being evicted at

the moment. (BUG#34634)
Fixed potential bug in pinning schema.


storage/maria/ma_pagecache.c:
  Fixed problem of deleting blocks which are being evicted at
  the moment.
  Fixed potential bug in pinning schema.
parent b2724a6a
...@@ -1331,6 +1331,7 @@ static void unlink_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block) ...@@ -1331,6 +1331,7 @@ static void unlink_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
{ {
DBUG_ENTER("unlink_block"); DBUG_ENTER("unlink_block");
DBUG_PRINT("unlink_block", ("unlink 0x%lx", (ulong)block)); DBUG_PRINT("unlink_block", ("unlink 0x%lx", (ulong)block));
DBUG_ASSERT(block->next_used != NULL);
if (block->next_used == block) if (block->next_used == block)
{ {
/* The list contains only one member */ /* The list contains only one member */
...@@ -2440,20 +2441,17 @@ static void release_rdlock(PAGECACHE_BLOCK_LINK *block) ...@@ -2440,20 +2441,17 @@ static void release_rdlock(PAGECACHE_BLOCK_LINK *block)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* /**
Try to lock/unlock and pin/unpin the block @brief Try to lock/unlock and pin/unpin the block
SYNOPSIS @param pagecache pointer to a page cache data structure
make_lock_and_pin() @param block the block to work with
pagecache pointer to a page cache data structure @param lock lock change mode
block the block to work with @param pin pinchange mode
lock lock change mode @param file File handler requesting pin
pin pinchange mode
file File handler requesting pin
RETURN @retval 0 OK
0 - OK @retval 1 Try to lock the block failed
1 - Try to lock the block failed
*/ */
static my_bool make_lock_and_pin(PAGECACHE *pagecache, static my_bool make_lock_and_pin(PAGECACHE *pagecache,
...@@ -2551,8 +2549,6 @@ retry: ...@@ -2551,8 +2549,6 @@ retry:
PCBLOCK_INFO(block); PCBLOCK_INFO(block);
DBUG_ASSERT(block->hash_link->requests > 0); DBUG_ASSERT(block->hash_link->requests > 0);
block->hash_link->requests--; block->hash_link->requests--;
DBUG_ASSERT(block->requests > 0);
unreg_request(pagecache, block, 1);
PCBLOCK_INFO(block); PCBLOCK_INFO(block);
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -3118,6 +3114,7 @@ uchar *pagecache_read(PAGECACHE *pagecache, ...@@ -3118,6 +3114,7 @@ uchar *pagecache_read(PAGECACHE *pagecache,
PAGECACHE_BLOCK_LINK *fake_link; PAGECACHE_BLOCK_LINK *fake_link;
#ifndef DBUG_OFF #ifndef DBUG_OFF
char llbuf[22]; char llbuf[22];
my_bool reg_request;
DBUG_ENTER("pagecache_read"); DBUG_ENTER("pagecache_read");
DBUG_PRINT("enter", ("fd: %u page: %s buffer: 0x%lx level: %u " DBUG_PRINT("enter", ("fd: %u page: %s buffer: 0x%lx level: %u "
"t:%s %s %s", "t:%s %s %s",
...@@ -3154,11 +3151,11 @@ restart: ...@@ -3154,11 +3151,11 @@ restart:
inc_counter_for_resize_op(pagecache); inc_counter_for_resize_op(pagecache);
pagecache->global_cache_r_requests++; pagecache->global_cache_r_requests++;
/* See NOTE for pagecache_unlock about registering requests. */ /* See NOTE for pagecache_unlock about registering requests. */
reg_request= ((pin == PAGECACHE_PIN_LEFT_UNPINNED) ||
(pin == PAGECACHE_PIN));
block= find_block(pagecache, file, pageno, level, block= find_block(pagecache, file, pageno, level,
test(lock == PAGECACHE_LOCK_WRITE), test(lock == PAGECACHE_LOCK_WRITE),
test((pin == PAGECACHE_PIN_LEFT_UNPINNED) || reg_request, &page_st);
(pin == PAGECACHE_PIN)),
&page_st);
DBUG_PRINT("info", ("Block type: %s current type %s", DBUG_PRINT("info", ("Block type: %s current type %s",
page_cache_page_type_str[block->type], page_cache_page_type_str[block->type],
page_cache_page_type_str[type])); page_cache_page_type_str[type]));
...@@ -3197,6 +3194,8 @@ restart: ...@@ -3197,6 +3194,8 @@ restart:
We failed to write lock the block, cache is unlocked, We failed to write lock the block, cache is unlocked,
we will try to get the block again. we will try to get the block again.
*/ */
if (reg_request)
unreg_request(pagecache, block, 1);
pagecache_pthread_mutex_unlock(&pagecache->cache_lock); pagecache_pthread_mutex_unlock(&pagecache->cache_lock);
DBUG_PRINT("info", ("restarting...")); DBUG_PRINT("info", ("restarting..."));
goto restart; goto restart;
...@@ -3328,9 +3327,10 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache, ...@@ -3328,9 +3327,10 @@ 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 */
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))
DBUG_ASSERT(0);
DBUG_ASSERT(block->hash_link->requests > 0); DBUG_ASSERT(block->hash_link->requests > 0);
page_link->requests--; page_link->requests--;
/* See NOTE for pagecache_unlock about registering requests. */ /* See NOTE for pagecache_unlock about registering requests. */
...@@ -3375,24 +3375,24 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache, ...@@ -3375,24 +3375,24 @@ my_bool pagecache_delete_by_link(PAGECACHE *pagecache,
lock == PAGECACHE_LOCK_LEFT_WRITELOCKED); lock == PAGECACHE_LOCK_LEFT_WRITELOCKED);
DBUG_ASSERT(block->pins != 0); /* should be pinned */ DBUG_ASSERT(block->pins != 0); /* should be pinned */
restart:
if (pagecache->can_be_used) if (pagecache->can_be_used)
{ {
pagecache_pthread_mutex_lock(&pagecache->cache_lock); pagecache_pthread_mutex_lock(&pagecache->cache_lock);
if (!pagecache->can_be_used) if (!pagecache->can_be_used)
goto end; goto end;
/*
This block should be pinned (i.e. has not zero request counter) =>
Such block can't be chosen for eviction.
*/
DBUG_ASSERT((block->status &
(PCBLOCK_IN_SWITCH | PCBLOCK_REASSIGNED)) == 0);
/*
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)
*/
if (make_lock_and_pin(pagecache, block, lock, pin)) if (make_lock_and_pin(pagecache, block, lock, pin))
{ DBUG_ASSERT(0);
/*
We failed to writelock the block, cache is unlocked, and last write
lock is released, we will try to get the block again.
*/
pagecache_pthread_mutex_unlock(&pagecache->cache_lock);
DBUG_PRINT("info", ("restarting..."));
goto restart;
}
/* /*
get_present_hash_link() side effect emulation before call get_present_hash_link() side effect emulation before call
...@@ -3495,6 +3495,16 @@ restart: ...@@ -3495,6 +3495,16 @@ restart:
DBUG_RETURN(0); DBUG_RETURN(0);
} }
block= page_link->block; block= page_link->block;
if (block->status & (PCBLOCK_REASSIGNED | PCBLOCK_IN_SWITCH))
{
DBUG_PRINT("info", ("Block 0x%0lx already is %s",
(ulong) block,
((block->status & PCBLOCK_REASSIGNED) ?
"reassigned" : "in switch")));
PCBLOCK_INFO(block);
page_link->requests--;
goto end;
}
/* See NOTE for pagecache_unlock about registering requests. */ /* See NOTE for pagecache_unlock about registering requests. */
if (pin == PAGECACHE_PIN) if (pin == PAGECACHE_PIN)
reg_requests(pagecache, block, 1); reg_requests(pagecache, block, 1);
...@@ -3505,6 +3515,8 @@ restart: ...@@ -3505,6 +3515,8 @@ restart:
We failed to writelock the block, cache is unlocked, and last write We failed to writelock the block, cache is unlocked, and last write
lock is released, we will try to get the block again. lock is released, we will try to get the block again.
*/ */
if (pin == PAGECACHE_PIN)
unreg_request(pagecache, block, 1);
pagecache_pthread_mutex_unlock(&pagecache->cache_lock); pagecache_pthread_mutex_unlock(&pagecache->cache_lock);
DBUG_PRINT("info", ("restarting...")); DBUG_PRINT("info", ("restarting..."));
goto restart; goto restart;
...@@ -3642,6 +3654,7 @@ my_bool pagecache_write_part(PAGECACHE *pagecache, ...@@ -3642,6 +3654,7 @@ my_bool pagecache_write_part(PAGECACHE *pagecache,
int need_lock_change= write_lock_change_table[lock].need_lock_change; int need_lock_change= write_lock_change_table[lock].need_lock_change;
#ifndef DBUG_OFF #ifndef DBUG_OFF
char llbuf[22]; char llbuf[22];
my_bool reg_request;
DBUG_ENTER("pagecache_write_part"); DBUG_ENTER("pagecache_write_part");
DBUG_PRINT("enter", ("fd: %u page: %s level: %u type: %s lock: %s " DBUG_PRINT("enter", ("fd: %u page: %s level: %u type: %s lock: %s "
"pin: %s mode: %s offset: %u size %u", "pin: %s mode: %s offset: %u size %u",
...@@ -3684,14 +3697,14 @@ restart: ...@@ -3684,14 +3697,14 @@ restart:
inc_counter_for_resize_op(pagecache); inc_counter_for_resize_op(pagecache);
pagecache->global_cache_w_requests++; pagecache->global_cache_w_requests++;
/* See NOTE for pagecache_unlock about registering requests. */ /* See NOTE for pagecache_unlock about registering requests. */
reg_request= ((pin == PAGECACHE_PIN_LEFT_UNPINNED) ||
(pin == PAGECACHE_PIN));
block= find_block(pagecache, file, pageno, level, block= find_block(pagecache, file, pageno, level,
test(write_mode != PAGECACHE_WRITE_DONE && test(write_mode != PAGECACHE_WRITE_DONE &&
lock != PAGECACHE_LOCK_LEFT_WRITELOCKED && lock != PAGECACHE_LOCK_LEFT_WRITELOCKED &&
lock != PAGECACHE_LOCK_WRITE_UNLOCK && lock != PAGECACHE_LOCK_WRITE_UNLOCK &&
lock != PAGECACHE_LOCK_WRITE_TO_READ), lock != PAGECACHE_LOCK_WRITE_TO_READ),
test((pin == PAGECACHE_PIN_LEFT_UNPINNED) || reg_request, &page_st);
(pin == PAGECACHE_PIN)),
&page_st);
if (!block) if (!block)
{ {
DBUG_ASSERT(write_mode != PAGECACHE_WRITE_DONE); DBUG_ASSERT(write_mode != PAGECACHE_WRITE_DONE);
...@@ -3724,6 +3737,8 @@ restart: ...@@ -3724,6 +3737,8 @@ restart:
We failed to writelock the block, cache is unlocked, and last write We failed to writelock the block, cache is unlocked, and last write
lock is released, we will try to get the block again. lock is released, we will try to get the block again.
*/ */
if (reg_request)
unreg_request(pagecache, block, 1);
pagecache_pthread_mutex_unlock(&pagecache->cache_lock); pagecache_pthread_mutex_unlock(&pagecache->cache_lock);
DBUG_PRINT("info", ("restarting...")); DBUG_PRINT("info", ("restarting..."));
goto restart; goto restart;
...@@ -4042,9 +4057,10 @@ static int flush_cached_blocks(PAGECACHE *pagecache, ...@@ -4042,9 +4057,10 @@ static int flush_cached_blocks(PAGECACHE *pagecache,
pagecache->readwrite_flags); pagecache->readwrite_flags);
pagecache_pthread_mutex_lock(&pagecache->cache_lock); pagecache_pthread_mutex_lock(&pagecache->cache_lock);
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))
DBUG_ASSERT(0);
pagecache->global_cache_write++; pagecache->global_cache_write++;
if (error) if (error)
......
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