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

Commitb74e94d

Browse files
committed
Rethink PROCSIGNAL_BARRIER_SMGRRELEASE.
With sufficiently bad luck, it was possible for IssuePendingWritebacks()to reopen a file after we'd processed PROCSIGNAL_BARRIER_SMGRRELEASE andbefore the file was unlinked by some other backend. That left a smallhole in commit4eb2176's plan to fix all spurious errors from DROPTABLESPACE and similar on Windows.Fix by closing md.c's segments, instead of just closing fd.c'sdescriptors, and then teaching smgrwriteback() not to open files thataren't already open.Reported-by: Andres Freund <andres@anarazel.de>Reviewed-by: Robert Haas <robertmhaas@gmail.com>Discussion:https://postgr.es/m/20220209220004.kb3dgtn2x2k2gtdm%40alap3.anarazel.de
1 parent701d918 commitb74e94d

File tree

4 files changed

+52
-18
lines changed

4 files changed

+52
-18
lines changed

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

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ static MemoryContext MdCxt;/* context for all MdfdVec objects */
116116
* mdnblocks().
117117
*/
118118
#defineEXTENSION_DONT_CHECK_SIZE(1 << 4)
119+
/* don't try to open a segment, if not already open */
120+
#defineEXTENSION_DONT_OPEN(1 << 5)
119121

120122

121123
/* local routines */
@@ -551,12 +553,6 @@ mdclose(SMgrRelation reln, ForkNumber forknum)
551553
}
552554
}
553555

554-
void
555-
mdrelease(void)
556-
{
557-
closeAllVfds();
558-
}
559-
560556
/*
561557
*mdprefetch() -- Initiate asynchronous read of the specified block of a relation
562558
*/
@@ -605,11 +601,14 @@ mdwriteback(SMgrRelation reln, ForkNumber forknum,
605601
segnum_end;
606602

607603
v=_mdfd_getseg(reln,forknum,blocknum, true/* not used */ ,
608-
EXTENSION_RETURN_NULL);
604+
EXTENSION_DONT_OPEN);
609605

610606
/*
611607
* We might be flushing buffers of already removed relations, that's
612-
* ok, just ignore that case.
608+
* ok, just ignore that case. If the segment file wasn't open already
609+
* (ie from a recent mdwrite()), then we don't want to re-open it, to
610+
* avoid a race with PROCSIGNAL_BARRIER_SMGRRELEASE that might leave
611+
* us with a descriptor to a file that is about to be unlinked.
613612
*/
614613
if (!v)
615614
return;
@@ -1202,7 +1201,8 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
12021201

12031202
/* some way to handle non-existent segments needs to be specified */
12041203
Assert(behavior&
1205-
(EXTENSION_FAIL |EXTENSION_CREATE |EXTENSION_RETURN_NULL));
1204+
(EXTENSION_FAIL |EXTENSION_CREATE |EXTENSION_RETURN_NULL |
1205+
EXTENSION_DONT_OPEN));
12061206

12071207
targetseg=blkno / ((BlockNumber)RELSEG_SIZE);
12081208

@@ -1213,6 +1213,10 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
12131213
returnv;
12141214
}
12151215

1216+
/* The caller only wants the segment if we already had it open. */
1217+
if (behavior&EXTENSION_DONT_OPEN)
1218+
returnNULL;
1219+
12161220
/*
12171221
* The target segment is not yet open. Iterate over all the segments
12181222
* between the last opened and the target segment. This way missing

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

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ typedef struct f_smgr
4141
{
4242
void(*smgr_init) (void);/* may be NULL */
4343
void(*smgr_shutdown) (void);/* may be NULL */
44-
void(*smgr_release) (void);/* may be NULL */
4544
void(*smgr_open) (SMgrRelationreln);
4645
void(*smgr_close) (SMgrRelationreln,ForkNumberforknum);
4746
void(*smgr_create) (SMgrRelationreln,ForkNumberforknum,
@@ -70,7 +69,6 @@ static const f_smgr smgrsw[] = {
7069
{
7170
.smgr_init=mdinit,
7271
.smgr_shutdown=NULL,
73-
.smgr_release=mdrelease,
7472
.smgr_open=mdopen,
7573
.smgr_close=mdclose,
7674
.smgr_create=mdcreate,
@@ -281,6 +279,42 @@ smgrclose(SMgrRelation reln)
281279
*owner=NULL;
282280
}
283281

282+
/*
283+
*smgrrelease() -- Release all resources used by this object.
284+
*
285+
*The object remains valid.
286+
*/
287+
void
288+
smgrrelease(SMgrRelationreln)
289+
{
290+
for (ForkNumberforknum=0;forknum <=MAX_FORKNUM;forknum++)
291+
{
292+
smgrsw[reln->smgr_which].smgr_close(reln,forknum);
293+
reln->smgr_cached_nblocks[forknum]=InvalidBlockNumber;
294+
}
295+
}
296+
297+
/*
298+
*smgrreleaseall() -- Release resources used by all objects.
299+
*
300+
*This is called for PROCSIGNAL_BARRIER_SMGRRELEASE.
301+
*/
302+
void
303+
smgrreleaseall(void)
304+
{
305+
HASH_SEQ_STATUSstatus;
306+
SMgrRelationreln;
307+
308+
/* Nothing to do if hashtable not set up */
309+
if (SMgrRelationHash==NULL)
310+
return;
311+
312+
hash_seq_init(&status,SMgrRelationHash);
313+
314+
while ((reln= (SMgrRelation)hash_seq_search(&status))!=NULL)
315+
smgrrelease(reln);
316+
}
317+
284318
/*
285319
*smgrcloseall() -- Close all existing SMgrRelation objects.
286320
*/
@@ -698,11 +732,6 @@ AtEOXact_SMgr(void)
698732
bool
699733
ProcessBarrierSmgrRelease(void)
700734
{
701-
for (inti=0;i<NSmgr;i++)
702-
{
703-
if (smgrsw[i].smgr_release)
704-
smgrsw[i].smgr_release();
705-
}
706-
735+
smgrreleaseall();
707736
return true;
708737
}

‎src/include/storage/md.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
externvoidmdinit(void);
2424
externvoidmdopen(SMgrRelationreln);
2525
externvoidmdclose(SMgrRelationreln,ForkNumberforknum);
26-
externvoidmdrelease(void);
2726
externvoidmdcreate(SMgrRelationreln,ForkNumberforknum,boolisRedo);
2827
externboolmdexists(SMgrRelationreln,ForkNumberforknum);
2928
externvoidmdunlink(RelFileNodeBackendrnode,ForkNumberforknum,boolisRedo);

‎src/include/storage/smgr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ extern void smgrclearowner(SMgrRelation *owner, SMgrRelation reln);
8585
externvoidsmgrclose(SMgrRelationreln);
8686
externvoidsmgrcloseall(void);
8787
externvoidsmgrclosenode(RelFileNodeBackendrnode);
88+
externvoidsmgrrelease(SMgrRelationreln);
89+
externvoidsmgrreleaseall(void);
8890
externvoidsmgrcreate(SMgrRelationreln,ForkNumberforknum,boolisRedo);
8991
externvoidsmgrdosyncall(SMgrRelation*rels,intnrels);
9092
externvoidsmgrdounlinkall(SMgrRelation*rels,intnrels,boolisRedo);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp