| Bug #34634 | Concurrent pagecache_delete() and eviction of the same page cause crash | ||
|---|---|---|---|
| Submitted: | 18 Feb 2008 10:11 | Modified: | 5 Mar 2008 8:18 |
| Reporter: | Guilhem Bichot | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Maria storage engine | Severity: | S3 (Non-critical) |
| Version: | OS: | Any | |
| Assigned to: | Oleksandr Byelkin | CPU Architecture: | Any |
[18 Feb 2008 10:11]
Guilhem Bichot
[18 Feb 2008 10:12]
Guilhem Bichot
testcase to crash pagecache
Attachment: bug34634.tar.bz2 (application/x-bzip2, text), 3.14 KiB.
[18 Feb 2008 10:14]
Guilhem Bichot
download bug34634.tar.bz2 from the "Files" section, apply diff to ma_pagecache.c; replace ma_pagecache_single.c of your tree with the one from the tar.bz2, recompile, run "ma_pagecache_single_1k-t --debug". It should segfault. Look at the debug trace it contains tags "BUGINFO" which show what is going wrong.
[22 Feb 2008 8:47]
Oleksandr Byelkin
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2008/02/22 10:42:29+02:00 bell@88-214-96-85.dialup.umc.net.ua
# Fixed problem of deleting blocks which are removing at the moment.
#
# storage/maria/ma_pagecache.c
# 2008/02/22 10:42:19+02:00 bell@88-214-96-85.dialup.umc.net.ua +33 -1
# Avoid deleting blocks which already chosen for deleting.
#
diff -Nru a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c
--- a/storage/maria/ma_pagecache.c 2008-02-22 10:45:48 +02:00
+++ b/storage/maria/ma_pagecache.c 2008-02-22 10:45:48 +02:00
@@ -1774,7 +1774,7 @@
PAGECACHE_HASH_LINK *hash_link;
PAGECACHE_BLOCK_LINK *block;
int error= 0;
- int page_status;
+ int page_status, old_block_status;
DBUG_ENTER("find_block");
KEYCACHE_THREAD_TRACE("find_block:begin");
@@ -1909,7 +1909,12 @@
/* Resubmit the request */
goto restart;
}
+ old_block_status= block->status;
block->status&= ~PCBLOCK_IN_SWITCH;
+ if (old_block_status & PCBLOCK_IN_SWITCH)
+ DBUG_PRINT("info", ("BUGINFO block loses PCBLOCK_IN_SWITCH; "
+ "status %d changes to %d",
+ old_block_status, block->status));
}
else
{
@@ -2009,9 +2014,13 @@
! (block->status & PCBLOCK_IN_SWITCH) )
{
/* this is a primary request for a new page */
+ int old_block_status= block->status;
DBUG_ASSERT(block->wlocks == 0);
DBUG_ASSERT(block->pins == 0);
block->status|= PCBLOCK_IN_SWITCH;
+ DBUG_PRINT("info", ("BUGINFO block got PCBLOCK_IN_SWITCH; "
+ "status %d changes to %d",
+ old_block_status, block->status));
KEYCACHE_DBUG_PRINT("find_block",
("got block %u for new page",
@@ -3225,6 +3234,15 @@
if (!pagecache->can_be_used)
goto end;
+ DBUG_ASSERT((block->status & PCBLOCK_IN_SWITCH) == 0);
+ if (block->status & PCBLOCK_REASSIGNED)
+ {
+ DBUG_PRINT("info", ("Block 0x%0lx already is reassigned",
+ (ulong) block));
+ /* The block (will be | is) flushed and we can't prevent it */
+ error= !flush;
+ goto end;
+ }
if (make_lock_and_pin(pagecache, block, lock, pin))
{
/*
@@ -3336,6 +3354,15 @@
pagecache_pthread_mutex_unlock(&pagecache->cache_lock);
DBUG_RETURN(0);
}
+ if (block->status & (PCBLOCK_REASSIGNED | PCBLOCK_IN_SWITCH))
+ {
+ DBUG_PRINT("info", ("Block 0x%0lx already is reassigned or in switch",
+ (ulong) block));
+ /* The block (will be | is) flushed and we can't prevent it */
+ error= !flush;
+ page_link->requests--;
+ goto end;
+ }
block= page_link->block;
/* See NOTE for pagecache_unlock about registering requests. */
if (pin == PAGECACHE_PIN)
@@ -3348,6 +3375,7 @@
lock is released, we will try to get the block again.
*/
pagecache_pthread_mutex_unlock(&pagecache->cache_lock);
+ page_link->requests--;
DBUG_PRINT("info", ("restarting..."));
goto restart;
}
@@ -3750,10 +3778,14 @@
KEYCACHE_THREAD_TRACE("free block");
KEYCACHE_DBUG_PRINT("free_block",
("block is freed"));
+ if (block->requests > 1)
+ DBUG_PRINT("info",("BUGINFO block->requests is %d", block->requests));
unreg_request(pagecache, block, 0);
block->hash_link= NULL;
/* Remove the free block from the LRU ring. */
+ if (block->next_used == NULL)
+ DBUG_PRINT("info",("BUGINFO block->next_used is NULL"));
unlink_block(pagecache, block);
if (block->temperature == PCBLOCK_WARM)
pagecache->warm_blocks--;
[25 Feb 2008 9:48]
Guilhem Bichot
review sent by mail
[3 Mar 2008 8:25]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/43294 ChangeSet@1.2616, 2008-03-03 10:25:19+02:00, bell@desktop.sanja.is.com.ua +1 -0 Fixed problem of deleting blocks which are being evicted at the moment. (BUG#34634)
[4 Mar 2008 12:00]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/43366 ChangeSet@1.2616, 2008-03-04 13:58:50+02:00, bell@desktop.sanja.is.com.ua +1 -0 Fixed problem of deleting blocks which are being evicted at the moment. (BUG#34634) Fixed potential bug in pinning schema.
[4 Mar 2008 12:05]
Guilhem Bichot
Patch is approved. Another related problem found by Sanja remains (for the case of make_lock_and_pin() failing), so I leave the bug in "patch pending" state.
[4 Mar 2008 14:38]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/43390 ChangeSet@1.2616, 2008-03-04 16:38:29+02:00, bell@desktop.sanja.is.com.ua +1 -0 Fixed problem of deleting blocks which are being evicted at the moment. (BUG#34634) Fixed potential bug in pinning schema.
[4 Mar 2008 21:13]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/43430 ChangeSet@1.2616, 2008-03-04 23:12:19+02:00, bell@desktop.sanja.is.com.ua +1 -0 Fixed problem of deleting blocks which are being evicted at the moment. (BUG#34634) Fixed potential bug in pinning schema.
