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