Skip to content

Commit f3e5d86

Browse files
committed
Prevent creating a boatload of empty segments when md.c is asked to
access a ridiculously large block number within a relation.
1 parent b54faa1 commit f3e5d86

File tree

1 file changed

+25
-7
lines changed
  • src/backend/storage/smgr

1 file changed

+25
-7
lines changed

src/backend/storage/smgr/md.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.72 2000/06/28 03:32:14 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.73 2000/07/10 04:32:00 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -714,9 +714,16 @@ mdnblocks(Relation reln)
714714

715715
if (v->mdfd_chain == (MdfdVec *) NULL)
716716
{
717+
/*
718+
* Because we pass O_CREAT, we will create the next segment
719+
* (with zero length) immediately, if the last segment is of
720+
* length REL_SEGSIZE. This is unnecessary but harmless, and
721+
* testing for the case would take more cycles than it seems
722+
* worth.
723+
*/
717724
v->mdfd_chain = _mdfd_openseg(reln, segno, O_CREAT);
718725
if (v->mdfd_chain == (MdfdVec *) NULL)
719-
elog(ERROR, "cannot count blocks for %s -- open failed",
726+
elog(ERROR, "cannot count blocks for %s -- open failed: %m",
720727
RelationGetRelationName(reln));
721728
}
722729

@@ -1038,11 +1045,20 @@ _mdfd_getseg(Relation reln, int blkno)
10381045

10391046
if (v->mdfd_chain == (MdfdVec *) NULL)
10401047
{
1041-
v->mdfd_chain = _mdfd_openseg(reln, i, O_CREAT);
1048+
/*
1049+
* We will create the next segment only if the target block
1050+
* is within it. This prevents Sorcerer's Apprentice syndrome
1051+
* if a bug at higher levels causes us to be handed a ridiculously
1052+
* large blkno --- otherwise we could create many thousands of
1053+
* empty segment files before reaching the "target" block. We
1054+
* should never need to create more than one new segment per call,
1055+
* so this restriction seems reasonable.
1056+
*/
1057+
v->mdfd_chain = _mdfd_openseg(reln, i, (segno == 1) ? O_CREAT : 0);
10421058

10431059
if (v->mdfd_chain == (MdfdVec *) NULL)
1044-
elog(ERROR, "cannot open segment %d of relation %s",
1045-
i, RelationGetRelationName(reln));
1060+
elog(ERROR, "cannot open segment %d of relation %s (target block %d): %m",
1061+
i, RelationGetRelationName(reln), blkno);
10461062
}
10471063
v = v->mdfd_chain;
10481064
}
@@ -1060,8 +1076,10 @@ _mdfd_getseg(Relation reln, int blkno)
10601076
* "blind" with no Relation struct. We assume that we are not likely to
10611077
* touch the same relation again soon, so we do not create an FD entry for
10621078
* the relation --- we just open a kernel file descriptor which will be
1063-
* used and promptly closed. The return value is the kernel descriptor,
1064-
* or -1 on failure.
1079+
* used and promptly closed. We also assume that the target block already
1080+
* exists, ie, we need not extend the relation.
1081+
*
1082+
* The return value is the kernel descriptor, or -1 on failure.
10651083
*/
10661084

10671085
static int

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy