aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xact.c5
-rw-r--r--src/backend/postmaster/bgwriter.c1
-rw-r--r--src/backend/postmaster/checkpointer.c1
-rw-r--r--src/backend/postmaster/walwriter.c1
-rw-r--r--src/backend/storage/smgr/smgr.c80
-rw-r--r--src/include/storage/smgr.h7
6 files changed, 92 insertions, 3 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index e7a6606ec3b..c24df3f38c2 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -1949,7 +1949,7 @@ CommitTransaction(void)
AtEOXact_SPI(true);
AtEOXact_on_commit_actions(true);
AtEOXact_Namespace(true);
- /* smgrcommit already done */
+ AtEOXact_SMgr();
AtEOXact_Files();
AtEOXact_ComboCid();
AtEOXact_HashTables(true);
@@ -2202,7 +2202,7 @@ PrepareTransaction(void)
AtEOXact_SPI(true);
AtEOXact_on_commit_actions(true);
AtEOXact_Namespace(true);
- /* smgrcommit already done */
+ AtEOXact_SMgr();
AtEOXact_Files();
AtEOXact_ComboCid();
AtEOXact_HashTables(true);
@@ -2348,6 +2348,7 @@ AbortTransaction(void)
AtEOXact_SPI(false);
AtEOXact_on_commit_actions(false);
AtEOXact_Namespace(false);
+ AtEOXact_SMgr();
AtEOXact_Files();
AtEOXact_ComboCid();
AtEOXact_HashTables(false);
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 748fd85edb0..709ccf1f256 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -183,6 +183,7 @@ BackgroundWriterMain(void)
false, true);
/* we needn't bother with the other ResourceOwnerRelease phases */
AtEOXact_Buffers(false);
+ AtEOXact_SMgr();
AtEOXact_Files();
AtEOXact_HashTables(false);
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index c5f32059a79..18e6a4e8c4b 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -291,6 +291,7 @@ CheckpointerMain(void)
false, true);
/* we needn't bother with the other ResourceOwnerRelease phases */
AtEOXact_Buffers(false);
+ AtEOXact_SMgr();
AtEOXact_Files();
AtEOXact_HashTables(false);
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 43139017c27..c3e15ef7595 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -188,6 +188,7 @@ WalWriterMain(void)
false, true);
/* we needn't bother with the other ResourceOwnerRelease phases */
AtEOXact_Buffers(false);
+ AtEOXact_SMgr();
AtEOXact_Files();
AtEOXact_HashTables(false);
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 6319d1e8589..5dff8b3702e 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -76,11 +76,15 @@ static const int NSmgr = lengthof(smgrsw);
/*
* Each backend has a hashtable that stores all extant SMgrRelation objects.
+ * In addition, "unowned" SMgrRelation objects are chained together in a list.
*/
static HTAB *SMgrRelationHash = NULL;
+static SMgrRelation first_unowned_reln = NULL;
+
/* local function prototypes */
static void smgrshutdown(int code, Datum arg);
+static void remove_from_unowned_list(SMgrRelation reln);
/*
@@ -124,7 +128,7 @@ smgrshutdown(int code, Datum arg)
/*
* smgropen() -- Return an SMgrRelation object, creating it if need be.
*
- * This does not attempt to actually open the object.
+ * This does not attempt to actually open the underlying file.
*/
SMgrRelation
smgropen(RelFileNode rnode, BackendId backend)
@@ -144,6 +148,7 @@ smgropen(RelFileNode rnode, BackendId backend)
ctl.hash = tag_hash;
SMgrRelationHash = hash_create("smgr relation table", 400,
&ctl, HASH_ELEM | HASH_FUNCTION);
+ first_unowned_reln = NULL;
}
/* Look up or create an entry */
@@ -168,6 +173,10 @@ smgropen(RelFileNode rnode, BackendId backend)
/* mark it not open */
for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
reln->md_fd[forknum] = NULL;
+
+ /* place it at head of unowned list (to make smgrsetowner cheap) */
+ reln->next_unowned_reln = first_unowned_reln;
+ first_unowned_reln = reln;
}
return reln;
@@ -182,14 +191,22 @@ smgropen(RelFileNode rnode, BackendId backend)
void
smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
{
+ /* We don't currently support "disowning" an SMgrRelation here */
+ Assert(owner != NULL);
+
/*
* First, unhook any old owner. (Normally there shouldn't be any, but it
* seems possible that this can happen during swap_relation_files()
* depending on the order of processing. It's ok to close the old
* relcache entry early in that case.)
+ *
+ * If there isn't an old owner, then the reln should be in the unowned
+ * list, and we need to remove it.
*/
if (reln->smgr_owner)
*(reln->smgr_owner) = NULL;
+ else
+ remove_from_unowned_list(reln);
/* Now establish the ownership relationship. */
reln->smgr_owner = owner;
@@ -197,6 +214,38 @@ smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
}
/*
+ * remove_from_unowned_list -- unlink an SMgrRelation from the unowned list
+ *
+ * If the reln is not present in the list, nothing happens. Typically this
+ * would be caller error, but there seems no reason to throw an error.
+ *
+ * In the worst case this could be rather slow; but in all the cases that seem
+ * likely to be performance-critical, the reln being sought will actually be
+ * first in the list. Furthermore, the number of unowned relns touched in any
+ * one transaction shouldn't be all that high typically. So it doesn't seem
+ * worth expending the additional space and management logic needed for a
+ * doubly-linked list.
+ */
+static void
+remove_from_unowned_list(SMgrRelation reln)
+{
+ SMgrRelation *link;
+ SMgrRelation cur;
+
+ for (link = &first_unowned_reln, cur = *link;
+ cur != NULL;
+ link = &cur->next_unowned_reln, cur = *link)
+ {
+ if (cur == reln)
+ {
+ *link = cur->next_unowned_reln;
+ cur->next_unowned_reln = NULL;
+ break;
+ }
+ }
+}
+
+/*
* smgrexists() -- Does the underlying file for a fork exist?
*/
bool
@@ -219,6 +268,9 @@ smgrclose(SMgrRelation reln)
owner = reln->smgr_owner;
+ if (!owner)
+ remove_from_unowned_list(reln);
+
if (hash_search(SMgrRelationHash,
(void *) &(reln->smgr_rnode),
HASH_REMOVE, NULL) == NULL)
@@ -600,3 +652,29 @@ smgrpostckpt(void)
(*(smgrsw[i].smgr_post_ckpt)) ();
}
}
+
+/*
+ * AtEOXact_SMgr
+ *
+ * This routine is called during transaction commit or abort (it doesn't
+ * particularly care which). All transient SMgrRelation objects are closed.
+ *
+ * We do this as a compromise between wanting transient SMgrRelations to
+ * live awhile (to amortize the costs of blind writes of multiple blocks)
+ * and needing them to not live forever (since we're probably holding open
+ * a kernel file descriptor for the underlying file, and we need to ensure
+ * that gets closed reasonably soon if the file gets deleted).
+ */
+void
+AtEOXact_SMgr(void)
+{
+ /*
+ * Zap all unowned SMgrRelations. We rely on smgrclose() to remove each
+ * one from the list.
+ */
+ while (first_unowned_reln != NULL)
+ {
+ Assert(first_unowned_reln->smgr_owner == NULL);
+ smgrclose(first_unowned_reln);
+ }
+}
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h
index 92b9198d542..9eccf7671ed 100644
--- a/src/include/storage/smgr.h
+++ b/src/include/storage/smgr.h
@@ -33,6 +33,9 @@
* without having to make the smgr explicitly aware of relcache. There
* can't be more than one "owner" pointer per SMgrRelation, but that's
* all we need.
+ *
+ * SMgrRelations that do not have an "owner" are considered to be transient,
+ * and are deleted at end of transaction.
*/
typedef struct SMgrRelationData
{
@@ -63,6 +66,9 @@ typedef struct SMgrRelationData
/* for md.c; NULL for forks that are not open */
struct _MdfdVec *md_fd[MAX_FORKNUM + 1];
+
+ /* if unowned, list link in list of all unowned SMgrRelations */
+ struct SMgrRelationData *next_unowned_reln;
} SMgrRelationData;
typedef SMgrRelationData *SMgrRelation;
@@ -95,6 +101,7 @@ extern void smgrimmedsync(SMgrRelation reln, ForkNumber forknum);
extern void smgrpreckpt(void);
extern void smgrsync(void);
extern void smgrpostckpt(void);
+extern void AtEOXact_SMgr(void);
/* internals: move me elsewhere -- ay 7/94 */