From: | Andres Freund <andres(at)anarazel(dot)de> |
---|---|
To: | Thomas Munro <thomas(dot)munro(at)gmail(dot)com> |
Cc: | pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>, Tomas Vondra <tomas(at)vondra(dot)me> |
Subject: | Re: Allow io_combine_limit up to 1MB |
Date: | 2025-04-25 14:15:55 |
Message-ID: | c5jyqnuwrpigd35qe7xdypxsisdjrdba5iw63mhcse4mzjogxo@qdjpv22z763f |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Hi,
On 2025-03-18 16:18:17 +1300, Thomas Munro wrote:
> Here's a new version that also adjusts the code that just landed in
> da722699:
Something isn't quite right with this code. If I just add -c
io_combine_limit=32 to the options and do a seqscan, I get odd
failures. Mostly assertion failures about buffers not being valid in
CheckReadBuffersOperation().
Sure glad I added CheckReadBuffersOperation(), that'd have been much nastier
to figure out without those assertion failures.
A bit of debugging later: Ie figured out that this is because io_combine_limit
is bigger than io_max_combine_limit, so the iovecs of one IO overlap with
another. With predictably hilarious results.
I think it might be a small thing:
Since our GUC system doesn't support dependencies or cross-checks
between GUCs, the user-settable one now assigns a "raw" value to
io_combine_limit_guc, and the lower of io_combine_limit_guc and
io_max_combine_limit is maintained in io_combine_limit.
However, the IO combine limit GUC still references io_combine_limit:
{
{"io_combine_limit",
PGC_USERSET,
RESOURCES_IO,
gettext_noop("Limit on the size of data reads and writes."),
NULL,
GUC_UNIT_BLOCKS
},
&io_combine_limit,
DEFAULT_IO_COMBINE_LIMIT,
1, MAX_IO_COMBINE_LIMIT,
NULL, assign_io_combine_limit, NULL
},
Therefore the GUC machinery undoes the work of io_combine_limit done in
assign_io_combine_limit:
/*
* GUC assign hooks that recompute io_combine_limit whenever
* io_combine_limit_guc and io_max_combine_limit are changed. These are needed
* because the GUC subsystem doesn't support dependencies between GUCs, and
* they may be assigned in either order.
*/
void
assign_io_max_combine_limit(int newval, void *extra)
{
io_max_combine_limit = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
void
assign_io_combine_limit(int newval, void *extra)
{
io_combine_limit_guc = newval;
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
}
So we end up with a larger io_combine_limit than
io_max_combine_limit. Hilarity ensues.
Besides the obvious fix, I think we should also add
Assert(len <= io_max_combine_limit);
to pgaio_io_set_handle_data_32/64, that'd have made the bug much more obvious.
Greetings,
Andres Freund
From | Date | Subject | |
---|---|---|---|
Next Message | Tom Lane | 2025-04-25 14:26:09 | Re: Allow io_combine_limit up to 1MB |
Previous Message | Daniel Gustafsson | 2025-04-25 14:04:29 | Re: Making sslrootcert=system work on Windows psql |