PostgreSQL Source Code  git master
smgr.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * smgr.c
4  * public interface routines to storage manager switch.
5  *
6  * All file system operations in POSTGRES dispatch through these
7  * routines.
8  *
9  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
10  * Portions Copyright (c) 1994, Regents of the University of California
11  *
12  *
13  * IDENTIFICATION
14  * src/backend/storage/smgr/smgr.c
15  *
16  *-------------------------------------------------------------------------
17  */
18 #include "postgres.h"
19 
20 #include "access/xlogutils.h"
21 #include "lib/ilist.h"
22 #include "storage/bufmgr.h"
23 #include "storage/ipc.h"
24 #include "storage/md.h"
25 #include "storage/smgr.h"
26 #include "utils/hsearch.h"
27 #include "utils/inval.h"
28 
29 
30 /*
31  * This struct of function pointers defines the API between smgr.c and
32  * any individual storage manager module. Note that smgr subfunctions are
33  * generally expected to report problems via elog(ERROR). An exception is
34  * that smgr_unlink should use elog(WARNING), rather than erroring out,
35  * because we normally unlink relations during post-commit/abort cleanup,
36  * and so it's too late to raise an error. Also, various conditions that
37  * would normally be errors should be allowed during bootstrap and/or WAL
38  * recovery --- see comments in md.c for details.
39  */
40 typedef struct f_smgr
41 {
42  void (*smgr_init) (void); /* may be NULL */
43  void (*smgr_shutdown) (void); /* may be NULL */
44  void (*smgr_open) (SMgrRelation reln);
45  void (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
46  void (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
47  bool isRedo);
49  void (*smgr_unlink) (RelFileLocatorBackend rlocator, ForkNumber forknum,
50  bool isRedo);
51  void (*smgr_extend) (SMgrRelation reln, ForkNumber forknum,
52  BlockNumber blocknum, char *buffer, bool skipFsync);
54  BlockNumber blocknum);
55  void (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
56  BlockNumber blocknum, char *buffer);
57  void (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
58  BlockNumber blocknum, char *buffer, bool skipFsync);
59  void (*smgr_writeback) (SMgrRelation reln, ForkNumber forknum,
60  BlockNumber blocknum, BlockNumber nblocks);
62  void (*smgr_truncate) (SMgrRelation reln, ForkNumber forknum,
63  BlockNumber nblocks);
64  void (*smgr_immedsync) (SMgrRelation reln, ForkNumber forknum);
66 
67 static const f_smgr smgrsw[] = {
68  /* magnetic disk */
69  {
70  .smgr_init = mdinit,
71  .smgr_shutdown = NULL,
72  .smgr_open = mdopen,
73  .smgr_close = mdclose,
74  .smgr_create = mdcreate,
75  .smgr_exists = mdexists,
76  .smgr_unlink = mdunlink,
77  .smgr_extend = mdextend,
78  .smgr_prefetch = mdprefetch,
79  .smgr_read = mdread,
80  .smgr_write = mdwrite,
81  .smgr_writeback = mdwriteback,
82  .smgr_nblocks = mdnblocks,
83  .smgr_truncate = mdtruncate,
84  .smgr_immedsync = mdimmedsync,
85  }
86 };
87 
88 static const int NSmgr = lengthof(smgrsw);
89 
90 /*
91  * Each backend has a hashtable that stores all extant SMgrRelation objects.
92  * In addition, "unowned" SMgrRelation objects are chained together in a list.
93  */
94 static HTAB *SMgrRelationHash = NULL;
95 
97 
98 /* local function prototypes */
99 static void smgrshutdown(int code, Datum arg);
100 
101 
102 /*
103  * smgrinit(), smgrshutdown() -- Initialize or shut down storage
104  * managers.
105  *
106  * Note: smgrinit is called during backend startup (normal or standalone
107  * case), *not* during postmaster start. Therefore, any resources created
108  * here or destroyed in smgrshutdown are backend-local.
109  */
110 void
111 smgrinit(void)
112 {
113  int i;
114 
115  for (i = 0; i < NSmgr; i++)
116  {
117  if (smgrsw[i].smgr_init)
118  smgrsw[i].smgr_init();
119  }
120 
121  /* register the shutdown proc */
123 }
124 
125 /*
126  * on_proc_exit hook for smgr cleanup during backend shutdown
127  */
128 static void
130 {
131  int i;
132 
133  for (i = 0; i < NSmgr; i++)
134  {
135  if (smgrsw[i].smgr_shutdown)
137  }
138 }
139 
140 /*
141  * smgropen() -- Return an SMgrRelation object, creating it if need be.
142  *
143  * This does not attempt to actually open the underlying file.
144  */
147 {
148  RelFileLocatorBackend brlocator;
149  SMgrRelation reln;
150  bool found;
151 
152  if (SMgrRelationHash == NULL)
153  {
154  /* First time through: initialize the hash table */
155  HASHCTL ctl;
156 
157  ctl.keysize = sizeof(RelFileLocatorBackend);
158  ctl.entrysize = sizeof(SMgrRelationData);
159  SMgrRelationHash = hash_create("smgr relation table", 400,
160  &ctl, HASH_ELEM | HASH_BLOBS);
162  }
163 
164  /* Look up or create an entry */
165  brlocator.locator = rlocator;
166  brlocator.backend = backend;
168  (void *) &brlocator,
169  HASH_ENTER, &found);
170 
171  /* Initialize it if not present before */
172  if (!found)
173  {
174  /* hash_search already filled in the lookup key */
175  reln->smgr_owner = NULL;
177  for (int i = 0; i <= MAX_FORKNUM; ++i)
179  reln->smgr_which = 0; /* we only have md.c at present */
180 
181  /* implementation-specific initialization */
182  smgrsw[reln->smgr_which].smgr_open(reln);
183 
184  /* it has no owner yet */
186  }
187 
188  return reln;
189 }
190 
191 /*
192  * smgrsetowner() -- Establish a long-lived reference to an SMgrRelation object
193  *
194  * There can be only one owner at a time; this is sufficient since currently
195  * the only such owners exist in the relcache.
196  */
197 void
199 {
200  /* We don't support "disowning" an SMgrRelation here, use smgrclearowner */
201  Assert(owner != NULL);
202 
203  /*
204  * First, unhook any old owner. (Normally there shouldn't be any, but it
205  * seems possible that this can happen during swap_relation_files()
206  * depending on the order of processing. It's ok to close the old
207  * relcache entry early in that case.)
208  *
209  * If there isn't an old owner, then the reln should be in the unowned
210  * list, and we need to remove it.
211  */
212  if (reln->smgr_owner)
213  *(reln->smgr_owner) = NULL;
214  else
215  dlist_delete(&reln->node);
216 
217  /* Now establish the ownership relationship. */
218  reln->smgr_owner = owner;
219  *owner = reln;
220 }
221 
222 /*
223  * smgrclearowner() -- Remove long-lived reference to an SMgrRelation object
224  * if one exists
225  */
226 void
228 {
229  /* Do nothing if the SMgrRelation object is not owned by the owner */
230  if (reln->smgr_owner != owner)
231  return;
232 
233  /* unset the owner's reference */
234  *owner = NULL;
235 
236  /* unset our reference to the owner */
237  reln->smgr_owner = NULL;
238 
239  /* add to list of unowned relations */
241 }
242 
243 /*
244  * smgrexists() -- Does the underlying file for a fork exist?
245  */
246 bool
248 {
249  return smgrsw[reln->smgr_which].smgr_exists(reln, forknum);
250 }
251 
252 /*
253  * smgrclose() -- Close and delete an SMgrRelation object.
254  */
255 void
257 {
258  SMgrRelation *owner;
259  ForkNumber forknum;
260 
261  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
262  smgrsw[reln->smgr_which].smgr_close(reln, forknum);
263 
264  owner = reln->smgr_owner;
265 
266  if (!owner)
267  dlist_delete(&reln->node);
268 
270  (void *) &(reln->smgr_rlocator),
271  HASH_REMOVE, NULL) == NULL)
272  elog(ERROR, "SMgrRelation hashtable corrupted");
273 
274  /*
275  * Unhook the owner pointer, if any. We do this last since in the remote
276  * possibility of failure above, the SMgrRelation object will still exist.
277  */
278  if (owner)
279  *owner = NULL;
280 }
281 
282 /*
283  * smgrrelease() -- Release all resources used by this object.
284  *
285  * The object remains valid.
286  */
287 void
289 {
290  for (ForkNumber forknum = 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
304 {
306  SMgrRelation reln;
307 
308  /* Nothing to do if hashtable not set up */
309  if (SMgrRelationHash == NULL)
310  return;
311 
313 
314  while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
315  smgrrelease(reln);
316 }
317 
318 /*
319  * smgrcloseall() -- Close all existing SMgrRelation objects.
320  */
321 void
323 {
325  SMgrRelation reln;
326 
327  /* Nothing to do if hashtable not set up */
328  if (SMgrRelationHash == NULL)
329  return;
330 
332 
333  while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
334  smgrclose(reln);
335 }
336 
337 /*
338  * smgrcloserellocator() -- Close SMgrRelation object for given RelFileLocator,
339  * if one exists.
340  *
341  * This has the same effects as smgrclose(smgropen(rlocator)), but it avoids
342  * uselessly creating a hashtable entry only to drop it again when no
343  * such entry exists already.
344  */
345 void
347 {
348  SMgrRelation reln;
349 
350  /* Nothing to do if hashtable not set up */
351  if (SMgrRelationHash == NULL)
352  return;
353 
355  (void *) &rlocator,
356  HASH_FIND, NULL);
357  if (reln != NULL)
358  smgrclose(reln);
359 }
360 
361 /*
362  * smgrcreate() -- Create a new relation.
363  *
364  * Given an already-created (but presumably unused) SMgrRelation,
365  * cause the underlying disk file or other storage for the fork
366  * to be created.
367  */
368 void
369 smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
370 {
371  smgrsw[reln->smgr_which].smgr_create(reln, forknum, isRedo);
372 }
373 
374 /*
375  * smgrdosyncall() -- Immediately sync all forks of all given relations
376  *
377  * All forks of all given relations are synced out to the store.
378  *
379  * This is equivalent to FlushRelationBuffers() for each smgr relation,
380  * then calling smgrimmedsync() for all forks of each relation, but it's
381  * significantly quicker so should be preferred when possible.
382  */
383 void
384 smgrdosyncall(SMgrRelation *rels, int nrels)
385 {
386  int i = 0;
387  ForkNumber forknum;
388 
389  if (nrels == 0)
390  return;
391 
392  FlushRelationsAllBuffers(rels, nrels);
393 
394  /*
395  * Sync the physical file(s).
396  */
397  for (i = 0; i < nrels; i++)
398  {
399  int which = rels[i]->smgr_which;
400 
401  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
402  {
403  if (smgrsw[which].smgr_exists(rels[i], forknum))
404  smgrsw[which].smgr_immedsync(rels[i], forknum);
405  }
406  }
407 }
408 
409 /*
410  * smgrdounlinkall() -- Immediately unlink all forks of all given relations
411  *
412  * All forks of all given relations are removed from the store. This
413  * should not be used during transactional operations, since it can't be
414  * undone.
415  *
416  * If isRedo is true, it is okay for the underlying file(s) to be gone
417  * already.
418  */
419 void
420 smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
421 {
422  int i = 0;
423  RelFileLocatorBackend *rlocators;
424  ForkNumber forknum;
425 
426  if (nrels == 0)
427  return;
428 
429  /*
430  * Get rid of any remaining buffers for the relations. bufmgr will just
431  * drop them without bothering to write the contents.
432  */
433  DropRelFileLocatorsAllBuffers(rels, nrels);
434 
435  /*
436  * create an array which contains all relations to be dropped, and close
437  * each relation's forks at the smgr level while at it
438  */
439  rlocators = palloc(sizeof(RelFileLocatorBackend) * nrels);
440  for (i = 0; i < nrels; i++)
441  {
442  RelFileLocatorBackend rlocator = rels[i]->smgr_rlocator;
443  int which = rels[i]->smgr_which;
444 
445  rlocators[i] = rlocator;
446 
447  /* Close the forks at smgr level */
448  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
449  smgrsw[which].smgr_close(rels[i], forknum);
450  }
451 
452  /*
453  * Send a shared-inval message to force other backends to close any
454  * dangling smgr references they may have for these rels. We should do
455  * this before starting the actual unlinking, in case we fail partway
456  * through that step. Note that the sinval messages will eventually come
457  * back to this backend, too, and thereby provide a backstop that we
458  * closed our own smgr rel.
459  */
460  for (i = 0; i < nrels; i++)
461  CacheInvalidateSmgr(rlocators[i]);
462 
463  /*
464  * Delete the physical file(s).
465  *
466  * Note: smgr_unlink must treat deletion failure as a WARNING, not an
467  * ERROR, because we've already decided to commit or abort the current
468  * xact.
469  */
470 
471  for (i = 0; i < nrels; i++)
472  {
473  int which = rels[i]->smgr_which;
474 
475  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
476  smgrsw[which].smgr_unlink(rlocators[i], forknum, isRedo);
477  }
478 
479  pfree(rlocators);
480 }
481 
482 
483 /*
484  * smgrextend() -- Add a new block to a file.
485  *
486  * The semantics are nearly the same as smgrwrite(): write at the
487  * specified position. However, this is to be used for the case of
488  * extending a relation (i.e., blocknum is at or beyond the current
489  * EOF). Note that we assume writing a block beyond current EOF
490  * causes intervening file space to become filled with zeroes.
491  */
492 void
494  char *buffer, bool skipFsync)
495 {
496  smgrsw[reln->smgr_which].smgr_extend(reln, forknum, blocknum,
497  buffer, skipFsync);
498 
499  /*
500  * Normally we expect this to increase nblocks by one, but if the cached
501  * value isn't as expected, just invalidate it so the next call asks the
502  * kernel.
503  */
504  if (reln->smgr_cached_nblocks[forknum] == blocknum)
505  reln->smgr_cached_nblocks[forknum] = blocknum + 1;
506  else
507  reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber;
508 }
509 
510 /*
511  * smgrprefetch() -- Initiate asynchronous read of the specified block of a relation.
512  *
513  * In recovery only, this can return false to indicate that a file
514  * doesn't exist (presumably it has been dropped by a later WAL
515  * record).
516  */
517 bool
519 {
520  return smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum);
521 }
522 
523 /*
524  * smgrread() -- read a particular block from a relation into the supplied
525  * buffer.
526  *
527  * This routine is called from the buffer manager in order to
528  * instantiate pages in the shared buffer cache. All storage managers
529  * return pages in the format that POSTGRES expects.
530  */
531 void
532 smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
533  char *buffer)
534 {
535  smgrsw[reln->smgr_which].smgr_read(reln, forknum, blocknum, buffer);
536 }
537 
538 /*
539  * smgrwrite() -- Write the supplied buffer out.
540  *
541  * This is to be used only for updating already-existing blocks of a
542  * relation (ie, those before the current EOF). To extend a relation,
543  * use smgrextend().
544  *
545  * This is not a synchronous write -- the block is not necessarily
546  * on disk at return, only dumped out to the kernel. However,
547  * provisions will be made to fsync the write before the next checkpoint.
548  *
549  * skipFsync indicates that the caller will make other provisions to
550  * fsync the relation, so we needn't bother. Temporary relations also
551  * do not require fsync.
552  */
553 void
555  char *buffer, bool skipFsync)
556 {
557  smgrsw[reln->smgr_which].smgr_write(reln, forknum, blocknum,
558  buffer, skipFsync);
559 }
560 
561 
562 /*
563  * smgrwriteback() -- Trigger kernel writeback for the supplied range of
564  * blocks.
565  */
566 void
568  BlockNumber nblocks)
569 {
570  smgrsw[reln->smgr_which].smgr_writeback(reln, forknum, blocknum,
571  nblocks);
572 }
573 
574 /*
575  * smgrnblocks() -- Calculate the number of blocks in the
576  * supplied relation.
577  */
580 {
581  BlockNumber result;
582 
583  /* Check and return if we get the cached value for the number of blocks. */
584  result = smgrnblocks_cached(reln, forknum);
585  if (result != InvalidBlockNumber)
586  return result;
587 
588  result = smgrsw[reln->smgr_which].smgr_nblocks(reln, forknum);
589 
590  reln->smgr_cached_nblocks[forknum] = result;
591 
592  return result;
593 }
594 
595 /*
596  * smgrnblocks_cached() -- Get the cached number of blocks in the supplied
597  * relation.
598  *
599  * Returns an InvalidBlockNumber when not in recovery and when the relation
600  * fork size is not cached.
601  */
604 {
605  /*
606  * For now, we only use cached values in recovery due to lack of a shared
607  * invalidation mechanism for changes in file size.
608  */
609  if (InRecovery && reln->smgr_cached_nblocks[forknum] != InvalidBlockNumber)
610  return reln->smgr_cached_nblocks[forknum];
611 
612  return InvalidBlockNumber;
613 }
614 
615 /*
616  * smgrtruncate() -- Truncate the given forks of supplied relation to
617  * each specified numbers of blocks
618  *
619  * The truncation is done immediately, so this can't be rolled back.
620  *
621  * The caller must hold AccessExclusiveLock on the relation, to ensure that
622  * other backends receive the smgr invalidation event that this function sends
623  * before they access any forks of the relation again.
624  */
625 void
626 smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nblocks)
627 {
628  int i;
629 
630  /*
631  * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
632  * just drop them without bothering to write the contents.
633  */
634  DropRelFileLocatorBuffers(reln, forknum, nforks, nblocks);
635 
636  /*
637  * Send a shared-inval message to force other backends to close any smgr
638  * references they may have for this rel. This is useful because they
639  * might have open file pointers to segments that got removed, and/or
640  * smgr_targblock variables pointing past the new rel end. (The inval
641  * message will come back to our backend, too, causing a
642  * probably-unnecessary local smgr flush. But we don't expect that this
643  * is a performance-critical path.) As in the unlink code, we want to be
644  * sure the message is sent before we start changing things on-disk.
645  */
647 
648  /* Do the truncation */
649  for (i = 0; i < nforks; i++)
650  {
651  /* Make the cached size is invalid if we encounter an error. */
652  reln->smgr_cached_nblocks[forknum[i]] = InvalidBlockNumber;
653 
654  smgrsw[reln->smgr_which].smgr_truncate(reln, forknum[i], nblocks[i]);
655 
656  /*
657  * We might as well update the local smgr_cached_nblocks values. The
658  * smgr cache inval message that this function sent will cause other
659  * backends to invalidate their copies of smgr_fsm_nblocks and
660  * smgr_vm_nblocks, and these ones too at the next command boundary.
661  * But these ensure they aren't outright wrong until then.
662  */
663  reln->smgr_cached_nblocks[forknum[i]] = nblocks[i];
664  }
665 }
666 
667 /*
668  * smgrimmedsync() -- Force the specified relation to stable storage.
669  *
670  * Synchronously force all previous writes to the specified relation
671  * down to disk.
672  *
673  * This is useful for building completely new relations (eg, new
674  * indexes). Instead of incrementally WAL-logging the index build
675  * steps, we can just write completed index pages to disk with smgrwrite
676  * or smgrextend, and then fsync the completed index file before
677  * committing the transaction. (This is sufficient for purposes of
678  * crash recovery, since it effectively duplicates forcing a checkpoint
679  * for the completed index. But it is *not* sufficient if one wishes
680  * to use the WAL log for PITR or replication purposes: in that case
681  * we have to make WAL entries as well.)
682  *
683  * The preceding writes should specify skipFsync = true to avoid
684  * duplicative fsyncs.
685  *
686  * Note that you need to do FlushRelationBuffers() first if there is
687  * any possibility that there are dirty buffers for the relation;
688  * otherwise the sync is not very meaningful.
689  */
690 void
692 {
693  smgrsw[reln->smgr_which].smgr_immedsync(reln, forknum);
694 }
695 
696 /*
697  * AtEOXact_SMgr
698  *
699  * This routine is called during transaction commit or abort (it doesn't
700  * particularly care which). All transient SMgrRelation objects are closed.
701  *
702  * We do this as a compromise between wanting transient SMgrRelations to
703  * live awhile (to amortize the costs of blind writes of multiple blocks)
704  * and needing them to not live forever (since we're probably holding open
705  * a kernel file descriptor for the underlying file, and we need to ensure
706  * that gets closed reasonably soon if the file gets deleted).
707  */
708 void
710 {
711  dlist_mutable_iter iter;
712 
713  /*
714  * Zap all unowned SMgrRelations. We rely on smgrclose() to remove each
715  * one from the list.
716  */
718  {
720  iter.cur);
721 
722  Assert(rel->smgr_owner == NULL);
723 
724  smgrclose(rel);
725  }
726 }
727 
728 /*
729  * This routine is called when we are ordered to release all open files by a
730  * ProcSignalBarrier.
731  */
732 bool
734 {
735  smgrreleaseall();
736  return true;
737 }
int BackendId
Definition: backendid.h:21
uint32 BlockNumber
Definition: block.h:31
#define InvalidBlockNumber
Definition: block.h:33
void FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
Definition: bufmgr.c:3597
void DropRelFileLocatorBuffers(SMgrRelation smgr_reln, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
Definition: bufmgr.c:3050
void DropRelFileLocatorsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
Definition: bufmgr.c:3174
unsigned char bool
Definition: c.h:402
#define lengthof(array)
Definition: c.h:745
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
#define ERROR
Definition: elog.h:33
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_REMOVE
Definition: hsearch.h:115
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
static void dlist_init(dlist_head *head)
Definition: ilist.h:278
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:543
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
#define dlist_container(type, membername, ptr)
Definition: ilist.h:496
void CacheInvalidateSmgr(RelFileLocatorBackend rlocator)
Definition: inval.c:1462
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:305
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc(Size size)
Definition: mcxt.c:1068
bool mdexists(SMgrRelation reln, ForkNumber forkNum)
Definition: md.c:163
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:770
void mdunlink(RelFileLocatorBackend rlocator, ForkNumber forkNum, bool isRedo)
Definition: md.c:281
void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
Definition: md.c:182
void mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: md.c:418
void mdinit(void)
Definition: md.c:150
void mdclose(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:537
void mdwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
Definition: md.c:588
void mdopen(SMgrRelation reln)
Definition: md.c:526
void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
Definition: md.c:640
bool mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: md.c:560
void mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: md.c:705
void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
Definition: md.c:827
void mdimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:929
void * arg
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
uintptr_t Datum
Definition: postgres.h:411
struct RelFileLocatorBackend RelFileLocatorBackend
ForkNumber
Definition: relpath.h:41
#define MAX_FORKNUM
Definition: relpath.h:55
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:579
static HTAB * SMgrRelationHash
Definition: smgr.c:94
void smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
Definition: smgr.c:567
void smgrrelease(SMgrRelation reln)
Definition: smgr.c:288
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:554
void smgrinit(void)
Definition: smgr.c:111
void smgrreleaseall(void)
Definition: smgr.c:303
void smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
Definition: smgr.c:198
void smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:493
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:518
void smgrcloserellocator(RelFileLocatorBackend rlocator)
Definition: smgr.c:346
void smgrdosyncall(SMgrRelation *rels, int nrels)
Definition: smgr.c:384
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:691
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:369
BlockNumber smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:603
void smgrclose(SMgrRelation reln)
Definition: smgr.c:256
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:146
void smgrcloseall(void)
Definition: smgr.c:322
static const int NSmgr
Definition: smgr.c:88
bool ProcessBarrierSmgrRelease(void)
Definition: smgr.c:733
void AtEOXact_SMgr(void)
Definition: smgr.c:709
static void smgrshutdown(int code, Datum arg)
Definition: smgr.c:129
void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
Definition: smgr.c:532
void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nblocks)
Definition: smgr.c:626
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:247
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:420
static dlist_head unowned_relns
Definition: smgr.c:96
void smgrclearowner(SMgrRelation *owner, SMgrRelation reln)
Definition: smgr.c:227
static const f_smgr smgrsw[]
Definition: smgr.c:67
struct f_smgr f_smgr
struct SMgrRelationData SMgrRelationData
SMgrRelationData * SMgrRelation
Definition: smgr.h:75
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
Definition: dynahash.c:220
RelFileLocator locator
struct SMgrRelationData ** smgr_owner
Definition: smgr.h:45
BlockNumber smgr_targblock
Definition: smgr.h:53
BlockNumber smgr_cached_nblocks[MAX_FORKNUM+1]
Definition: smgr.h:54
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:42
dlist_node node
Definition: smgr.h:72
int smgr_which
Definition: smgr.h:62
dlist_node * cur
Definition: ilist.h:180
Definition: smgr.c:41
bool(* smgr_prefetch)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:53
void(* smgr_writeback)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
Definition: smgr.c:59
void(* smgr_create)(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:46
BlockNumber(* smgr_nblocks)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:61
void(* smgr_immedsync)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:64
void(* smgr_read)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
Definition: smgr.c:55
void(* smgr_write)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:57
void(* smgr_unlink)(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
Definition: smgr.c:49
void(* smgr_extend)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:51
void(* smgr_open)(SMgrRelation reln)
Definition: smgr.c:44
void(* smgr_shutdown)(void)
Definition: smgr.c:43
void(* smgr_init)(void)
Definition: smgr.c:42
bool(* smgr_exists)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:48
void(* smgr_truncate)(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
Definition: smgr.c:62
void(* smgr_close)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:45
bool InRecovery
Definition: xlogutils.c:53