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  }
299 }
300 
301 /*
302  * smgrreleaseall() -- Release resources used by all objects.
303  *
304  * This is called for PROCSIGNAL_BARRIER_SMGRRELEASE.
305  */
306 void
308 {
309  HASH_SEQ_STATUS status;
310  SMgrRelation reln;
311 
312  /* Nothing to do if hashtable not set up */
313  if (SMgrRelationHash == NULL)
314  return;
315 
317 
318  while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
319  smgrrelease(reln);
320 }
321 
322 /*
323  * smgrcloseall() -- Close all existing SMgrRelation objects.
324  */
325 void
327 {
328  HASH_SEQ_STATUS status;
329  SMgrRelation reln;
330 
331  /* Nothing to do if hashtable not set up */
332  if (SMgrRelationHash == NULL)
333  return;
334 
336 
337  while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
338  smgrclose(reln);
339 }
340 
341 /*
342  * smgrcloserellocator() -- Close SMgrRelation object for given RelFileLocator,
343  * if one exists.
344  *
345  * This has the same effects as smgrclose(smgropen(rlocator)), but it avoids
346  * uselessly creating a hashtable entry only to drop it again when no
347  * such entry exists already.
348  */
349 void
351 {
352  SMgrRelation reln;
353 
354  /* Nothing to do if hashtable not set up */
355  if (SMgrRelationHash == NULL)
356  return;
357 
359  &rlocator,
360  HASH_FIND, NULL);
361  if (reln != NULL)
362  smgrclose(reln);
363 }
364 
365 /*
366  * smgrcreate() -- Create a new relation.
367  *
368  * Given an already-created (but presumably unused) SMgrRelation,
369  * cause the underlying disk file or other storage for the fork
370  * to be created.
371  */
372 void
373 smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
374 {
375  smgrsw[reln->smgr_which].smgr_create(reln, forknum, isRedo);
376 }
377 
378 /*
379  * smgrdosyncall() -- Immediately sync all forks of all given relations
380  *
381  * All forks of all given relations are synced out to the store.
382  *
383  * This is equivalent to FlushRelationBuffers() for each smgr relation,
384  * then calling smgrimmedsync() for all forks of each relation, but it's
385  * significantly quicker so should be preferred when possible.
386  */
387 void
388 smgrdosyncall(SMgrRelation *rels, int nrels)
389 {
390  int i = 0;
391  ForkNumber forknum;
392 
393  if (nrels == 0)
394  return;
395 
396  FlushRelationsAllBuffers(rels, nrels);
397 
398  /*
399  * Sync the physical file(s).
400  */
401  for (i = 0; i < nrels; i++)
402  {
403  int which = rels[i]->smgr_which;
404 
405  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
406  {
407  if (smgrsw[which].smgr_exists(rels[i], forknum))
408  smgrsw[which].smgr_immedsync(rels[i], forknum);
409  }
410  }
411 }
412 
413 /*
414  * smgrdounlinkall() -- Immediately unlink all forks of all given relations
415  *
416  * All forks of all given relations are removed from the store. This
417  * should not be used during transactional operations, since it can't be
418  * undone.
419  *
420  * If isRedo is true, it is okay for the underlying file(s) to be gone
421  * already.
422  */
423 void
424 smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
425 {
426  int i = 0;
427  RelFileLocatorBackend *rlocators;
428  ForkNumber forknum;
429 
430  if (nrels == 0)
431  return;
432 
433  /*
434  * Get rid of any remaining buffers for the relations. bufmgr will just
435  * drop them without bothering to write the contents.
436  */
437  DropRelationsAllBuffers(rels, nrels);
438 
439  /*
440  * create an array which contains all relations to be dropped, and close
441  * each relation's forks at the smgr level while at it
442  */
443  rlocators = palloc(sizeof(RelFileLocatorBackend) * nrels);
444  for (i = 0; i < nrels; i++)
445  {
446  RelFileLocatorBackend rlocator = rels[i]->smgr_rlocator;
447  int which = rels[i]->smgr_which;
448 
449  rlocators[i] = rlocator;
450 
451  /* Close the forks at smgr level */
452  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
453  smgrsw[which].smgr_close(rels[i], forknum);
454  }
455 
456  /*
457  * Send a shared-inval message to force other backends to close any
458  * dangling smgr references they may have for these rels. We should do
459  * this before starting the actual unlinking, in case we fail partway
460  * through that step. Note that the sinval messages will eventually come
461  * back to this backend, too, and thereby provide a backstop that we
462  * closed our own smgr rel.
463  */
464  for (i = 0; i < nrels; i++)
465  CacheInvalidateSmgr(rlocators[i]);
466 
467  /*
468  * Delete the physical file(s).
469  *
470  * Note: smgr_unlink must treat deletion failure as a WARNING, not an
471  * ERROR, because we've already decided to commit or abort the current
472  * xact.
473  */
474 
475  for (i = 0; i < nrels; i++)
476  {
477  int which = rels[i]->smgr_which;
478 
479  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
480  smgrsw[which].smgr_unlink(rlocators[i], forknum, isRedo);
481  }
482 
483  pfree(rlocators);
484 }
485 
486 
487 /*
488  * smgrextend() -- Add a new block to a file.
489  *
490  * The semantics are nearly the same as smgrwrite(): write at the
491  * specified position. However, this is to be used for the case of
492  * extending a relation (i.e., blocknum is at or beyond the current
493  * EOF). Note that we assume writing a block beyond current EOF
494  * causes intervening file space to become filled with zeroes.
495  */
496 void
498  const void *buffer, bool skipFsync)
499 {
500  smgrsw[reln->smgr_which].smgr_extend(reln, forknum, blocknum,
501  buffer, skipFsync);
502 
503  /*
504  * Normally we expect this to increase nblocks by one, but if the cached
505  * value isn't as expected, just invalidate it so the next call asks the
506  * kernel.
507  */
508  if (reln->smgr_cached_nblocks[forknum] == blocknum)
509  reln->smgr_cached_nblocks[forknum] = blocknum + 1;
510  else
511  reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber;
512 }
513 
514 /*
515  * smgrzeroextend() -- Add new zeroed out blocks to a file.
516  *
517  * Similar to smgrextend(), except the relation can be extended by
518  * multiple blocks at once and the added blocks will be filled with
519  * zeroes.
520  */
521 void
523  int nblocks, bool skipFsync)
524 {
525  smgrsw[reln->smgr_which].smgr_zeroextend(reln, forknum, blocknum,
526  nblocks, skipFsync);
527 
528  /*
529  * Normally we expect this to increase the fork size by nblocks, but if
530  * the cached value isn't as expected, just invalidate it so the next call
531  * asks the kernel.
532  */
533  if (reln->smgr_cached_nblocks[forknum] == blocknum)
534  reln->smgr_cached_nblocks[forknum] = blocknum + nblocks;
535  else
536  reln->smgr_cached_nblocks[forknum] = InvalidBlockNumber;
537 }
538 
539 /*
540  * smgrprefetch() -- Initiate asynchronous read of the specified block of a relation.
541  *
542  * In recovery only, this can return false to indicate that a file
543  * doesn't exist (presumably it has been dropped by a later WAL
544  * record).
545  */
546 bool
548 {
549  return smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum);
550 }
551 
552 /*
553  * smgrread() -- read a particular block from a relation into the supplied
554  * buffer.
555  *
556  * This routine is called from the buffer manager in order to
557  * instantiate pages in the shared buffer cache. All storage managers
558  * return pages in the format that POSTGRES expects.
559  */
560 void
561 smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
562  void *buffer)
563 {
564  smgrsw[reln->smgr_which].smgr_read(reln, forknum, blocknum, buffer);
565 }
566 
567 /*
568  * smgrwrite() -- Write the supplied buffer out.
569  *
570  * This is to be used only for updating already-existing blocks of a
571  * relation (ie, those before the current EOF). To extend a relation,
572  * use smgrextend().
573  *
574  * This is not a synchronous write -- the block is not necessarily
575  * on disk at return, only dumped out to the kernel. However,
576  * provisions will be made to fsync the write before the next checkpoint.
577  *
578  * skipFsync indicates that the caller will make other provisions to
579  * fsync the relation, so we needn't bother. Temporary relations also
580  * do not require fsync.
581  */
582 void
584  const void *buffer, bool skipFsync)
585 {
586  smgrsw[reln->smgr_which].smgr_write(reln, forknum, blocknum,
587  buffer, skipFsync);
588 }
589 
590 
591 /*
592  * smgrwriteback() -- Trigger kernel writeback for the supplied range of
593  * blocks.
594  */
595 void
597  BlockNumber nblocks)
598 {
599  smgrsw[reln->smgr_which].smgr_writeback(reln, forknum, blocknum,
600  nblocks);
601 }
602 
603 /*
604  * smgrnblocks() -- Calculate the number of blocks in the
605  * supplied relation.
606  */
609 {
610  BlockNumber result;
611 
612  /* Check and return if we get the cached value for the number of blocks. */
613  result = smgrnblocks_cached(reln, forknum);
614  if (result != InvalidBlockNumber)
615  return result;
616 
617  result = smgrsw[reln->smgr_which].smgr_nblocks(reln, forknum);
618 
619  reln->smgr_cached_nblocks[forknum] = result;
620 
621  return result;
622 }
623 
624 /*
625  * smgrnblocks_cached() -- Get the cached number of blocks in the supplied
626  * relation.
627  *
628  * Returns an InvalidBlockNumber when not in recovery and when the relation
629  * fork size is not cached.
630  */
633 {
634  /*
635  * For now, we only use cached values in recovery due to lack of a shared
636  * invalidation mechanism for changes in file size.
637  */
638  if (InRecovery && reln->smgr_cached_nblocks[forknum] != InvalidBlockNumber)
639  return reln->smgr_cached_nblocks[forknum];
640 
641  return InvalidBlockNumber;
642 }
643 
644 /*
645  * smgrtruncate() -- Truncate the given forks of supplied relation to
646  * each specified numbers of blocks
647  *
648  * The truncation is done immediately, so this can't be rolled back.
649  *
650  * The caller must hold AccessExclusiveLock on the relation, to ensure that
651  * other backends receive the smgr invalidation event that this function sends
652  * before they access any forks of the relation again.
653  */
654 void
655 smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nblocks)
656 {
657  int i;
658 
659  /*
660  * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
661  * just drop them without bothering to write the contents.
662  */
663  DropRelationBuffers(reln, forknum, nforks, nblocks);
664 
665  /*
666  * Send a shared-inval message to force other backends to close any smgr
667  * references they may have for this rel. This is useful because they
668  * might have open file pointers to segments that got removed, and/or
669  * smgr_targblock variables pointing past the new rel end. (The inval
670  * message will come back to our backend, too, causing a
671  * probably-unnecessary local smgr flush. But we don't expect that this
672  * is a performance-critical path.) As in the unlink code, we want to be
673  * sure the message is sent before we start changing things on-disk.
674  */
676 
677  /* Do the truncation */
678  for (i = 0; i < nforks; i++)
679  {
680  /* Make the cached size is invalid if we encounter an error. */
681  reln->smgr_cached_nblocks[forknum[i]] = InvalidBlockNumber;
682 
683  smgrsw[reln->smgr_which].smgr_truncate(reln, forknum[i], nblocks[i]);
684 
685  /*
686  * We might as well update the local smgr_cached_nblocks values. The
687  * smgr cache inval message that this function sent will cause other
688  * backends to invalidate their copies of smgr_fsm_nblocks and
689  * smgr_vm_nblocks, and these ones too at the next command boundary.
690  * But these ensure they aren't outright wrong until then.
691  */
692  reln->smgr_cached_nblocks[forknum[i]] = nblocks[i];
693  }
694 }
695 
696 /*
697  * smgrimmedsync() -- Force the specified relation to stable storage.
698  *
699  * Synchronously force all previous writes to the specified relation
700  * down to disk.
701  *
702  * This is useful for building completely new relations (eg, new
703  * indexes). Instead of incrementally WAL-logging the index build
704  * steps, we can just write completed index pages to disk with smgrwrite
705  * or smgrextend, and then fsync the completed index file before
706  * committing the transaction. (This is sufficient for purposes of
707  * crash recovery, since it effectively duplicates forcing a checkpoint
708  * for the completed index. But it is *not* sufficient if one wishes
709  * to use the WAL log for PITR or replication purposes: in that case
710  * we have to make WAL entries as well.)
711  *
712  * The preceding writes should specify skipFsync = true to avoid
713  * duplicative fsyncs.
714  *
715  * Note that you need to do FlushRelationBuffers() first if there is
716  * any possibility that there are dirty buffers for the relation;
717  * otherwise the sync is not very meaningful.
718  */
719 void
721 {
722  smgrsw[reln->smgr_which].smgr_immedsync(reln, forknum);
723 }
724 
725 /*
726  * AtEOXact_SMgr
727  *
728  * This routine is called during transaction commit or abort (it doesn't
729  * particularly care which). All transient SMgrRelation objects are closed.
730  *
731  * We do this as a compromise between wanting transient SMgrRelations to
732  * live awhile (to amortize the costs of blind writes of multiple blocks)
733  * and needing them to not live forever (since we're probably holding open
734  * a kernel file descriptor for the underlying file, and we need to ensure
735  * that gets closed reasonably soon if the file gets deleted).
736  */
737 void
739 {
740  dlist_mutable_iter iter;
741 
742  /*
743  * Zap all unowned SMgrRelations. We rely on smgrclose() to remove each
744  * one from the list.
745  */
747  {
749  iter.cur);
750 
751  Assert(rel->smgr_owner == NULL);
752 
753  smgrclose(rel);
754  }
755 }
756 
757 /*
758  * This routine is called when we are ordered to release all open files by a
759  * ProcSignalBarrier.
760  */
761 bool
763 {
764  smgrreleaseall();
765  return true;
766 }
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:4156
void DropRelationBuffers(SMgrRelation smgr_reln, ForkNumber *forkNum, int nforks, BlockNumber *firstDelBlock)
Definition: bufmgr.c:3597
void DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
Definition: bufmgr.c:3720
unsigned char bool
Definition: c.h:440
#define lengthof(array)
Definition: c.h:772
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: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:1456
void * palloc(Size size)
Definition: mcxt.c:1226
void mdunlink(RelFileLocatorBackend rlocator, ForkNumber forknum, bool isRedo)
Definition: md.c:306
void mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: md.c:809
bool mdexists(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:173
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:935
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:459
void mdinit(void)
Definition: md.c:160
void mdclose(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:690
void mdzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync)
Definition: md.c:524
void mdwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
Definition: md.c:876
void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void *buffer)
Definition: md.c:740
void mdopen(SMgrRelation reln)
Definition: md.c:679
bool mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: md.c:713
void mdtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
Definition: md.c:992
void mdimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:1094
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:608
static HTAB * SMgrRelationHash
Definition: smgr.c:98
void smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
Definition: smgr.c:596
void smgrrelease(SMgrRelation reln)
Definition: smgr.c:292
void smgrinit(void)
Definition: smgr.c:115
void smgrreleaseall(void)
Definition: smgr.c:307
void smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
Definition: smgr.c:202
bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:547
void smgrcloserellocator(RelFileLocatorBackend rlocator)
Definition: smgr.c:350
void smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, const void *buffer, bool skipFsync)
Definition: smgr.c:583
void smgrdosyncall(SMgrRelation *rels, int nrels)
Definition: smgr.c:388
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:720
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:373
BlockNumber smgrnblocks_cached(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:632
void smgrclose(SMgrRelation reln)
Definition: smgr.c:260
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:150
void smgrcloseall(void)
Definition: smgr.c:326
void smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, int nblocks, bool skipFsync)
Definition: smgr.c:522
void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void *buffer)
Definition: smgr.c:561
static const int NSmgr
Definition: smgr.c:92
bool ProcessBarrierSmgrRelease(void)
Definition: smgr.c:762
void AtEOXact_SMgr(void)
Definition: smgr.c:738
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:497
void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nblocks)
Definition: smgr.c:655
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:251
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:424
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