@@ -493,7 +493,8 @@ static my_bool info_check_lock(PAGECACHE_BLOCK_LINK *block,
493
493
494
494
#define FLUSH_CACHE 2000 /* sort this many blocks at once */
495
495
496
- static void free_block (PAGECACHE * pagecache , PAGECACHE_BLOCK_LINK * block );
496
+ static my_bool free_block (PAGECACHE * pagecache , PAGECACHE_BLOCK_LINK * block ,
497
+ my_bool abort_if_pinned );
497
498
static void unlink_hash (PAGECACHE * pagecache , PAGECACHE_HASH_LINK * hash_link );
498
499
#ifndef DBUG_OFF
499
500
static void test_key_cache (PAGECACHE * pagecache ,
@@ -1939,7 +1940,7 @@ static PAGECACHE_BLOCK_LINK *find_block(PAGECACHE *pagecache,
1939
1940
removed from the cache as we set the PCBLOCK_REASSIGNED
1940
1941
flag (see the code below that handles reading requests).
1941
1942
*/
1942
- free_block (pagecache , block );
1943
+ free_block (pagecache , block , 0 );
1943
1944
return 0 ;
1944
1945
}
1945
1946
/* Wait until the page is flushed on disk */
@@ -1950,7 +1951,7 @@ static PAGECACHE_BLOCK_LINK *find_block(PAGECACHE *pagecache,
1950
1951
/* Invalidate page in the block if it has not been done yet */
1951
1952
DBUG_ASSERT (block -> status ); /* Should always be true */
1952
1953
if (block -> status )
1953
- free_block (pagecache , block );
1954
+ free_block (pagecache , block , 0 );
1954
1955
return 0 ;
1955
1956
}
1956
1957
@@ -1975,8 +1976,13 @@ static PAGECACHE_BLOCK_LINK *find_block(PAGECACHE *pagecache,
1975
1976
}
1976
1977
else
1977
1978
{
1978
- DBUG_ASSERT (hash_link -> requests > 0 );
1979
- hash_link -> requests -- ;
1979
+ /*
1980
+ When we come here either PCBLOCK_REASSIGNED or PCBLOCK_IN_SWITCH are
1981
+ active. In both cases wqueue_release_queue() is called when the
1982
+ state changes.
1983
+ */
1984
+ DBUG_ASSERT (block -> hash_link == hash_link );
1985
+ remove_reader (block );
1980
1986
KEYCACHE_DBUG_PRINT ("find_block" ,
1981
1987
("request waiting for old page to be saved" ));
1982
1988
{
@@ -3635,7 +3641,7 @@ static my_bool pagecache_delete_internal(PAGECACHE *pagecache,
3635
3641
DBUG_ASSERT (block -> hash_link -> requests > 0 );
3636
3642
page_link -> requests -- ;
3637
3643
/* See NOTE for pagecache_unlock() about registering requests. */
3638
- free_block (pagecache , block );
3644
+ free_block (pagecache , block , 0 );
3639
3645
dec_counter_for_resize_op (pagecache );
3640
3646
return 0 ;
3641
3647
@@ -4227,7 +4233,8 @@ my_bool pagecache_write_part(PAGECACHE *pagecache,
4227
4233
and add it to the free list.
4228
4234
*/
4229
4235
4230
- static void free_block (PAGECACHE * pagecache , PAGECACHE_BLOCK_LINK * block )
4236
+ static my_bool free_block (PAGECACHE * pagecache , PAGECACHE_BLOCK_LINK * block ,
4237
+ my_bool abort_if_pinned )
4231
4238
{
4232
4239
uint status = block -> status ;
4233
4240
KEYCACHE_THREAD_TRACE ("free block" );
@@ -4241,11 +4248,27 @@ static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
4241
4248
/*
4242
4249
While waiting for readers to finish, new readers might request the
4243
4250
block. But since we set block->status|= PCBLOCK_REASSIGNED, they
4244
- will wait on block->wqueue[COND_FOR_SAVED]. They must be signalled
4251
+ will wait on block->wqueue[COND_FOR_SAVED]. They must be signaled
4245
4252
later.
4246
4253
*/
4247
4254
block -> status |= PCBLOCK_REASSIGNED ;
4248
4255
wait_for_readers (pagecache , block );
4256
+ if (unlikely (abort_if_pinned ) && unlikely (block -> pins ))
4257
+ {
4258
+ /*
4259
+ Block got pinned while waiting for readers.
4260
+ This can only happens when called from flush_pagecache_blocks_int()
4261
+ when flushing blocks as part of prepare for maria_close() or from
4262
+ flush_cached_blocks()
4263
+ */
4264
+ block -> status &= ~PCBLOCK_REASSIGNED ;
4265
+ unreg_request (pagecache , block , 0 );
4266
+
4267
+ /* All pending requests for this page must be resubmitted. */
4268
+ if (block -> wqueue [COND_FOR_SAVED ].last_thread )
4269
+ wqueue_release_queue (& block -> wqueue [COND_FOR_SAVED ]);
4270
+ return 1 ;
4271
+ }
4249
4272
unlink_hash (pagecache , block -> hash_link );
4250
4273
}
4251
4274
@@ -4296,6 +4319,8 @@ static void free_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block)
4296
4319
/* All pending requests for this page must be resubmitted. */
4297
4320
if (block -> wqueue [COND_FOR_SAVED ].last_thread )
4298
4321
wqueue_release_queue (& block -> wqueue [COND_FOR_SAVED ]);
4322
+
4323
+ return 0 ;
4299
4324
}
4300
4325
4301
4326
@@ -4431,9 +4456,16 @@ static int flush_cached_blocks(PAGECACHE *pagecache,
4431
4456
if (! (type == FLUSH_KEEP || type == FLUSH_KEEP_LAZY ||
4432
4457
type == FLUSH_FORCE_WRITE ))
4433
4458
{
4434
- pagecache -> blocks_changed -- ;
4435
- pagecache -> global_blocks_changed -- ;
4436
- free_block (pagecache , block );
4459
+ if (!free_block (pagecache , block , 1 ))
4460
+ {
4461
+ pagecache -> blocks_changed -- ;
4462
+ pagecache -> global_blocks_changed -- ;
4463
+ }
4464
+ else
4465
+ {
4466
+ block -> status &= ~PCBLOCK_IN_FLUSH ;
4467
+ link_to_file_list (pagecache , block , file , 1 );
4468
+ }
4437
4469
}
4438
4470
else
4439
4471
{
@@ -4671,7 +4703,7 @@ static int flush_pagecache_blocks_int(PAGECACHE *pagecache,
4671
4703
/* It's a temporary file */
4672
4704
pagecache -> blocks_changed -- ;
4673
4705
pagecache -> global_blocks_changed -- ;
4674
- free_block (pagecache , block );
4706
+ free_block (pagecache , block , 0 );
4675
4707
}
4676
4708
}
4677
4709
else if (type != FLUSH_KEEP_LAZY )
@@ -4741,11 +4773,12 @@ static int flush_pagecache_blocks_int(PAGECACHE *pagecache,
4741
4773
#endif
4742
4774
next = block -> next_changed ;
4743
4775
if (block -> hash_link -> file .file == file -> file &&
4776
+ !block -> pins &&
4744
4777
(! (block -> status & PCBLOCK_CHANGED )
4745
4778
|| type == FLUSH_IGNORE_CHANGED ))
4746
4779
{
4747
4780
reg_requests (pagecache , block , 1 );
4748
- free_block (pagecache , block );
4781
+ free_block (pagecache , block , 1 );
4749
4782
}
4750
4783
}
4751
4784
}
0 commit comments