aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-07-10 04:32:00 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-07-10 04:32:00 +0000
commitf3e5d8620c7c2fa7ca5a1a8cc969c08856756c9d (patch)
tree8d442d7093faada4d1a683213aa5befa277af5d6
parentb54faa1b15c9dea37d79995063a4e7d83e0159d3 (diff)
downloadpostgresql-f3e5d8620c7c2fa7ca5a1a8cc969c08856756c9d.tar.gz
postgresql-f3e5d8620c7c2fa7ca5a1a8cc969c08856756c9d.zip
Prevent creating a boatload of empty segments when md.c is asked to
access a ridiculously large block number within a relation.
-rw-r--r--src/backend/storage/smgr/md.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index de51e703f8b..5baf6935d0a 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.72 2000/06/28 03:32:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.73 2000/07/10 04:32:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -714,9 +714,16 @@ mdnblocks(Relation reln)
if (v->mdfd_chain == (MdfdVec *) NULL)
{
+ /*
+ * Because we pass O_CREAT, we will create the next segment
+ * (with zero length) immediately, if the last segment is of
+ * length REL_SEGSIZE. This is unnecessary but harmless, and
+ * testing for the case would take more cycles than it seems
+ * worth.
+ */
v->mdfd_chain = _mdfd_openseg(reln, segno, O_CREAT);
if (v->mdfd_chain == (MdfdVec *) NULL)
- elog(ERROR, "cannot count blocks for %s -- open failed",
+ elog(ERROR, "cannot count blocks for %s -- open failed: %m",
RelationGetRelationName(reln));
}
@@ -1038,11 +1045,20 @@ _mdfd_getseg(Relation reln, int blkno)
if (v->mdfd_chain == (MdfdVec *) NULL)
{
- v->mdfd_chain = _mdfd_openseg(reln, i, O_CREAT);
+ /*
+ * We will create the next segment only if the target block
+ * is within it. This prevents Sorcerer's Apprentice syndrome
+ * if a bug at higher levels causes us to be handed a ridiculously
+ * large blkno --- otherwise we could create many thousands of
+ * empty segment files before reaching the "target" block. We
+ * should never need to create more than one new segment per call,
+ * so this restriction seems reasonable.
+ */
+ v->mdfd_chain = _mdfd_openseg(reln, i, (segno == 1) ? O_CREAT : 0);
if (v->mdfd_chain == (MdfdVec *) NULL)
- elog(ERROR, "cannot open segment %d of relation %s",
- i, RelationGetRelationName(reln));
+ elog(ERROR, "cannot open segment %d of relation %s (target block %d): %m",
+ i, RelationGetRelationName(reln), blkno);
}
v = v->mdfd_chain;
}
@@ -1060,8 +1076,10 @@ _mdfd_getseg(Relation reln, int blkno)
* "blind" with no Relation struct. We assume that we are not likely to
* touch the same relation again soon, so we do not create an FD entry for
* the relation --- we just open a kernel file descriptor which will be
- * used and promptly closed. The return value is the kernel descriptor,
- * or -1 on failure.
+ * used and promptly closed. We also assume that the target block already
+ * exists, ie, we need not extend the relation.
+ *
+ * The return value is the kernel descriptor, or -1 on failure.
*/
static int