LCOV - code coverage report
Current view: top level - src/backend/storage/smgr - smgr.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 131 135 97.0 %
Date: 2020-05-29 00:07:09 Functions: 21 21 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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-2020, 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 "lib/ilist.h"
      21             : #include "storage/bufmgr.h"
      22             : #include "storage/ipc.h"
      23             : #include "storage/md.h"
      24             : #include "storage/smgr.h"
      25             : #include "utils/hsearch.h"
      26             : #include "utils/inval.h"
      27             : 
      28             : 
      29             : /*
      30             :  * This struct of function pointers defines the API between smgr.c and
      31             :  * any individual storage manager module.  Note that smgr subfunctions are
      32             :  * generally expected to report problems via elog(ERROR).  An exception is
      33             :  * that smgr_unlink should use elog(WARNING), rather than erroring out,
      34             :  * because we normally unlink relations during post-commit/abort cleanup,
      35             :  * and so it's too late to raise an error.  Also, various conditions that
      36             :  * would normally be errors should be allowed during bootstrap and/or WAL
      37             :  * recovery --- see comments in md.c for details.
      38             :  */
      39             : typedef struct f_smgr
      40             : {
      41             :     void        (*smgr_init) (void);    /* may be NULL */
      42             :     void        (*smgr_shutdown) (void);    /* may be NULL */
      43             :     void        (*smgr_open) (SMgrRelation reln);
      44             :     void        (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
      45             :     void        (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
      46             :                                 bool isRedo);
      47             :     bool        (*smgr_exists) (SMgrRelation reln, ForkNumber forknum);
      48             :     void        (*smgr_unlink) (RelFileNodeBackend rnode, ForkNumber forknum,
      49             :                                 bool isRedo);
      50             :     void        (*smgr_extend) (SMgrRelation reln, ForkNumber forknum,
      51             :                                 BlockNumber blocknum, char *buffer, bool skipFsync);
      52             :     bool        (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
      53             :                                   BlockNumber blocknum);
      54             :     void        (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
      55             :                               BlockNumber blocknum, char *buffer);
      56             :     void        (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
      57             :                                BlockNumber blocknum, char *buffer, bool skipFsync);
      58             :     void        (*smgr_writeback) (SMgrRelation reln, ForkNumber forknum,
      59             :                                    BlockNumber blocknum, BlockNumber nblocks);
      60             :     BlockNumber (*smgr_nblocks) (SMgrRelation reln, ForkNumber forknum);
      61             :     void        (*smgr_truncate) (SMgrRelation reln, ForkNumber forknum,
      62             :                                   BlockNumber nblocks);
      63             :     void        (*smgr_immedsync) (SMgrRelation reln, ForkNumber forknum);
      64             : } f_smgr;
      65             : 
      66             : static const f_smgr smgrsw[] = {
      67             :     /* magnetic disk */
      68             :     {
      69             :         .smgr_init = mdinit,
      70             :         .smgr_shutdown = NULL,
      71             :         .smgr_open = mdopen,
      72             :         .smgr_close = mdclose,
      73             :         .smgr_create = mdcreate,
      74             :         .smgr_exists = mdexists,
      75             :         .smgr_unlink = mdunlink,
      76             :         .smgr_extend = mdextend,
      77             :         .smgr_prefetch = mdprefetch,
      78             :         .smgr_read = mdread,
      79             :         .smgr_write = mdwrite,
      80             :         .smgr_writeback = mdwriteback,
      81             :         .smgr_nblocks = mdnblocks,
      82             :         .smgr_truncate = mdtruncate,
      83             :         .smgr_immedsync = mdimmedsync,
      84             :     }
      85             : };
      86             : 
      87             : static const int NSmgr = lengthof(smgrsw);
      88             : 
      89             : /*
      90             :  * Each backend has a hashtable that stores all extant SMgrRelation objects.
      91             :  * In addition, "unowned" SMgrRelation objects are chained together in a list.
      92             :  */
      93             : static HTAB *SMgrRelationHash = NULL;
      94             : 
      95             : static dlist_head unowned_relns;
      96             : 
      97             : /* local function prototypes */
      98             : static void smgrshutdown(int code, Datum arg);
      99             : 
     100             : 
     101             : /*
     102             :  *  smgrinit(), smgrshutdown() -- Initialize or shut down storage
     103             :  *                                managers.
     104             :  *
     105             :  * Note: smgrinit is called during backend startup (normal or standalone
     106             :  * case), *not* during postmaster start.  Therefore, any resources created
     107             :  * here or destroyed in smgrshutdown are backend-local.
     108             :  */
     109             : void
     110       13840 : smgrinit(void)
     111             : {
     112             :     int         i;
     113             : 
     114       27680 :     for (i = 0; i < NSmgr; i++)
     115             :     {
     116       13840 :         if (smgrsw[i].smgr_init)
     117       13840 :             smgrsw[i].smgr_init();
     118             :     }
     119             : 
     120             :     /* register the shutdown proc */
     121       13840 :     on_proc_exit(smgrshutdown, 0);
     122       13840 : }
     123             : 
     124             : /*
     125             :  * on_proc_exit hook for smgr cleanup during backend shutdown
     126             :  */
     127             : static void
     128       13840 : smgrshutdown(int code, Datum arg)
     129             : {
     130             :     int         i;
     131             : 
     132       27680 :     for (i = 0; i < NSmgr; i++)
     133             :     {
     134       13840 :         if (smgrsw[i].smgr_shutdown)
     135           0 :             smgrsw[i].smgr_shutdown();
     136             :     }
     137       13840 : }
     138             : 
     139             : /*
     140             :  *  smgropen() -- Return an SMgrRelation object, creating it if need be.
     141             :  *
     142             :  *      This does not attempt to actually open the underlying file.
     143             :  */
     144             : SMgrRelation
     145     3405362 : smgropen(RelFileNode rnode, BackendId backend)
     146             : {
     147             :     RelFileNodeBackend brnode;
     148             :     SMgrRelation reln;
     149             :     bool        found;
     150             : 
     151     3405362 :     if (SMgrRelationHash == NULL)
     152             :     {
     153             :         /* First time through: initialize the hash table */
     154             :         HASHCTL     ctl;
     155             : 
     156      162316 :         MemSet(&ctl, 0, sizeof(ctl));
     157       11594 :         ctl.keysize = sizeof(RelFileNodeBackend);
     158       11594 :         ctl.entrysize = sizeof(SMgrRelationData);
     159       11594 :         SMgrRelationHash = hash_create("smgr relation table", 400,
     160             :                                        &ctl, HASH_ELEM | HASH_BLOBS);
     161       11594 :         dlist_init(&unowned_relns);
     162             :     }
     163             : 
     164             :     /* Look up or create an entry */
     165     3405362 :     brnode.node = rnode;
     166     3405362 :     brnode.backend = backend;
     167     3405362 :     reln = (SMgrRelation) hash_search(SMgrRelationHash,
     168             :                                       (void *) &brnode,
     169             :                                       HASH_ENTER, &found);
     170             : 
     171             :     /* Initialize it if not present before */
     172     3405362 :     if (!found)
     173             :     {
     174             :         /* hash_search already filled in the lookup key */
     175     1331758 :         reln->smgr_owner = NULL;
     176     1331758 :         reln->smgr_targblock = InvalidBlockNumber;
     177     1331758 :         reln->smgr_fsm_nblocks = InvalidBlockNumber;
     178     1331758 :         reln->smgr_vm_nblocks = InvalidBlockNumber;
     179     1331758 :         reln->smgr_which = 0;    /* we only have md.c at present */
     180             : 
     181             :         /* implementation-specific initialization */
     182     1331758 :         smgrsw[reln->smgr_which].smgr_open(reln);
     183             : 
     184             :         /* it has no owner yet */
     185     1331758 :         dlist_push_tail(&unowned_relns, &reln->node);
     186             :     }
     187             : 
     188     3405362 :     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
     198     1219082 : smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
     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     1219082 :     if (reln->smgr_owner)
     213         168 :         *(reln->smgr_owner) = NULL;
     214             :     else
     215     1218914 :         dlist_delete(&reln->node);
     216             : 
     217             :     /* Now establish the ownership relationship. */
     218     1219082 :     reln->smgr_owner = owner;
     219     1219082 :     *owner = reln;
     220     1219082 : }
     221             : 
     222             : /*
     223             :  * smgrclearowner() -- Remove long-lived reference to an SMgrRelation object
     224             :  *                     if one exists
     225             :  */
     226             : void
     227        5454 : smgrclearowner(SMgrRelation *owner, SMgrRelation reln)
     228             : {
     229             :     /* Do nothing if the SMgrRelation object is not owned by the owner */
     230        5454 :     if (reln->smgr_owner != owner)
     231           0 :         return;
     232             : 
     233             :     /* unset the owner's reference */
     234        5454 :     *owner = NULL;
     235             : 
     236             :     /* unset our reference to the owner */
     237        5454 :     reln->smgr_owner = NULL;
     238             : 
     239             :     /* add to list of unowned relations */
     240        5454 :     dlist_push_tail(&unowned_relns, &reln->node);
     241             : }
     242             : 
     243             : /*
     244             :  *  smgrexists() -- Does the underlying file for a fork exist?
     245             :  */
     246             : bool
     247      452380 : smgrexists(SMgrRelation reln, ForkNumber forknum)
     248             : {
     249      452380 :     return smgrsw[reln->smgr_which].smgr_exists(reln, forknum);
     250             : }
     251             : 
     252             : /*
     253             :  *  smgrclose() -- Close and delete an SMgrRelation object.
     254             :  */
     255             : void
     256      859784 : smgrclose(SMgrRelation reln)
     257             : {
     258             :     SMgrRelation *owner;
     259             :     ForkNumber  forknum;
     260             : 
     261     4298920 :     for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     262     3439136 :         smgrsw[reln->smgr_which].smgr_close(reln, forknum);
     263             : 
     264      859784 :     owner = reln->smgr_owner;
     265             : 
     266      859784 :     if (!owner)
     267       97852 :         dlist_delete(&reln->node);
     268             : 
     269      859784 :     if (hash_search(SMgrRelationHash,
     270      859784 :                     (void *) &(reln->smgr_rnode),
     271             :                     HASH_REMOVE, NULL) == NULL)
     272           0 :         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      859784 :     if (owner)
     279      761932 :         *owner = NULL;
     280      859784 : }
     281             : 
     282             : /*
     283             :  *  smgrcloseall() -- Close all existing SMgrRelation objects.
     284             :  */
     285             : void
     286        4670 : smgrcloseall(void)
     287             : {
     288             :     HASH_SEQ_STATUS status;
     289             :     SMgrRelation reln;
     290             : 
     291             :     /* Nothing to do if hashtable not set up */
     292        4670 :     if (SMgrRelationHash == NULL)
     293         350 :         return;
     294             : 
     295        4320 :     hash_seq_init(&status, SMgrRelationHash);
     296             : 
     297       87320 :     while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
     298       83000 :         smgrclose(reln);
     299             : }
     300             : 
     301             : /*
     302             :  *  smgrclosenode() -- Close SMgrRelation object for given RelFileNode,
     303             :  *                     if one exists.
     304             :  *
     305             :  * This has the same effects as smgrclose(smgropen(rnode)), but it avoids
     306             :  * uselessly creating a hashtable entry only to drop it again when no
     307             :  * such entry exists already.
     308             :  */
     309             : void
     310      221742 : smgrclosenode(RelFileNodeBackend rnode)
     311             : {
     312             :     SMgrRelation reln;
     313             : 
     314             :     /* Nothing to do if hashtable not set up */
     315      221742 :     if (SMgrRelationHash == NULL)
     316         186 :         return;
     317             : 
     318      221556 :     reln = (SMgrRelation) hash_search(SMgrRelationHash,
     319             :                                       (void *) &rnode,
     320             :                                       HASH_FIND, NULL);
     321      221556 :     if (reln != NULL)
     322       16556 :         smgrclose(reln);
     323             : }
     324             : 
     325             : /*
     326             :  *  smgrcreate() -- Create a new relation.
     327             :  *
     328             :  *      Given an already-created (but presumably unused) SMgrRelation,
     329             :  *      cause the underlying disk file or other storage for the fork
     330             :  *      to be created.
     331             :  */
     332             : void
     333      829200 : smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
     334             : {
     335      829200 :     smgrsw[reln->smgr_which].smgr_create(reln, forknum, isRedo);
     336      829200 : }
     337             : 
     338             : /*
     339             :  *  smgrdosyncall() -- Immediately sync all forks of all given relations
     340             :  *
     341             :  *      All forks of all given relations are synced out to the store.
     342             :  *
     343             :  *      This is equivalent to FlushRelationBuffers() for each smgr relation,
     344             :  *      then calling smgrimmedsync() for all forks of each relation, but it's
     345             :  *      significantly quicker so should be preferred when possible.
     346             :  */
     347             : void
     348           4 : smgrdosyncall(SMgrRelation *rels, int nrels)
     349             : {
     350           4 :     int         i = 0;
     351             :     ForkNumber  forknum;
     352             : 
     353           4 :     if (nrels == 0)
     354           0 :         return;
     355             : 
     356           4 :     FlushRelationsAllBuffers(rels, nrels);
     357             : 
     358             :     /*
     359             :      * Sync the physical file(s).
     360             :      */
     361           8 :     for (i = 0; i < nrels; i++)
     362             :     {
     363           4 :         int         which = rels[i]->smgr_which;
     364             : 
     365          20 :         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     366             :         {
     367          16 :             if (smgrsw[which].smgr_exists(rels[i], forknum))
     368           4 :                 smgrsw[which].smgr_immedsync(rels[i], forknum);
     369             :         }
     370             :     }
     371             : }
     372             : 
     373             : /*
     374             :  *  smgrdounlinkall() -- Immediately unlink all forks of all given relations
     375             :  *
     376             :  *      All forks of all given relations are removed from the store.  This
     377             :  *      should not be used during transactional operations, since it can't be
     378             :  *      undone.
     379             :  *
     380             :  *      If isRedo is true, it is okay for the underlying file(s) to be gone
     381             :  *      already.
     382             :  */
     383             : void
     384       12444 : smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
     385             : {
     386       12444 :     int         i = 0;
     387             :     RelFileNodeBackend *rnodes;
     388             :     ForkNumber  forknum;
     389             : 
     390       12444 :     if (nrels == 0)
     391          72 :         return;
     392             : 
     393             :     /*
     394             :      * create an array which contains all relations to be dropped, and close
     395             :      * each relation's forks at the smgr level while at it
     396             :      */
     397       12372 :     rnodes = palloc(sizeof(RelFileNodeBackend) * nrels);
     398       54660 :     for (i = 0; i < nrels; i++)
     399             :     {
     400       42288 :         RelFileNodeBackend rnode = rels[i]->smgr_rnode;
     401       42288 :         int         which = rels[i]->smgr_which;
     402             : 
     403       42288 :         rnodes[i] = rnode;
     404             : 
     405             :         /* Close the forks at smgr level */
     406      211440 :         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     407      169152 :             smgrsw[which].smgr_close(rels[i], forknum);
     408             :     }
     409             : 
     410             :     /*
     411             :      * Get rid of any remaining buffers for the relations.  bufmgr will just
     412             :      * drop them without bothering to write the contents.
     413             :      */
     414       12372 :     DropRelFileNodesAllBuffers(rnodes, nrels);
     415             : 
     416             :     /*
     417             :      * It'd be nice to tell the stats collector to forget them immediately,
     418             :      * too. But we can't because we don't know the OIDs.
     419             :      */
     420             : 
     421             :     /*
     422             :      * Send a shared-inval message to force other backends to close any
     423             :      * dangling smgr references they may have for these rels.  We should do
     424             :      * this before starting the actual unlinking, in case we fail partway
     425             :      * through that step.  Note that the sinval messages will eventually come
     426             :      * back to this backend, too, and thereby provide a backstop that we
     427             :      * closed our own smgr rel.
     428             :      */
     429       54660 :     for (i = 0; i < nrels; i++)
     430       42288 :         CacheInvalidateSmgr(rnodes[i]);
     431             : 
     432             :     /*
     433             :      * Delete the physical file(s).
     434             :      *
     435             :      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     436             :      * ERROR, because we've already decided to commit or abort the current
     437             :      * xact.
     438             :      */
     439             : 
     440       54660 :     for (i = 0; i < nrels; i++)
     441             :     {
     442       42288 :         int         which = rels[i]->smgr_which;
     443             : 
     444      211440 :         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     445      169152 :             smgrsw[which].smgr_unlink(rnodes[i], forknum, isRedo);
     446             :     }
     447             : 
     448       12372 :     pfree(rnodes);
     449             : }
     450             : 
     451             : 
     452             : /*
     453             :  *  smgrextend() -- Add a new block to a file.
     454             :  *
     455             :  *      The semantics are nearly the same as smgrwrite(): write at the
     456             :  *      specified position.  However, this is to be used for the case of
     457             :  *      extending a relation (i.e., blocknum is at or beyond the current
     458             :  *      EOF).  Note that we assume writing a block beyond current EOF
     459             :  *      causes intervening file space to become filled with zeroes.
     460             :  */
     461             : void
     462      598878 : smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     463             :            char *buffer, bool skipFsync)
     464             : {
     465      598878 :     smgrsw[reln->smgr_which].smgr_extend(reln, forknum, blocknum,
     466             :                                          buffer, skipFsync);
     467      598878 : }
     468             : 
     469             : /*
     470             :  *  smgrprefetch() -- Initiate asynchronous read of the specified block of a relation.
     471             :  *
     472             :  *      In recovery only, this can return false to indicate that a file
     473             :  *      doesn't exist (presumably it has been dropped by a later WAL
     474             :  *      record).
     475             :  */
     476             : bool
     477         218 : smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
     478             : {
     479         218 :     return smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum);
     480             : }
     481             : 
     482             : /*
     483             :  *  smgrread() -- read a particular block from a relation into the supplied
     484             :  *                buffer.
     485             :  *
     486             :  *      This routine is called from the buffer manager in order to
     487             :  *      instantiate pages in the shared buffer cache.  All storage managers
     488             :  *      return pages in the format that POSTGRES expects.
     489             :  */
     490             : void
     491      547342 : smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     492             :          char *buffer)
     493             : {
     494      547342 :     smgrsw[reln->smgr_which].smgr_read(reln, forknum, blocknum, buffer);
     495      547342 : }
     496             : 
     497             : /*
     498             :  *  smgrwrite() -- Write the supplied buffer out.
     499             :  *
     500             :  *      This is to be used only for updating already-existing blocks of a
     501             :  *      relation (ie, those before the current EOF).  To extend a relation,
     502             :  *      use smgrextend().
     503             :  *
     504             :  *      This is not a synchronous write -- the block is not necessarily
     505             :  *      on disk at return, only dumped out to the kernel.  However,
     506             :  *      provisions will be made to fsync the write before the next checkpoint.
     507             :  *
     508             :  *      skipFsync indicates that the caller will make other provisions to
     509             :  *      fsync the relation, so we needn't bother.  Temporary relations also
     510             :  *      do not require fsync.
     511             :  */
     512             : void
     513      557432 : smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     514             :           char *buffer, bool skipFsync)
     515             : {
     516      557432 :     smgrsw[reln->smgr_which].smgr_write(reln, forknum, blocknum,
     517             :                                         buffer, skipFsync);
     518      557432 : }
     519             : 
     520             : 
     521             : /*
     522             :  *  smgrwriteback() -- Trigger kernel writeback for the supplied range of
     523             :  *                     blocks.
     524             :  */
     525             : void
     526      163894 : smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     527             :               BlockNumber nblocks)
     528             : {
     529      163894 :     smgrsw[reln->smgr_which].smgr_writeback(reln, forknum, blocknum,
     530             :                                             nblocks);
     531      163894 : }
     532             : 
     533             : /*
     534             :  *  smgrnblocks() -- Calculate the number of blocks in the
     535             :  *                   supplied relation.
     536             :  */
     537             : BlockNumber
     538     4320808 : smgrnblocks(SMgrRelation reln, ForkNumber forknum)
     539             : {
     540     4320808 :     return smgrsw[reln->smgr_which].smgr_nblocks(reln, forknum);
     541             : }
     542             : 
     543             : /*
     544             :  *  smgrtruncate() -- Truncate the given forks of supplied relation to
     545             :  *                    each specified numbers of blocks
     546             :  *
     547             :  * The truncation is done immediately, so this can't be rolled back.
     548             :  *
     549             :  * The caller must hold AccessExclusiveLock on the relation, to ensure that
     550             :  * other backends receive the smgr invalidation event that this function sends
     551             :  * before they access any forks of the relation again.
     552             :  */
     553             : void
     554         676 : smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nblocks)
     555             : {
     556             :     int         i;
     557             : 
     558             :     /*
     559             :      * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
     560             :      * just drop them without bothering to write the contents.
     561             :      */
     562         676 :     DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nforks, nblocks);
     563             : 
     564             :     /*
     565             :      * Send a shared-inval message to force other backends to close any smgr
     566             :      * references they may have for this rel.  This is useful because they
     567             :      * might have open file pointers to segments that got removed, and/or
     568             :      * smgr_targblock variables pointing past the new rel end.  (The inval
     569             :      * message will come back to our backend, too, causing a
     570             :      * probably-unnecessary local smgr flush.  But we don't expect that this
     571             :      * is a performance-critical path.)  As in the unlink code, we want to be
     572             :      * sure the message is sent before we start changing things on-disk.
     573             :      */
     574         676 :     CacheInvalidateSmgr(reln->smgr_rnode);
     575             : 
     576             :     /* Do the truncation */
     577        1524 :     for (i = 0; i < nforks; i++)
     578             :     {
     579         848 :         smgrsw[reln->smgr_which].smgr_truncate(reln, forknum[i], nblocks[i]);
     580             : 
     581             :         /*
     582             :          * We might as well update the local smgr_fsm_nblocks and
     583             :          * smgr_vm_nblocks settings. The smgr cache inval message that this
     584             :          * function sent will cause other backends to invalidate their copies
     585             :          * of smgr_fsm_nblocks and smgr_vm_nblocks, and these ones too at the
     586             :          * next command boundary. But these ensure they aren't outright wrong
     587             :          * until then.
     588             :          */
     589         848 :         if (forknum[i] == FSM_FORKNUM)
     590         120 :             reln->smgr_fsm_nblocks = nblocks[i];
     591         848 :         if (forknum[i] == VISIBILITYMAP_FORKNUM)
     592          54 :             reln->smgr_vm_nblocks = nblocks[i];
     593             :     }
     594         676 : }
     595             : 
     596             : /*
     597             :  *  smgrimmedsync() -- Force the specified relation to stable storage.
     598             :  *
     599             :  *      Synchronously force all previous writes to the specified relation
     600             :  *      down to disk.
     601             :  *
     602             :  *      This is useful for building completely new relations (eg, new
     603             :  *      indexes).  Instead of incrementally WAL-logging the index build
     604             :  *      steps, we can just write completed index pages to disk with smgrwrite
     605             :  *      or smgrextend, and then fsync the completed index file before
     606             :  *      committing the transaction.  (This is sufficient for purposes of
     607             :  *      crash recovery, since it effectively duplicates forcing a checkpoint
     608             :  *      for the completed index.  But it is *not* sufficient if one wishes
     609             :  *      to use the WAL log for PITR or replication purposes: in that case
     610             :  *      we have to make WAL entries as well.)
     611             :  *
     612             :  *      The preceding writes should specify skipFsync = true to avoid
     613             :  *      duplicative fsyncs.
     614             :  *
     615             :  *      Note that you need to do FlushRelationBuffers() first if there is
     616             :  *      any possibility that there are dirty buffers for the relation;
     617             :  *      otherwise the sync is not very meaningful.
     618             :  */
     619             : void
     620       70630 : smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
     621             : {
     622       70630 :     smgrsw[reln->smgr_which].smgr_immedsync(reln, forknum);
     623       70630 : }
     624             : 
     625             : /*
     626             :  * AtEOXact_SMgr
     627             :  *
     628             :  * This routine is called during transaction commit or abort (it doesn't
     629             :  * particularly care which).  All transient SMgrRelation objects are closed.
     630             :  *
     631             :  * We do this as a compromise between wanting transient SMgrRelations to
     632             :  * live awhile (to amortize the costs of blind writes of multiple blocks)
     633             :  * and needing them to not live forever (since we're probably holding open
     634             :  * a kernel file descriptor for the underlying file, and we need to ensure
     635             :  * that gets closed reasonably soon if the file gets deleted).
     636             :  */
     637             : void
     638      495204 : AtEOXact_SMgr(void)
     639             : {
     640             :     dlist_mutable_iter iter;
     641             : 
     642             :     /*
     643             :      * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
     644             :      * one from the list.
     645             :      */
     646      502658 :     dlist_foreach_modify(iter, &unowned_relns)
     647             :     {
     648        7454 :         SMgrRelation rel = dlist_container(SMgrRelationData, node,
     649             :                                            iter.cur);
     650             : 
     651             :         Assert(rel->smgr_owner == NULL);
     652             : 
     653        7454 :         smgrclose(rel);
     654             :     }
     655      495204 : }

Generated by: LCOV version 1.13