diff options
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/storage/smgr.h | 36 | ||||
| -rw-r--r-- | src/include/utils/rel.h | 18 | ||||
| -rw-r--r-- | src/include/utils/relcache.h | 2 |
3 files changed, 24 insertions, 32 deletions
diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h index 527cd2a0568..8d90d1f8e22 100644 --- a/src/include/storage/smgr.h +++ b/src/include/storage/smgr.h @@ -21,29 +21,21 @@ /* * smgr.c maintains a table of SMgrRelation objects, which are essentially * cached file handles. An SMgrRelation is created (if not already present) - * by smgropen(), and destroyed by smgrclose(). Note that neither of these - * operations imply I/O, they just create or destroy a hashtable entry. - * (But smgrclose() may release associated resources, such as OS-level file + * by smgropen(), and destroyed by smgrdestroy(). Note that neither of these + * operations imply I/O, they just create or destroy a hashtable entry. (But + * smgrdestroy() may release associated resources, such as OS-level file * descriptors.) * - * An SMgrRelation may have an "owner", which is just a pointer to it from - * somewhere else; smgr.c will clear this pointer if the SMgrRelation is - * closed. We use this to avoid dangling pointers from relcache to smgr - * 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. + * An SMgrRelation may be "pinned", to prevent it from being destroyed while + * it's in use. We use this to prevent pointers relcache to smgr from being + * invalidated. SMgrRelations that are not pinned are deleted at end of + * transaction. */ typedef struct SMgrRelationData { /* rlocator is the hashtable lookup key, so it must be first! */ RelFileLocatorBackend smgr_rlocator; /* relation physical identifier */ - /* pointer to owning pointer, or NULL if none */ - struct SMgrRelationData **smgr_owner; - /* * The following fields are reset to InvalidBlockNumber upon a cache flush * event, and hold the last known size for each fork. This information is @@ -68,7 +60,11 @@ typedef struct SMgrRelationData int md_num_open_segs[MAX_FORKNUM + 1]; struct _MdfdVec *md_seg_fds[MAX_FORKNUM + 1]; - /* if unowned, list link in list of all unowned SMgrRelations */ + /* + * Pinning support. If unpinned (ie. pincount == 0), 'node' is a list + * link in list of all unpinned SMgrRelations. + */ + int pincount; dlist_node node; } SMgrRelationData; @@ -80,13 +76,13 @@ typedef SMgrRelationData *SMgrRelation; extern void smgrinit(void); extern SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend); extern bool smgrexists(SMgrRelation reln, ForkNumber forknum); -extern void smgrsetowner(SMgrRelation *owner, SMgrRelation reln); -extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln); +extern void smgrpin(SMgrRelation reln); +extern void smgrunpin(SMgrRelation reln); extern void smgrclose(SMgrRelation reln); -extern void smgrcloseall(void); -extern void smgrcloserellocator(RelFileLocatorBackend rlocator); +extern void smgrdestroyall(void); extern void smgrrelease(SMgrRelation reln); extern void smgrreleaseall(void); +extern void smgrreleaserellocator(RelFileLocatorBackend rlocator); extern void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo); extern void smgrdosyncall(SMgrRelation *rels, int nrels); extern void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo); diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index a584b1ddff3..ab9fa4faf9f 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -561,18 +561,15 @@ typedef struct ViewOptions * * Very little code is authorized to touch rel->rd_smgr directly. Instead * use this function to fetch its value. - * - * Note: since a relcache flush can cause the file handle to be closed again, - * it's unwise to hold onto the pointer returned by this function for any - * long period. Recommended practice is to just re-execute RelationGetSmgr - * each time you need to access the SMgrRelation. It's quite cheap in - * comparison to whatever an smgr function is going to do. */ static inline SMgrRelation RelationGetSmgr(Relation rel) { if (unlikely(rel->rd_smgr == NULL)) - smgrsetowner(&(rel->rd_smgr), smgropen(rel->rd_locator, rel->rd_backend)); + { + rel->rd_smgr = smgropen(rel->rd_locator, rel->rd_backend); + smgrpin(rel->rd_smgr); + } return rel->rd_smgr; } @@ -584,10 +581,11 @@ static inline void RelationCloseSmgr(Relation relation) { if (relation->rd_smgr != NULL) + { + smgrunpin(relation->rd_smgr); smgrclose(relation->rd_smgr); - - /* smgrclose should unhook from owner pointer */ - Assert(relation->rd_smgr == NULL); + relation->rd_smgr = NULL; + } } #endif /* !FRONTEND */ diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index 058da62a726..18c32ea7008 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -129,8 +129,6 @@ extern void RelationCacheInvalidateEntry(Oid relationId); extern void RelationCacheInvalidate(bool debug_discard); -extern void RelationCloseSmgrByOid(Oid relationId); - #ifdef USE_ASSERT_CHECKING extern void AssertPendingSyncs_RelationCache(void); #else |
