diff options
Diffstat (limited to 'src/backend/storage/smgr/md.c')
-rw-r--r-- | src/backend/storage/smgr/md.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 4a897a83593..11fccda475f 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -1154,19 +1154,21 @@ mdnblocks(SMgrRelation reln, ForkNumber forknum) /* * mdtruncate() -- Truncate relation to specified number of blocks. + * + * Guaranteed not to allocate memory, so it can be used in a critical section. + * Caller must have called smgrnblocks() to obtain curnblk while holding a + * sufficient lock to prevent a change in relation size, and not used any smgr + * functions for this relation or handled interrupts in between. This makes + * sure we have opened all active segments, so that truncate loop will get + * them all! */ void -mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks) +mdtruncate(SMgrRelation reln, ForkNumber forknum, + BlockNumber curnblk, BlockNumber nblocks) { - BlockNumber curnblk; BlockNumber priorblocks; int curopensegs; - /* - * NOTE: mdnblocks makes sure we have opened all active segments, so that - * truncation loop will get them all! - */ - curnblk = mdnblocks(reln, forknum); if (nblocks > curnblk) { /* Bogus request ... but no complaint if InRecovery */ @@ -1505,7 +1507,7 @@ _fdvec_resize(SMgrRelation reln, reln->md_seg_fds[forknum] = MemoryContextAlloc(MdCxt, sizeof(MdfdVec) * nseg); } - else + else if (nseg > reln->md_num_open_segs[forknum]) { /* * It doesn't seem worthwhile complicating the code to amortize @@ -1517,6 +1519,16 @@ _fdvec_resize(SMgrRelation reln, repalloc(reln->md_seg_fds[forknum], sizeof(MdfdVec) * nseg); } + else + { + /* + * We don't reallocate a smaller array, because we want mdtruncate() + * to be able to promise that it won't allocate memory, so that it is + * allowed in a critical section. This means that a bit of space in + * the array is now wasted, until the next time we add a segment and + * reallocate. + */ + } reln->md_num_open_segs[forknum] = nseg; } |