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