Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite273468

Browse files
committed
Fix read_stream.c for changing io_combine_limit.
In a couple of places, read_stream.c assumed that io_combine_limit wouldbe stable during the lifetime of a stream. That is not true in at leastone unusual case: streams held by CURSORs where you could change the GUCbetween FETCH commands, with unpredictable results.Fix, by storing stream->io_combine_limit and referring only to thatafter construction. This mirrors the treatment of the other importantsetting {effective,maintenance}_io_concurrency, which is stored instream->max_ios.One of the cases was the queue overflow space, which was sized forio_combine_limit and could be overrun if the GUC was increased. Sincethat coding was a little hard to follow, also introduce a variable forbetter readability instead of open-coding the arithmetic. Doing sorevealed an off-by-one thinko while clamping max_pinned_buffers toINT16_MAX, though that wasn't a live bug due to the current limits onGUC values.Back-patch to 17.Discussion:https://postgr.es/m/CA%2BhUKG%2B2T9p-%2BzM6Eeou-RAJjTML6eit1qn26f9twznX59qtCA%40mail.gmail.com
1 parent8b2392a commite273468

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

‎src/backend/storage/aio/read_stream.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ typedef struct InProgressIO
109109
structReadStream
110110
{
111111
int16max_ios;
112+
int16io_combine_limit;
112113
int16ios_in_progress;
113114
int16queue_size;
114115
int16max_pinned_buffers;
@@ -219,7 +220,7 @@ read_stream_start_pending_read(ReadStream *stream, bool suppress_advice)
219220

220221
/* This should only be called with a pending read. */
221222
Assert(stream->pending_read_nblocks>0);
222-
Assert(stream->pending_read_nblocks <=io_combine_limit);
223+
Assert(stream->pending_read_nblocks <=stream->io_combine_limit);
223224

224225
/* We had better not exceed the pin limit by starting this read. */
225226
Assert(stream->pinned_buffers+stream->pending_read_nblocks <=
@@ -307,7 +308,7 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
307308
int16buffer_index;
308309
void*per_buffer_data;
309310

310-
if (stream->pending_read_nblocks==io_combine_limit)
311+
if (stream->pending_read_nblocks==stream->io_combine_limit)
311312
{
312313
read_stream_start_pending_read(stream,suppress_advice);
313314
suppress_advice= false;
@@ -367,7 +368,7 @@ read_stream_look_ahead(ReadStream *stream, bool suppress_advice)
367368
* signaled end-of-stream, we start the read immediately.
368369
*/
369370
if (stream->pending_read_nblocks>0&&
370-
(stream->pending_read_nblocks==io_combine_limit||
371+
(stream->pending_read_nblocks==stream->io_combine_limit||
371372
(stream->pending_read_nblocks==stream->distance&&
372373
stream->pinned_buffers==0)||
373374
stream->distance==0)&&
@@ -396,6 +397,7 @@ read_stream_begin_relation(int flags,
396397
ReadStream*stream;
397398
size_tsize;
398399
int16queue_size;
400+
int16queue_overflow;
399401
intmax_ios;
400402
intstrategy_pin_limit;
401403
uint32max_pinned_buffers;
@@ -429,6 +431,14 @@ read_stream_begin_relation(int flags,
429431
/* Cap to INT16_MAX to avoid overflowing below */
430432
max_ios=Min(max_ios,PG_INT16_MAX);
431433

434+
/*
435+
* If starting a multi-block I/O near the end of the queue, we might
436+
* temporarily need extra space for overflowing buffers before they are
437+
* moved to regular circular position. This is the maximum extra space we
438+
* could need.
439+
*/
440+
queue_overflow=io_combine_limit-1;
441+
432442
/*
433443
* Choose the maximum number of buffers we're prepared to pin. We try to
434444
* pin fewer if we can, though. We clamp it to at least io_combine_limit
@@ -439,7 +449,7 @@ read_stream_begin_relation(int flags,
439449
*/
440450
max_pinned_buffers=Max(max_ios*4,io_combine_limit);
441451
max_pinned_buffers=Min(max_pinned_buffers,
442-
PG_INT16_MAX-io_combine_limit-1);
452+
PG_INT16_MAX-queue_overflow-1);
443453

444454
/* Give the strategy a chance to limit the number of buffers we pin. */
445455
strategy_pin_limit=GetAccessStrategyPinLimit(strategy);
@@ -465,18 +475,17 @@ read_stream_begin_relation(int flags,
465475
* one big chunk. Though we have queue_size buffers, we want to be able
466476
* to assume that all the buffers for a single read are contiguous (i.e.
467477
* don't wrap around halfway through), so we allow temporary overflows of
468-
* up to the maximum possible read size by allocating an extra
469-
* io_combine_limit - 1 elements.
478+
* up to the maximum possible overflow size.
470479
*/
471480
size= offsetof(ReadStream,buffers);
472-
size+=sizeof(Buffer)* (queue_size+io_combine_limit-1);
481+
size+=sizeof(Buffer)* (queue_size+queue_overflow);
473482
size+=sizeof(InProgressIO)*Max(1,max_ios);
474483
size+=per_buffer_data_size*queue_size;
475484
size+=MAXIMUM_ALIGNOF*2;
476485
stream= (ReadStream*)palloc(size);
477486
memset(stream,0, offsetof(ReadStream,buffers));
478487
stream->ios= (InProgressIO*)
479-
MAXALIGN(&stream->buffers[queue_size+io_combine_limit-1]);
488+
MAXALIGN(&stream->buffers[queue_size+queue_overflow]);
480489
if (per_buffer_data_size>0)
481490
stream->per_buffer_data= (void*)
482491
MAXALIGN(&stream->ios[Max(1,max_ios)]);
@@ -503,7 +512,14 @@ read_stream_begin_relation(int flags,
503512
if (max_ios==0)
504513
max_ios=1;
505514

515+
/*
516+
* Capture stable values for these two GUC-derived numbers for the
517+
* lifetime of this stream, so we don't have to worry about the GUCs
518+
* changing underneath us beyond this point.
519+
*/
506520
stream->max_ios=max_ios;
521+
stream->io_combine_limit=io_combine_limit;
522+
507523
stream->per_buffer_data_size=per_buffer_data_size;
508524
stream->max_pinned_buffers=max_pinned_buffers;
509525
stream->queue_size=queue_size;
@@ -517,7 +533,7 @@ read_stream_begin_relation(int flags,
517533
* doing full io_combine_limit sized reads (behavior B).
518534
*/
519535
if (flags&READ_STREAM_FULL)
520-
stream->distance=Min(max_pinned_buffers,io_combine_limit);
536+
stream->distance=Min(max_pinned_buffers,stream->io_combine_limit);
521537
else
522538
stream->distance=1;
523539

@@ -683,14 +699,14 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
683699
else
684700
{
685701
/* No advice; move towards io_combine_limit (behavior B). */
686-
if (stream->distance>io_combine_limit)
702+
if (stream->distance>stream->io_combine_limit)
687703
{
688704
stream->distance--;
689705
}
690706
else
691707
{
692708
distance=stream->distance*2;
693-
distance=Min(distance,io_combine_limit);
709+
distance=Min(distance,stream->io_combine_limit);
694710
distance=Min(distance,stream->max_pinned_buffers);
695711
stream->distance=distance;
696712
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp