aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer/bufmgr.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2025-02-25 09:02:07 -0500
committerAndres Freund <andres@anarazel.de>2025-02-25 09:02:07 -0500
commit37c87e63f9e1a2d76db54fedcdf91d3895d200a6 (patch)
tree1289dd23f92391ef9ec5171b59f4ac76f2e14a02 /src/backend/storage/buffer/bufmgr.c
parent32c393f9f1f148febcd741e7067e9537825587cc (diff)
downloadpostgresql-37c87e63f9e1a2d76db54fedcdf91d3895d200a6.tar.gz
postgresql-37c87e63f9e1a2d76db54fedcdf91d3895d200a6.zip
Change relpath() et al to return path by value
For AIO, and also some other recent patches, we need the ability to call relpath() in a critical section. Until now that was not feasible, as it allocated memory. The fact that relpath() allocated memory also made it awkward to use in log messages because we had to take care to free the memory afterwards. Which we e.g. didn't do for when zeroing out an invalid buffer. We discussed other solutions, e.g. filling a pre-allocated buffer that's passed to relpath(), but they all came with plenty downsides or were larger projects. The easiest fix seems to be to make relpath() return the path by value. To be able to return the path by value we need to determine the maximum length of a relation path. This patch adds a long #define that computes the exact maximum, which is verified to be correct in a regression test. As this change the signature of relpath(), extensions using it will need to adapt their code. We discussed leaving a backward-compat shim in place, but decided it's not worth it given the use of relpath() doesn't seem widespread. Discussion: https://postgr.es/m/xeri5mla4b5syjd5a25nok5iez2kr3bm26j2qn4u7okzof2bmf@kwdh2vf7npra
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r--src/backend/storage/buffer/bufmgr.c48
1 files changed, 18 insertions, 30 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index d3216ef6ba7..40e9efec312 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1541,7 +1541,7 @@ WaitReadBuffers(ReadBuffersOperation *operation)
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page in block %u of relation %s; zeroing out page",
io_first_block + j,
- relpath(operation->smgr->smgr_rlocator, forknum))));
+ relpath(operation->smgr->smgr_rlocator, forknum).str)));
memset(bufBlock, 0, BLCKSZ);
}
else
@@ -1549,7 +1549,7 @@ WaitReadBuffers(ReadBuffersOperation *operation)
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("invalid page in block %u of relation %s",
io_first_block + j,
- relpath(operation->smgr->smgr_rlocator, forknum))));
+ relpath(operation->smgr->smgr_rlocator, forknum).str)));
}
/* Terminate I/O and set BM_VALID. */
@@ -2284,7 +2284,7 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("cannot extend relation %s beyond %u blocks",
- relpath(bmr.smgr->smgr_rlocator, fork),
+ relpath(bmr.smgr->smgr_rlocator, fork).str,
MaxBlockNumber)));
/*
@@ -2355,7 +2355,8 @@ ExtendBufferedRelShared(BufferManagerRelation bmr,
if (valid && !PageIsNew((Page) buf_block))
ereport(ERROR,
(errmsg("unexpected data beyond EOF in block %u of relation %s",
- existing_hdr->tag.blockNum, relpath(bmr.smgr->smgr_rlocator, fork)),
+ existing_hdr->tag.blockNum,
+ relpath(bmr.smgr->smgr_rlocator, fork).str),
errhint("This has been seen to occur with buggy kernels; consider updating your system.")));
/*
@@ -3663,7 +3664,6 @@ DebugPrintBufferRefcount(Buffer buffer)
{
BufferDesc *buf;
int32 loccount;
- char *path;
char *result;
ProcNumber backend;
uint32 buf_state;
@@ -3683,15 +3683,14 @@ DebugPrintBufferRefcount(Buffer buffer)
}
/* theoretically we should lock the bufhdr here */
- path = relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
- BufTagGetForkNum(&buf->tag));
buf_state = pg_atomic_read_u32(&buf->state);
result = psprintf("[%03d] (rel=%s, blockNum=%u, flags=0x%x, refcount=%u %d)",
- buffer, path,
+ buffer,
+ relpathbackend(BufTagGetRelFileLocator(&buf->tag), backend,
+ BufTagGetForkNum(&buf->tag)).str,
buf->tag.blockNum, buf_state & BUF_FLAG_MASK,
BUF_STATE_GET_REFCOUNT(buf_state), loccount);
- pfree(path);
return result;
}
@@ -5611,16 +5610,13 @@ AbortBufferIO(Buffer buffer)
if (buf_state & BM_IO_ERROR)
{
/* Buffer is pinned, so we can read tag without spinlock */
- char *path;
-
- path = relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
- BufTagGetForkNum(&buf_hdr->tag));
ereport(WARNING,
(errcode(ERRCODE_IO_ERROR),
errmsg("could not write block %u of %s",
- buf_hdr->tag.blockNum, path),
+ buf_hdr->tag.blockNum,
+ relpathperm(BufTagGetRelFileLocator(&buf_hdr->tag),
+ BufTagGetForkNum(&buf_hdr->tag)).str),
errdetail("Multiple failures --- write error might be permanent.")));
- pfree(path);
}
}
@@ -5637,14 +5633,10 @@ shared_buffer_write_error_callback(void *arg)
/* Buffer is pinned, so we can read the tag without locking the spinlock */
if (bufHdr != NULL)
- {
- char *path = relpathperm(BufTagGetRelFileLocator(&bufHdr->tag),
- BufTagGetForkNum(&bufHdr->tag));
-
errcontext("writing block %u of relation %s",
- bufHdr->tag.blockNum, path);
- pfree(path);
- }
+ bufHdr->tag.blockNum,
+ relpathperm(BufTagGetRelFileLocator(&bufHdr->tag),
+ BufTagGetForkNum(&bufHdr->tag)).str);
}
/*
@@ -5656,15 +5648,11 @@ local_buffer_write_error_callback(void *arg)
BufferDesc *bufHdr = (BufferDesc *) arg;
if (bufHdr != NULL)
- {
- char *path = relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
- MyProcNumber,
- BufTagGetForkNum(&bufHdr->tag));
-
errcontext("writing block %u of relation %s",
- bufHdr->tag.blockNum, path);
- pfree(path);
- }
+ bufHdr->tag.blockNum,
+ relpathbackend(BufTagGetRelFileLocator(&bufHdr->tag),
+ MyProcNumber,
+ BufTagGetForkNum(&bufHdr->tag)).str);
}
/*