Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit473320e

Browse files
committed
Close un-owned SMgrRelations at transaction end.
If an SMgrRelation is not "owned" by a relcache entry, don't allow it tolive past transaction end. This design allows the same SMgrRelation to beused for blind writes of multiple blocks during a transaction, but ensuresthat we don't hold onto such an SMgrRelation indefinitely. Because anSMgrRelation typically corresponds to open file descriptors at the fd.clevel, leaving it open when there's no corresponding relcache entry canmean that we prevent the kernel from reclaiming deleted disk space.(While CacheInvalidateSmgr messages usually fix that, there are caseswhere they're not issued, such as DROP DATABASE. We might want to addsome more sinval messaging for that, but I'd be inclined to keep thistype of logic anyway, since allowing VFDs to accumulate indefinitelyfor blind-written relations doesn't seem like a good idea.)This code replaces a previous attempt towards the same goal that provedto be unreliable. Back-patch to 9.1 where the previous patch was added.
1 parentcacb652 commit473320e

File tree

5 files changed

+91
-3
lines changed

5 files changed

+91
-3
lines changed

‎src/backend/access/transam/xact.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,7 +1917,7 @@ CommitTransaction(void)
19171917
AtEOXact_SPI(true);
19181918
AtEOXact_on_commit_actions(true);
19191919
AtEOXact_Namespace(true);
1920-
/* smgrcommit already done */
1920+
AtEOXact_SMgr();
19211921
AtEOXact_Files();
19221922
AtEOXact_ComboCid();
19231923
AtEOXact_HashTables(true);
@@ -2163,7 +2163,7 @@ PrepareTransaction(void)
21632163
AtEOXact_SPI(true);
21642164
AtEOXact_on_commit_actions(true);
21652165
AtEOXact_Namespace(true);
2166-
/* smgrcommit already done */
2166+
AtEOXact_SMgr();
21672167
AtEOXact_Files();
21682168
AtEOXact_ComboCid();
21692169
AtEOXact_HashTables(true);
@@ -2309,6 +2309,7 @@ AbortTransaction(void)
23092309
AtEOXact_SPI(false);
23102310
AtEOXact_on_commit_actions(false);
23112311
AtEOXact_Namespace(false);
2312+
AtEOXact_SMgr();
23122313
AtEOXact_Files();
23132314
AtEOXact_ComboCid();
23142315
AtEOXact_HashTables(false);

‎src/backend/postmaster/bgwriter.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ BackgroundWriterMain(void)
305305
false, true);
306306
/* we needn't bother with the other ResourceOwnerRelease phases */
307307
AtEOXact_Buffers(false);
308+
AtEOXact_SMgr();
308309
AtEOXact_Files();
309310
AtEOXact_HashTables(false);
310311

‎src/backend/postmaster/walwriter.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ WalWriterMain(void)
177177
false, true);
178178
/* we needn't bother with the other ResourceOwnerRelease phases */
179179
AtEOXact_Buffers(false);
180+
AtEOXact_SMgr();
180181
AtEOXact_Files();
181182
AtEOXact_HashTables(false);
182183

‎src/backend/storage/smgr/smgr.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,15 @@ static const int NSmgr = lengthof(smgrsw);
7878

7979
/*
8080
* Each backend has a hashtable that stores all extant SMgrRelation objects.
81+
* In addition, "unowned" SMgrRelation objects are chained together in a list.
8182
*/
8283
staticHTAB*SMgrRelationHash=NULL;
8384

85+
staticSMgrRelationfirst_unowned_reln=NULL;
86+
8487
/* local function prototypes */
8588
staticvoidsmgrshutdown(intcode,Datumarg);
89+
staticvoidremove_from_unowned_list(SMgrRelationreln);
8690

8791

8892
/*
@@ -126,7 +130,7 @@ smgrshutdown(int code, Datum arg)
126130
/*
127131
*smgropen() -- Return an SMgrRelation object, creating it if need be.
128132
*
129-
*This does not attempt to actually open theobject.
133+
*This does not attempt to actually open theunderlying file.
130134
*/
131135
SMgrRelation
132136
smgropen(RelFileNodernode,BackendIdbackend)
@@ -146,6 +150,7 @@ smgropen(RelFileNode rnode, BackendId backend)
146150
ctl.hash=tag_hash;
147151
SMgrRelationHash=hash_create("smgr relation table",400,
148152
&ctl,HASH_ELEM |HASH_FUNCTION);
153+
first_unowned_reln=NULL;
149154
}
150155

151156
/* Look up or create an entry */
@@ -170,6 +175,10 @@ smgropen(RelFileNode rnode, BackendId backend)
170175
/* mark it not open */
171176
for (forknum=0;forknum <=MAX_FORKNUM;forknum++)
172177
reln->md_fd[forknum]=NULL;
178+
179+
/* place it at head of unowned list (to make smgrsetowner cheap) */
180+
reln->next_unowned_reln=first_unowned_reln;
181+
first_unowned_reln=reln;
173182
}
174183

