]> granicus.if.org Git - postgresql/blob - src/backend/catalog/storage.c
Move the backup-block logic from XLogInsert to a new file, xloginsert.c.
[postgresql] / src / backend / catalog / storage.c
1 /*-------------------------------------------------------------------------
2  *
3  * storage.c
4  *        code to create and destroy physical storage for relations
5  *
6  * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/catalog/storage.c
12  *
13  * NOTES
14  *        Some of this code used to be in storage/smgr/smgr.c, and the
15  *        function names still reflect that.
16  *
17  *-------------------------------------------------------------------------
18  */
19
20 #include "postgres.h"
21
22 #include "access/visibilitymap.h"
23 #include "access/xact.h"
24 #include "access/xlog.h"
25 #include "access/xloginsert.h"
26 #include "access/xlogutils.h"
27 #include "catalog/catalog.h"
28 #include "catalog/storage.h"
29 #include "catalog/storage_xlog.h"
30 #include "storage/freespace.h"
31 #include "storage/smgr.h"
32 #include "utils/memutils.h"
33 #include "utils/rel.h"
34
35 /*
36  * We keep a list of all relations (represented as RelFileNode values)
37  * that have been created or deleted in the current transaction.  When
38  * a relation is created, we create the physical file immediately, but
39  * remember it so that we can delete the file again if the current
40  * transaction is aborted.  Conversely, a deletion request is NOT
41  * executed immediately, but is just entered in the list.  When and if
42  * the transaction commits, we can delete the physical file.
43  *
44  * To handle subtransactions, every entry is marked with its transaction
45  * nesting level.  At subtransaction commit, we reassign the subtransaction's
46  * entries to the parent nesting level.  At subtransaction abort, we can
47  * immediately execute the abort-time actions for all entries of the current
48  * nesting level.
49  *
50  * NOTE: the list is kept in TopMemoryContext to be sure it won't disappear
51  * unbetimes.  It'd probably be OK to keep it in TopTransactionContext,
52  * but I'm being paranoid.
53  */
54
55 typedef struct PendingRelDelete
56 {
57         RelFileNode relnode;            /* relation that may need to be deleted */
58         BackendId       backend;                /* InvalidBackendId if not a temp rel */
59         bool            atCommit;               /* T=delete at commit; F=delete at abort */
60         int                     nestLevel;              /* xact nesting level of request */
61         struct PendingRelDelete *next;          /* linked-list link */
62 } PendingRelDelete;
63
64 static PendingRelDelete *pendingDeletes = NULL; /* head of linked list */
65
66 /*
67  * RelationCreateStorage
68  *              Create physical storage for a relation.
69  *
70  * Create the underlying disk file storage for the relation. This only
71  * creates the main fork; additional forks are created lazily by the
72  * modules that need them.
73  *
74  * This function is transactional. The creation is WAL-logged, and if the
75  * transaction aborts later on, the storage will be destroyed.
76  */
77 void
78 RelationCreateStorage(RelFileNode rnode, char relpersistence)
79 {
80         PendingRelDelete *pending;
81         SMgrRelation srel;
82         BackendId       backend;
83         bool            needs_wal;
84
85         switch (relpersistence)
86         {
87                 case RELPERSISTENCE_TEMP:
88                         backend = MyBackendId;
89                         needs_wal = false;
90                         break;
91                 case RELPERSISTENCE_UNLOGGED:
92                         backend = InvalidBackendId;
93                         needs_wal = false;
94                         break;
95                 case RELPERSISTENCE_PERMANENT:
96                         backend = InvalidBackendId;
97                         needs_wal = true;
98                         break;
99                 default:
100                         elog(ERROR, "invalid relpersistence: %c", relpersistence);
101                         return;                         /* placate compiler */
102         }
103
104         srel = smgropen(rnode, backend);
105         smgrcreate(srel, MAIN_FORKNUM, false);
106
107         if (needs_wal)
108                 log_smgrcreate(&srel->smgr_rnode.node, MAIN_FORKNUM);
109
110         /* Add the relation to the list of stuff to delete at abort */
111         pending = (PendingRelDelete *)
112                 MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
113         pending->relnode = rnode;
114         pending->backend = backend;
115         pending->atCommit = false;      /* delete if abort */
116         pending->nestLevel = GetCurrentTransactionNestLevel();
117         pending->next = pendingDeletes;
118         pendingDeletes = pending;
119 }
120
121 /*
122  * Perform XLogInsert of a XLOG_SMGR_CREATE record to WAL.
123  */
124 void
125 log_smgrcreate(RelFileNode *rnode, ForkNumber forkNum)
126 {
127         xl_smgr_create xlrec;
128         XLogRecData rdata;
129
130         /*
131          * Make an XLOG entry reporting the file creation.
132          */
133         xlrec.rnode = *rnode;
134         xlrec.forkNum = forkNum;
135
136         rdata.data = (char *) &xlrec;
137         rdata.len = sizeof(xlrec);
138         rdata.buffer = InvalidBuffer;
139         rdata.next = NULL;
140
141         XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE, &rdata);
142 }
143
144 /*
145  * RelationDropStorage
146  *              Schedule unlinking of physical storage at transaction commit.
147  */
148 void
149 RelationDropStorage(Relation rel)
150 {
151         PendingRelDelete *pending;
152
153         /* Add the relation to the list of stuff to delete at commit */
154         pending = (PendingRelDelete *)
155                 MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
156         pending->relnode = rel->rd_node;
157         pending->backend = rel->rd_backend;
158         pending->atCommit = true;       /* delete if commit */
159         pending->nestLevel = GetCurrentTransactionNestLevel();
160         pending->next = pendingDeletes;
161         pendingDeletes = pending;
162
163         /*
164          * NOTE: if the relation was created in this transaction, it will now be
165          * present in the pending-delete list twice, once with atCommit true and
166          * once with atCommit false.  Hence, it will be physically deleted at end
167          * of xact in either case (and the other entry will be ignored by
168          * smgrDoPendingDeletes, so no error will occur).  We could instead remove
169          * the existing list entry and delete the physical file immediately, but
170          * for now I'll keep the logic simple.
171          */
172
173         RelationCloseSmgr(rel);
174 }
175
176 /*
177  * RelationPreserveStorage
178  *              Mark a relation as not to be deleted after all.
179  *
180  * We need this function because relation mapping changes are committed
181  * separately from commit of the whole transaction, so it's still possible
182  * for the transaction to abort after the mapping update is done.
183  * When a new physical relation is installed in the map, it would be
184  * scheduled for delete-on-abort, so we'd delete it, and be in trouble.
185  * The relation mapper fixes this by telling us to not delete such relations
186  * after all as part of its commit.
187  *
188  * We also use this to reuse an old build of an index during ALTER TABLE, this
189  * time removing the delete-at-commit entry.
190  *
191  * No-op if the relation is not among those scheduled for deletion.
192  */
193 void
194 RelationPreserveStorage(RelFileNode rnode, bool atCommit)
195 {
196         PendingRelDelete *pending;
197         PendingRelDelete *prev;
198         PendingRelDelete *next;
199
200         prev = NULL;
201         for (pending = pendingDeletes; pending != NULL; pending = next)
202         {
203                 next = pending->next;
204                 if (RelFileNodeEquals(rnode, pending->relnode)
205                         && pending->atCommit == atCommit)
206                 {
207                         /* unlink and delete list entry */
208                         if (prev)
209                                 prev->next = next;
210                         else
211                                 pendingDeletes = next;
212                         pfree(pending);
213                         /* prev does not change */
214                 }
215                 else
216                 {
217                         /* unrelated entry, don't touch it */
218                         prev = pending;
219                 }
220         }
221 }
222
223 /*
224  * RelationTruncate
225  *              Physically truncate a relation to the specified number of blocks.
226  *
227  * This includes getting rid of any buffers for the blocks that are to be
228  * dropped.
229  */
230 void
231 RelationTruncate(Relation rel, BlockNumber nblocks)
232 {
233         bool            fsm;
234         bool            vm;
235
236         /* Open it at the smgr level if not already done */
237         RelationOpenSmgr(rel);
238
239         /*
240          * Make sure smgr_targblock etc aren't pointing somewhere past new end
241          */
242         rel->rd_smgr->smgr_targblock = InvalidBlockNumber;
243         rel->rd_smgr->smgr_fsm_nblocks = InvalidBlockNumber;
244         rel->rd_smgr->smgr_vm_nblocks = InvalidBlockNumber;
245
246         /* Truncate the FSM first if it exists */
247         fsm = smgrexists(rel->rd_smgr, FSM_FORKNUM);
248         if (fsm)
249                 FreeSpaceMapTruncateRel(rel, nblocks);
250
251         /* Truncate the visibility map too if it exists. */
252         vm = smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
253         if (vm)
254                 visibilitymap_truncate(rel, nblocks);
255
256         /*
257          * We WAL-log the truncation before actually truncating, which means
258          * trouble if the truncation fails. If we then crash, the WAL replay
259          * likely isn't going to succeed in the truncation either, and cause a
260          * PANIC. It's tempting to put a critical section here, but that cure
261          * would be worse than the disease. It would turn a usually harmless
262          * failure to truncate, that might spell trouble at WAL replay, into a
263          * certain PANIC.
264          */
265         if (RelationNeedsWAL(rel))
266         {
267                 /*
268                  * Make an XLOG entry reporting the file truncation.
269                  */
270                 XLogRecPtr      lsn;
271                 XLogRecData rdata;
272                 xl_smgr_truncate xlrec;
273
274                 xlrec.blkno = nblocks;
275                 xlrec.rnode = rel->rd_node;
276
277                 rdata.data = (char *) &xlrec;
278                 rdata.len = sizeof(xlrec);
279                 rdata.buffer = InvalidBuffer;
280                 rdata.next = NULL;
281
282                 lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE, &rdata);
283
284                 /*
285                  * Flush, because otherwise the truncation of the main relation might
286                  * hit the disk before the WAL record, and the truncation of the FSM
287                  * or visibility map. If we crashed during that window, we'd be left
288                  * with a truncated heap, but the FSM or visibility map would still
289                  * contain entries for the non-existent heap pages.
290                  */
291                 if (fsm || vm)
292                         XLogFlush(lsn);
293         }
294
295         /* Do the real work */
296         smgrtruncate(rel->rd_smgr, MAIN_FORKNUM, nblocks);
297 }
298
299 /*
300  *      smgrDoPendingDeletes() -- Take care of relation deletes at end of xact.
301  *
302  * This also runs when aborting a subxact; we want to clean up a failed
303  * subxact immediately.
304  *
305  * Note: It's possible that we're being asked to remove a relation that has
306  * no physical storage in any fork. In particular, it's possible that we're
307  * cleaning up an old temporary relation for which RemovePgTempFiles has
308  * already recovered the physical storage.
309  */
310 void
311 smgrDoPendingDeletes(bool isCommit)
312 {
313         int                     nestLevel = GetCurrentTransactionNestLevel();
314         PendingRelDelete *pending;
315         PendingRelDelete *prev;
316         PendingRelDelete *next;
317         int                     nrels = 0,
318                                 i = 0,
319                                 maxrels = 0;
320         SMgrRelation *srels = NULL;
321
322         prev = NULL;
323         for (pending = pendingDeletes; pending != NULL; pending = next)
324         {
325                 next = pending->next;
326                 if (pending->nestLevel < nestLevel)
327                 {
328                         /* outer-level entries should not be processed yet */
329                         prev = pending;
330                 }
331                 else
332                 {
333                         /* unlink list entry first, so we don't retry on failure */
334                         if (prev)
335                                 prev->next = next;
336                         else
337                                 pendingDeletes = next;
338                         /* do deletion if called for */
339                         if (pending->atCommit == isCommit)
340                         {
341                                 SMgrRelation srel;
342
343                                 srel = smgropen(pending->relnode, pending->backend);
344
345                                 /* allocate the initial array, or extend it, if needed */
346                                 if (maxrels == 0)
347                                 {
348                                         maxrels = 8;
349                                         srels = palloc(sizeof(SMgrRelation) * maxrels);
350                                 }
351                                 else if (maxrels <= nrels)
352                                 {
353                                         maxrels *= 2;
354                                         srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
355                                 }
356
357                                 srels[nrels++] = srel;
358                         }
359                         /* must explicitly free the list entry */
360                         pfree(pending);
361                         /* prev does not change */
362                 }
363         }
364
365         if (nrels > 0)
366         {
367                 smgrdounlinkall(srels, nrels, false);
368
369                 for (i = 0; i < nrels; i++)
370                         smgrclose(srels[i]);
371
372                 pfree(srels);
373         }
374 }
375
376 /*
377  * smgrGetPendingDeletes() -- Get a list of non-temp relations to be deleted.
378  *
379  * The return value is the number of relations scheduled for termination.
380  * *ptr is set to point to a freshly-palloc'd array of RelFileNodes.
381  * If there are no relations to be deleted, *ptr is set to NULL.
382  *
383  * Only non-temporary relations are included in the returned list.  This is OK
384  * because the list is used only in contexts where temporary relations don't
385  * matter: we're either writing to the two-phase state file (and transactions
386  * that have touched temp tables can't be prepared) or we're writing to xlog
387  * (and all temporary files will be zapped if we restart anyway, so no need
388  * for redo to do it also).
389  *
390  * Note that the list does not include anything scheduled for termination
391  * by upper-level transactions.
392  */
393 int
394 smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr)
395 {
396         int                     nestLevel = GetCurrentTransactionNestLevel();
397         int                     nrels;
398         RelFileNode *rptr;
399         PendingRelDelete *pending;
400
401         nrels = 0;
402         for (pending = pendingDeletes; pending != NULL; pending = pending->next)
403         {
404                 if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
405                         && pending->backend == InvalidBackendId)
406                         nrels++;
407         }
408         if (nrels == 0)
409         {
410                 *ptr = NULL;
411                 return 0;
412         }
413         rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode));
414         *ptr = rptr;
415         for (pending = pendingDeletes; pending != NULL; pending = pending->next)
416         {
417                 if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
418                         && pending->backend == InvalidBackendId)
419                 {
420                         *rptr = pending->relnode;
421                         rptr++;
422                 }
423         }
424         return nrels;
425 }
426
427 /*
428  *      PostPrepare_smgr -- Clean up after a successful PREPARE
429  *
430  * What we have to do here is throw away the in-memory state about pending
431  * relation deletes.  It's all been recorded in the 2PC state file and
432  * it's no longer smgr's job to worry about it.
433  */
434 void
435 PostPrepare_smgr(void)
436 {
437         PendingRelDelete *pending;
438         PendingRelDelete *next;
439
440         for (pending = pendingDeletes; pending != NULL; pending = next)
441         {
442                 next = pending->next;
443                 pendingDeletes = next;
444                 /* must explicitly free the list entry */
445                 pfree(pending);
446         }
447 }
448
449
450 /*
451  * AtSubCommit_smgr() --- Take care of subtransaction commit.
452  *
453  * Reassign all items in the pending-deletes list to the parent transaction.
454  */
455 void
456 AtSubCommit_smgr(void)
457 {
458         int                     nestLevel = GetCurrentTransactionNestLevel();
459         PendingRelDelete *pending;
460
461         for (pending = pendingDeletes; pending != NULL; pending = pending->next)
462         {
463                 if (pending->nestLevel >= nestLevel)
464                         pending->nestLevel = nestLevel - 1;
465         }
466 }
467
468 /*
469  * AtSubAbort_smgr() --- Take care of subtransaction abort.
470  *
471  * Delete created relations and forget about deleted relations.
472  * We can execute these operations immediately because we know this
473  * subtransaction will not commit.
474  */
475 void
476 AtSubAbort_smgr(void)
477 {
478         smgrDoPendingDeletes(false);
479 }
480
481 void
482 smgr_redo(XLogRecPtr lsn, XLogRecord *record)
483 {
484         uint8           info = record->xl_info & ~XLR_INFO_MASK;
485
486         /* Backup blocks are not used in smgr records */
487         Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));
488
489         if (info == XLOG_SMGR_CREATE)
490         {
491                 xl_smgr_create *xlrec = (xl_smgr_create *) XLogRecGetData(record);
492                 SMgrRelation reln;
493
494                 reln = smgropen(xlrec->rnode, InvalidBackendId);
495                 smgrcreate(reln, xlrec->forkNum, true);
496         }
497         else if (info == XLOG_SMGR_TRUNCATE)
498         {
499                 xl_smgr_truncate *xlrec = (xl_smgr_truncate *) XLogRecGetData(record);
500                 SMgrRelation reln;
501                 Relation        rel;
502
503                 reln = smgropen(xlrec->rnode, InvalidBackendId);
504
505                 /*
506                  * Forcibly create relation if it doesn't exist (which suggests that
507                  * it was dropped somewhere later in the WAL sequence).  As in
508                  * XLogReadBuffer, we prefer to recreate the rel and replay the log as
509                  * best we can until the drop is seen.
510                  */
511                 smgrcreate(reln, MAIN_FORKNUM, true);
512
513                 /*
514                  * Before we perform the truncation, update minimum recovery point to
515                  * cover this WAL record. Once the relation is truncated, there's no
516                  * going back. The buffer manager enforces the WAL-first rule for
517                  * normal updates to relation files, so that the minimum recovery
518                  * point is always updated before the corresponding change in the data
519                  * file is flushed to disk. We have to do the same manually here.
520                  *
521                  * Doing this before the truncation means that if the truncation fails
522                  * for some reason, you cannot start up the system even after restart,
523                  * until you fix the underlying situation so that the truncation will
524                  * succeed. Alternatively, we could update the minimum recovery point
525                  * after truncation, but that would leave a small window where the
526                  * WAL-first rule could be violated.
527                  */
528                 XLogFlush(lsn);
529
530                 smgrtruncate(reln, MAIN_FORKNUM, xlrec->blkno);
531
532                 /* Also tell xlogutils.c about it */
533                 XLogTruncateRelation(xlrec->rnode, MAIN_FORKNUM, xlrec->blkno);
534
535                 /* Truncate FSM and VM too */
536                 rel = CreateFakeRelcacheEntry(xlrec->rnode);
537
538                 if (smgrexists(reln, FSM_FORKNUM))
539                         FreeSpaceMapTruncateRel(rel, xlrec->blkno);
540                 if (smgrexists(reln, VISIBILITYMAP_FORKNUM))
541                         visibilitymap_truncate(rel, xlrec->blkno);
542
543                 FreeFakeRelcacheEntry(rel);
544         }
545         else
546                 elog(PANIC, "smgr_redo: unknown op code %u", info);
547 }