summaryrefslogtreecommitdiff
path: root/storage/maria/ma_pagecache.c
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2017-05-09 13:24:52 +0200
committerSergei Golubchik <serg@mariadb.org>2017-05-09 13:24:52 +0200
commitc91ecf9e9bebf3cf2dafbd3193de4df94be09870 (patch)
treea9ab429c8e8a6a50c38557cbdd38d9612480f49c /storage/maria/ma_pagecache.c
parent2645bda5f20ab10bc26dc1cb69f91b5505c1faae (diff)
parentc92168fcd26aad35bd4cb5d65175e3545133f201 (diff)
downloadmariadb-git-c91ecf9e9bebf3cf2dafbd3193de4df94be09870.tar.gz
Merge branch '10.1' into 10.2
Revert commit db0917f68f, because the fix for MDEV-12696 is coming from 5.5 and 10.1 in this merge.
Diffstat (limited to 'storage/maria/ma_pagecache.c')
-rw-r--r--storage/maria/ma_pagecache.c59
1 files changed, 46 insertions, 13 deletions
diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c
index afb5fb8bdff..1eebfac03f8 100644
--- a/storage/maria/ma_pagecache.c
+++ b/storage/maria/ma_pagecache.c
@@ -493,7 +493,8 @@ error:
#define FLUSH_CACHE 2000 /* sort this many blocks at once */
-static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block);
+static my_bool free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block,
+ my_bool abort_if_pinned);
static void unlink_hash(PAGECACHE *pagecache, PAGECACHE_HASH_LINK *hash_link);
#ifndef DBUG_OFF
static void test_key_cache(PAGECACHE *pagecache,
@@ -1945,7 +1946,7 @@ restart:
removed from the cache as we set the PCBLOCK_REASSIGNED
flag (see the code below that handles reading requests).
*/
- free_block(pagecache, block);
+ free_block(pagecache, block, 0);
return 0;
}
/* Wait until the page is flushed on disk */
@@ -1956,7 +1957,7 @@ restart:
/* Invalidate page in the block if it has not been done yet */
DBUG_ASSERT(block->status); /* Should always be true */
if (block->status)
- free_block(pagecache, block);
+ free_block(pagecache, block, 0);
return 0;
}
@@ -1981,8 +1982,13 @@ restart:
}
else
{
- DBUG_ASSERT(hash_link->requests > 0);
- hash_link->requests--;
+ /*
+ When we come here either PCBLOCK_REASSIGNED or PCBLOCK_IN_SWITCH are
+ active. In both cases wqueue_release_queue() is called when the
+ state changes.
+ */
+ DBUG_ASSERT(block->hash_link == hash_link);
+ remove_reader(block);
KEYCACHE_DBUG_PRINT("find_block",
("request waiting for old page to be saved"));
{
@@ -3638,7 +3644,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache,
DBUG_ASSERT(block->hash_link->requests > 0);
page_link->requests--;
/* See NOTE for pagecache_unlock() about registering requests. */
- free_block(pagecache, block);
+ free_block(pagecache, block, 0);
dec_counter_for_resize_op(pagecache);
return 0;
@@ -4219,7 +4225,8 @@ end:
and add it to the free list.
*/
-static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
+static my_bool free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block,
+ my_bool abort_if_pinned)
{
uint status= block->status;
KEYCACHE_THREAD_TRACE("free block");
@@ -4233,11 +4240,27 @@ static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
/*
While waiting for readers to finish, new readers might request the
block. But since we set block->status|= PCBLOCK_REASSIGNED, they
- will wait on block->wqueue[COND_FOR_SAVED]. They must be signalled
+ will wait on block->wqueue[COND_FOR_SAVED]. They must be signaled
later.
*/
block->status|= PCBLOCK_REASSIGNED;
wait_for_readers(pagecache, block);
+ if (unlikely(abort_if_pinned) && unlikely(block->pins))
+ {
+ /*
+ Block got pinned while waiting for readers.
+ This can only happens when called from flush_pagecache_blocks_int()
+ when flushing blocks as part of prepare for maria_close() or from
+ flush_cached_blocks()
+ */
+ block->status&= ~PCBLOCK_REASSIGNED;
+ unreg_request(pagecache, block, 0);
+
+ /* All pending requests for this page must be resubmitted. */
+ if (block->wqueue[COND_FOR_SAVED].last_thread)
+ wqueue_release_queue(&block->wqueue[COND_FOR_SAVED]);
+ return 1;
+ }
unlink_hash(pagecache, block->hash_link);
}
@@ -4288,6 +4311,8 @@ static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
/* All pending requests for this page must be resubmitted. */
if (block->wqueue[COND_FOR_SAVED].last_thread)
wqueue_release_queue(&block->wqueue[COND_FOR_SAVED]);
+
+ return 0;
}
@@ -4423,9 +4448,16 @@ static int flush_cached_blocks(PAGECACHE *pagecache,
if (! (type == FLUSH_KEEP || type == FLUSH_KEEP_LAZY ||
type == FLUSH_FORCE_WRITE))
{
- pagecache->blocks_changed--;
- pagecache->global_blocks_changed--;
- free_block(pagecache, block);
+ if (!free_block(pagecache, block, 1))
+ {
+ pagecache->blocks_changed--;
+ pagecache->global_blocks_changed--;
+ }
+ else
+ {
+ block->status&= ~PCBLOCK_IN_FLUSH;
+ link_to_file_list(pagecache, block, file, 1);
+ }
}
else
{
@@ -4663,7 +4695,7 @@ restart:
/* It's a temporary file */
pagecache->blocks_changed--;
pagecache->global_blocks_changed--;
- free_block(pagecache, block);
+ free_block(pagecache, block, 0);
}
}
else if (type != FLUSH_KEEP_LAZY)
@@ -4733,11 +4765,12 @@ restart:
#endif
next= block->next_changed;
if (block->hash_link->file.file == file->file &&
+ !block->pins &&
(! (block->status & PCBLOCK_CHANGED)
|| type == FLUSH_IGNORE_CHANGED))
{
reg_requests(pagecache, block, 1);
- free_block(pagecache, block);
+ free_block(pagecache, block, 1);
}
}
}