175184
returnreln;
@@ -184,20 +193,60 @@ smgropen(RelFileNode rnode, BackendId backend)
184193
void
185194
smgrsetowner(SMgrRelation*owner,SMgrRelationreln)
186195
{
196+
/* We don't currently support "disowning" an SMgrRelation here */
197+
Assert(owner!=NULL);
198+
187199
/*
188200
* First, unhook any old owner. (Normally there shouldn't be any, but it
189201
* seems possible that this can happen during swap_relation_files()
190202
* depending on the order of processing. It's ok to close the old
191203
* relcache entry early in that case.)
204+
*
205+
* If there isn't an old owner, then the reln should be in the unowned
206+
* list, and we need to remove it.
192207
*/
193208
if (reln->smgr_owner)
194209
*(reln->smgr_owner)=NULL;
210+
else
211+
remove_from_unowned_list(reln);
195212

196213
/* Now establish the ownership relationship. */
197214
reln->smgr_owner=owner;
198215
*owner=reln;
199216
}
200217

218+
/*
219+
* remove_from_unowned_list -- unlink an SMgrRelation from the unowned list
220+
*
221+
* If the reln is not present in the list, nothing happens. Typically this
222+
* would be caller error, but there seems no reason to throw an error.
223+
*
224+
* In the worst case this could be rather slow; but in all the cases that seem
225+
* likely to be performance-critical, the reln being sought will actually be
226+
* first in the list. Furthermore, the number of unowned relns touched in any
227+
* one transaction shouldn't be all that high typically. So it doesn't seem
228+
* worth expending the additional space and management logic needed for a
229+
* doubly-linked list.
230+
*/
231+
staticvoid
232+
remove_from_unowned_list(SMgrRelationreln)
233+
{
234+
SMgrRelation*link;
235+
SMgrRelationcur;
236+
237+
for (link=&first_unowned_reln,cur=*link;
238+
cur!=NULL;
239+
link=&cur->next_unowned_reln,cur=*link)
240+
{
241+
if (cur==reln)
242+
{
243+
*link=cur->next_unowned_reln;
244+
cur->next_unowned_reln=NULL;
245+
break;
246+
}
247+
}
248+
}
249+
201250
/*
202251
*smgrexists() -- Does the underlying file for a fork exist?
203252
*/
@@ -221,6 +270,9 @@ smgrclose(SMgrRelation reln)
221270

222271
owner=reln->smgr_owner;
223272

273+
if (!owner)
274+
remove_from_unowned_list(reln);
275+
224276
if (hash_search(SMgrRelationHash,
225277
(void*)&(reln->smgr_rnode),
226278
HASH_REMOVE,NULL)==NULL)
@@ -546,3 +598,29 @@ smgrpostckpt(void)
546598
(*(smgrsw[i].smgr_post_ckpt)) ();
547599
}
548600
}
601+
602+
/*
603+
* AtEOXact_SMgr
604+
*
605+
* This routine is called during transaction commit or abort (it doesn't
606+
* particularly care which). All transient SMgrRelation objects are closed.
607+
*
608+
* We do this as a compromise between wanting transient SMgrRelations to
609+
* live awhile (to amortize the costs of blind writes of multiple blocks)
610+
* and needing them to not live forever (since we're probably holding open
611+
* a kernel file descriptor for the underlying file, and we need to ensure
612+
* that gets closed reasonably soon if the file gets deleted).
613+
*/
614+
void
615+
AtEOXact_SMgr(void)
616+
{
617+
/*
618+
* Zap all unowned SMgrRelations. We rely on smgrclose() to remove each
619+
* one from the list.
620+
*/
621+
while (first_unowned_reln!=NULL)
622+
{
623+
Assert(first_unowned_reln->smgr_owner==NULL);
624+
smgrclose(first_unowned_reln);
625+
}
626+
}

‎src/include/storage/smgr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
* without having to make the smgr explicitly aware of relcache. There
3636
* can't be more than one "owner" pointer per SMgrRelation, but that's
3737
* all we need.
38+
*
39+
* SMgrRelations that do not have an "owner" are considered to be transient,
40+
* and are deleted at end of transaction.
3841
*/
3942
typedefstructSMgrRelationData
4043
{
@@ -65,6 +68,9 @@ typedef struct SMgrRelationData
6568

6669
/* for md.c; NULL for forks that are not open */
6770
struct_MdfdVec*md_fd[MAX_FORKNUM+1];
71+
72+
/* if unowned, list link in list of all unowned SMgrRelations */
73+
structSMgrRelationData*next_unowned_reln;
6874
}SMgrRelationData;
6975

7076
typedefSMgrRelationData*SMgrRelation;
@@ -97,6 +103,7 @@ extern void smgrimmedsync(SMgrRelation reln, ForkNumber forknum);
97103
externvoidsmgrpreckpt(void);
98104
externvoidsmgrsync(void);
99105
externvoidsmgrpostckpt(void);
106+
externvoidAtEOXact_SMgr(void);
100107

101108

102109
/* internals: move me elsewhere -- ay 7/94 */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp