@@ -121,13 +121,17 @@ static MemoryContext MdCxt; /* context for all md.c allocations */
121
121
* be deleted after the next checkpoint, but we use a linked list instead of
122
122
* a hash table, because we don't expect there to be any duplicate requests.
123
123
*
124
+ * These mechanisms are only used for non-temp relations; we never fsync
125
+ * temp rels, nor do we need to postpone their deletion (see comments in
126
+ * mdunlink).
127
+ *
124
128
* (Regular backends do not track pending operations locally, but forward
125
129
* them to the bgwriter.)
126
130
*/
127
131
typedef struct
128
132
{
129
- RelFileNodeBackend rnode ; /* the targeted relation */
130
- ForkNumber forknum ;
133
+ RelFileNode rnode ; /* the targeted relation */
134
+ ForkNumber forknum ; /* which fork */
131
135
BlockNumber segno ; /* which segment */
132
136
} PendingOperationTag ;
133
137
@@ -142,7 +146,7 @@ typedef struct
142
146
143
147
typedef struct
144
148
{
145
- RelFileNodeBackend rnode ; /* the dead relation to delete */
149
+ RelFileNode rnode ; /* the dead relation to delete */
146
150
CycleCtr cycle_ctr ; /* mdckpt_cycle_ctr when request was made */
147
151
} PendingUnlinkEntry ;
148
152
@@ -301,11 +305,11 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
301
305
/*
302
306
* mdunlink() -- Unlink a relation.
303
307
*
304
- * Note that we're passed a RelFileNode --- by the time this is called,
308
+ * Note that we're passed a RelFileNodeBackend --- by the time this is called,
305
309
* there won't be an SMgrRelation hashtable entry anymore.
306
310
*
307
- * Actually , we don't unlink the first segment file of the relation, but
308
- * just truncate it to zero length, and record a request to unlink it after
311
+ * For regular relations , we don't unlink the first segment file of the rel,
312
+ * but just truncate it to zero length, and record a request to unlink it after
309
313
* the next checkpoint. Additional segments can be unlinked immediately,
310
314
* however. Leaving the empty file in place prevents that relfilenode
311
315
* number from being reused. The scenario this protects us from is:
@@ -322,6 +326,12 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
322
326
* number until it's safe, because relfilenode assignment skips over any
323
327
* existing file.
324
328
*
329
+ * We do not need to go through this dance for temp relations, though, because
330
+ * we never make WAL entries for temp rels, and so a temp rel poses no threat
331
+ * to the health of a regular rel that has taken over its relfilenode number.
332
+ * The fact that temp rels and regular rels have different file naming
333
+ * patterns provides additional safety.
334
+ *
325
335
* All the above applies only to the relation's main fork; other forks can
326
336
* just be removed immediately, since they are not needed to prevent the
327
337
* relfilenode number from being recycled. Also, we do not carefully
@@ -344,16 +354,18 @@ mdunlink(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
344
354
345
355
/*
346
356
* We have to clean out any pending fsync requests for the doomed
347
- * relation, else the next mdsync() will fail.
357
+ * relation, else the next mdsync() will fail. There can't be any such
358
+ * requests for a temp relation, though.
348
359
*/
349
- ForgetRelationFsyncRequests (rnode , forkNum );
360
+ if (!RelFileNodeBackendIsTemp (rnode ))
361
+ ForgetRelationFsyncRequests (rnode .node , forkNum );
350
362
351
363
path = relpath (rnode , forkNum );
352
364
353
365
/*
354
366
* Delete or truncate the first segment.
355
367
*/
356
- if (isRedo || forkNum != MAIN_FORKNUM )
368
+ if (isRedo || forkNum != MAIN_FORKNUM || RelFileNodeBackendIsTemp ( rnode ) )
357
369
{
358
370
ret = unlink (path );
359
371
if (ret < 0 && errno != ENOENT )
@@ -1078,8 +1090,7 @@ mdsync(void)
1078
1090
* the relation will have been dirtied through this same smgr
1079
1091
* relation, and so we can save a file open/close cycle.
1080
1092
*/
1081
- reln = smgropen (entry -> tag .rnode .node ,
1082
- entry -> tag .rnode .backend );
1093
+ reln = smgropen (entry -> tag .rnode , InvalidBackendId );
1083
1094
1084
1095
/*
1085
1096
* It is possible that the relation has been dropped or
@@ -1230,7 +1241,7 @@ mdpostckpt(void)
1230
1241
Assert ((CycleCtr ) (entry -> cycle_ctr + 1 ) == mdckpt_cycle_ctr );
1231
1242
1232
1243
/* Unlink the file */
1233
- path = relpath (entry -> rnode , MAIN_FORKNUM );
1244
+ path = relpathperm (entry -> rnode , MAIN_FORKNUM );
1234
1245
if (unlink (path ) < 0 )
1235
1246
{
1236
1247
/*
@@ -1258,20 +1269,23 @@ mdpostckpt(void)
1258
1269
* If there is a local pending-ops table, just make an entry in it for
1259
1270
* mdsync to process later. Otherwise, try to pass off the fsync request
1260
1271
* to the background writer process. If that fails, just do the fsync
1261
- * locally before returning (we expect this will not happen often enough
1272
+ * locally before returning (we hope this will not happen often enough
1262
1273
* to be a performance problem).
1263
1274
*/
1264
1275
static void
1265
1276
register_dirty_segment (SMgrRelation reln , ForkNumber forknum , MdfdVec * seg )
1266
1277
{
1278
+ /* Temp relations should never be fsync'd */
1279
+ Assert (!SmgrIsTemp (reln ));
1280
+
1267
1281
if (pendingOpsTable )
1268
1282
{
1269
1283
/* push it into local pending-ops table */
1270
- RememberFsyncRequest (reln -> smgr_rnode , forknum , seg -> mdfd_segno );
1284
+ RememberFsyncRequest (reln -> smgr_rnode . node , forknum , seg -> mdfd_segno );
1271
1285
}
1272
1286
else
1273
1287
{
1274
- if (ForwardFsyncRequest (reln -> smgr_rnode , forknum , seg -> mdfd_segno ))
1288
+ if (ForwardFsyncRequest (reln -> smgr_rnode . node , forknum , seg -> mdfd_segno ))
1275
1289
return ; /* passed it off successfully */
1276
1290
1277
1291
ereport (DEBUG1 ,
@@ -1288,16 +1302,23 @@ register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
1288
1302
/*
1289
1303
* register_unlink() -- Schedule a file to be deleted after next checkpoint
1290
1304
*
1305
+ * We don't bother passing in the fork number, because this is only used
1306
+ * with main forks.
1307
+ *
1291
1308
* As with register_dirty_segment, this could involve either a local or
1292
1309
* a remote pending-ops table.
1293
1310
*/
1294
1311
static void
1295
1312
register_unlink (RelFileNodeBackend rnode )
1296
1313
{
1314
+ /* Should never be used with temp relations */
1315
+ Assert (!RelFileNodeBackendIsTemp (rnode ));
1316
+
1297
1317
if (pendingOpsTable )
1298
1318
{
1299
1319
/* push it into local pending-ops table */
1300
- RememberFsyncRequest (rnode , MAIN_FORKNUM , UNLINK_RELATION_REQUEST );
1320
+ RememberFsyncRequest (rnode .node , MAIN_FORKNUM ,
1321
+ UNLINK_RELATION_REQUEST );
1301
1322
}
1302
1323
else
1303
1324
{
@@ -1309,7 +1330,7 @@ register_unlink(RelFileNodeBackend rnode)
1309
1330
* XXX should we just leave the file orphaned instead?
1310
1331
*/
1311
1332
Assert (IsUnderPostmaster );
1312
- while (!ForwardFsyncRequest (rnode , MAIN_FORKNUM ,
1333
+ while (!ForwardFsyncRequest (rnode . node , MAIN_FORKNUM ,
1313
1334
UNLINK_RELATION_REQUEST ))
1314
1335
pg_usleep (10000L ); /* 10 msec seems a good number */
1315
1336
}
@@ -1335,8 +1356,7 @@ register_unlink(RelFileNodeBackend rnode)
1335
1356
* structure for them.)
1336
1357
*/
1337
1358
void
1338
- RememberFsyncRequest (RelFileNodeBackend rnode , ForkNumber forknum ,
1339
- BlockNumber segno )
1359
+ RememberFsyncRequest (RelFileNode rnode , ForkNumber forknum , BlockNumber segno )
1340
1360
{
1341
1361
Assert (pendingOpsTable );
1342
1362
@@ -1349,7 +1369,7 @@ RememberFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
1349
1369
hash_seq_init (& hstat , pendingOpsTable );
1350
1370
while ((entry = (PendingOperationEntry * ) hash_seq_search (& hstat )) != NULL )
1351
1371
{
1352
- if (RelFileNodeBackendEquals (entry -> tag .rnode , rnode ) &&
1372
+ if (RelFileNodeEquals (entry -> tag .rnode , rnode ) &&
1353
1373
entry -> tag .forknum == forknum )
1354
1374
{
1355
1375
/* Okay, cancel this entry */
@@ -1370,7 +1390,7 @@ RememberFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
1370
1390
hash_seq_init (& hstat , pendingOpsTable );
1371
1391
while ((entry = (PendingOperationEntry * ) hash_seq_search (& hstat )) != NULL )
1372
1392
{
1373
- if (entry -> tag .rnode .node . dbNode == rnode . node .dbNode )
1393
+ if (entry -> tag .rnode .dbNode == rnode .dbNode )
1374
1394
{
1375
1395
/* Okay, cancel this entry */
1376
1396
entry -> canceled = true;
@@ -1384,7 +1404,7 @@ RememberFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
1384
1404
PendingUnlinkEntry * entry = (PendingUnlinkEntry * ) lfirst (cell );
1385
1405
1386
1406
next = lnext (cell );
1387
- if (entry -> rnode .node . dbNode == rnode . node .dbNode )
1407
+ if (entry -> rnode .dbNode == rnode .dbNode )
1388
1408
{
1389
1409
pendingUnlinks = list_delete_cell (pendingUnlinks , cell , prev );
1390
1410
pfree (entry );
@@ -1399,6 +1419,9 @@ RememberFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
1399
1419
MemoryContext oldcxt = MemoryContextSwitchTo (MdCxt );
1400
1420
PendingUnlinkEntry * entry ;
1401
1421
1422
+ /* PendingUnlinkEntry doesn't store forknum, since it's always MAIN */
1423
+ Assert (forknum == MAIN_FORKNUM );
1424
+
1402
1425
entry = palloc (sizeof (PendingUnlinkEntry ));
1403
1426
entry -> rnode = rnode ;
1404
1427
entry -> cycle_ctr = mdckpt_cycle_ctr ;
@@ -1448,10 +1471,10 @@ RememberFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
1448
1471
}
1449
1472
1450
1473
/*
1451
- * ForgetRelationFsyncRequests -- forget any fsyncs for a rel
1474
+ * ForgetRelationFsyncRequests -- forget any fsyncs for a relation fork
1452
1475
*/
1453
1476
void
1454
- ForgetRelationFsyncRequests (RelFileNodeBackend rnode , ForkNumber forknum )
1477
+ ForgetRelationFsyncRequests (RelFileNode rnode , ForkNumber forknum )
1455
1478
{
1456
1479
if (pendingOpsTable )
1457
1480
{
@@ -1486,12 +1509,11 @@ ForgetRelationFsyncRequests(RelFileNodeBackend rnode, ForkNumber forknum)
1486
1509
void
1487
1510
ForgetDatabaseFsyncRequests (Oid dbid )
1488
1511
{
1489
- RelFileNodeBackend rnode ;
1512
+ RelFileNode rnode ;
1490
1513
1491
- rnode .node .dbNode = dbid ;
1492
- rnode .node .spcNode = 0 ;
1493
- rnode .node .relNode = 0 ;
1494
- rnode .backend = InvalidBackendId ;
1514
+ rnode .dbNode = dbid ;
1515
+ rnode .spcNode = 0 ;
1516
+ rnode .relNode = 0 ;
1495
1517
1496
1518
if (pendingOpsTable )
1497
1519
{
0 commit comments