LCOV - code coverage report
Current view: top level - src/backend/storage/smgr - smgr.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 118 130 90.8 %
Date: 2019-09-22 07:07:17 Functions: 20 21 95.2 %
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-2019, 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             :     void        (*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       12372 : smgrinit(void)
     111             : {
     112             :     int         i;
     113             : 
     114       24744 :     for (i = 0; i < NSmgr; i++)
     115             :     {
     116       12372 :         if (smgrsw[i].smgr_init)
     117       12372 :             smgrsw[i].smgr_init();
     118             :     }
     119             : 
     120             :     /* register the shutdown proc */
     121       12372 :     on_proc_exit(smgrshutdown, 0);
     122       12372 : }
     123             : 
     124             : /*
     125             :  * on_proc_exit hook for smgr cleanup during backend shutdown
     126             :  */
     127             : static void
     128       12372 : smgrshutdown(int code, Datum arg)
     129             : {
     130             :     int         i;
     131             : 
     132       24744 :     for (i = 0; i < NSmgr; i++)
     133             :     {
     134       12372 :         if (smgrsw[i].smgr_shutdown)
     135           0 :             smgrsw[i].smgr_shutdown();
     136             :     }
     137       12372 : }
     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     2353468 : smgropen(RelFileNode rnode, BackendId backend)
     146             : {
     147             :     RelFileNodeBackend brnode;
     148             :     SMgrRelation reln;
     149             :     bool        found;
     150             : 
     151     2353468 :     if (SMgrRelationHash == NULL)
     152             :     {
     153             :         /* First time through: initialize the hash table */
     154             :         HASHCTL     ctl;
     155             : 
     156       10308 :         MemSet(&ctl, 0, sizeof(ctl));
     157       10308 :         ctl.keysize = sizeof(RelFileNodeBackend);
     158       10308 :         ctl.entrysize = sizeof(SMgrRelationData);
     159       10308 :         SMgrRelationHash = hash_create("smgr relation table", 400,
     160             :                                        &ctl, HASH_ELEM | HASH_BLOBS);
     161       10308 :         dlist_init(&unowned_relns);
     162             :     }
     163             : 
     164             :     /* Look up or create an entry */
     165     2353468 :     brnode.node = rnode;
     166     2353468 :     brnode.backend = backend;
     167     2353468 :     reln = (SMgrRelation) hash_search(SMgrRelationHash,
     168             :                                       (void *) &brnode,
     169             :                                       HASH_ENTER, &found);
     170             : 
     171             :     /* Initialize it if not present before */
     172     2353468 :     if (!found)
     173             :     {
     174             :         /* hash_search already filled in the lookup key */
     175     1203008 :         reln->smgr_owner = NULL;
     176     1203008 :         reln->smgr_targblock = InvalidBlockNumber;
     177     1203008 :         reln->smgr_fsm_nblocks = InvalidBlockNumber;
     178     1203008 :         reln->smgr_vm_nblocks = InvalidBlockNumber;
     179     1203008 :         reln->smgr_which = 0;    /* we only have md.c at present */
     180             : 
     181             :         /* implementation-specific initialization */
     182     1203008 :         smgrsw[reln->smgr_which].smgr_open(reln);
     183             : 
     184             :         /* it has no owner yet */
     185     1203008 :         dlist_push_tail(&unowned_relns, &reln->node);
     186             :     }
     187             : 
     188     2353468 :     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     1115732 : 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     1115732 :     if (reln->smgr_owner)
     213           4 :         *(reln->smgr_owner) = NULL;
     214             :     else
     215     1115728 :         dlist_delete(&reln->node);
     216             : 
     217             :     /* Now establish the ownership relationship. */
     218     1115732 :     reln->smgr_owner = owner;
     219     1115732 :     *owner = reln;
     220     1115732 : }
     221             : 
     222             : /*
     223             :  * smgrclearowner() -- Remove long-lived reference to an SMgrRelation object
     224             :  *                     if one exists
     225             :  */
     226             : void
     227         274 : smgrclearowner(SMgrRelation *owner, SMgrRelation reln)
     228             : {
     229             :     /* Do nothing if the SMgrRelation object is not owned by the owner */
     230         274 :     if (reln->smgr_owner != owner)
     231           0 :         return;
     232             : 
     233             :     /* unset the owner's reference */
     234         274 :     *owner = NULL;
     235             : 
     236             :     /* unset our reference to the owner */
     237         274 :     reln->smgr_owner = NULL;
     238             : 
     239             :     /* add to list of unowned relations */
     240         274 :     dlist_push_tail(&unowned_relns, &reln->node);
     241             : }
     242             : 
     243             : /*
     244             :  *  smgrexists() -- Does the underlying file for a fork exist?
     245             :  */
     246             : bool
     247      397778 : smgrexists(SMgrRelation reln, ForkNumber forknum)
     248             : {
     249      397778 :     return smgrsw[reln->smgr_which].smgr_exists(reln, forknum);
     250             : }
     251             : 
     252             : /*
     253             :  *  smgrclose() -- Close and delete an SMgrRelation object.
     254             :  */
     255             : void
     256      777684 : smgrclose(SMgrRelation reln)
     257             : {
     258             :     SMgrRelation *owner;
     259             :     ForkNumber  forknum;
     260             : 
     261     3888420 :     for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     262     3110736 :         smgrsw[reln->smgr_which].smgr_close(reln, forknum);
     263             : 
     264      777684 :     owner = reln->smgr_owner;
     265             : 
     266      777684 :     if (!owner)
     267       70330 :         dlist_delete(&reln->node);
     268             : 
     269      777684 :     if (hash_search(SMgrRelationHash,
     270      777684 :                     (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      777684 :     if (owner)
     279      707354 :         *owner = NULL;
     280      777684 : }
     281             : 
     282             : /*
     283             :  *  smgrcloseall() -- Close all existing SMgrRelation objects.
     284             :  */
     285             : void
     286        4486 : smgrcloseall(void)
     287             : {
     288             :     HASH_SEQ_STATUS status;
     289             :     SMgrRelation reln;
     290             : 
     291             :     /* Nothing to do if hashtable not set up */
     292        4486 :     if (SMgrRelationHash == NULL)
     293         318 :         return;
     294             : 
     295        4168 :     hash_seq_init(&status, SMgrRelationHash);
     296             : 
     297       85682 :     while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
     298       77346 :         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      203294 : smgrclosenode(RelFileNodeBackend rnode)
     311             : {
     312             :     SMgrRelation reln;
     313             : 
     314             :     /* Nothing to do if hashtable not set up */
     315      203294 :     if (SMgrRelationHash == NULL)
     316         168 :         return;
     317             : 
     318      203126 :     reln = (SMgrRelation) hash_search(SMgrRelationHash,
     319             :                                       (void *) &rnode,
     320             :                                       HASH_FIND, NULL);
     321      203126 :     if (reln != NULL)
     322       15678 :         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      385458 : smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
     334             : {
     335      385458 :     smgrsw[reln->smgr_which].smgr_create(reln, forknum, isRedo);
     336      385458 : }
     337             : 
     338             : /*
     339             :  *  smgrdounlink() -- Immediately unlink all forks of a relation.
     340             :  *
     341             :  *      All forks of the relation are removed from the store.  This should
     342             :  *      not be used during transactional operations, since it can't be undone.
     343             :  *
     344             :  *      If isRedo is true, it is okay for the underlying file(s) to be gone
     345             :  *      already.
     346             :  */
     347             : void
     348           0 : smgrdounlink(SMgrRelation reln, bool isRedo)
     349             : {
     350           0 :     RelFileNodeBackend rnode = reln->smgr_rnode;
     351           0 :     int         which = reln->smgr_which;
     352             :     ForkNumber  forknum;
     353             : 
     354             :     /* Close the forks at smgr level */
     355           0 :     for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     356           0 :         smgrsw[which].smgr_close(reln, forknum);
     357             : 
     358             :     /*
     359             :      * Get rid of any remaining buffers for the relation.  bufmgr will just
     360             :      * drop them without bothering to write the contents.
     361             :      */
     362           0 :     DropRelFileNodesAllBuffers(&rnode, 1);
     363             : 
     364             :     /*
     365             :      * It'd be nice to tell the stats collector to forget it immediately, too.
     366             :      * But we can't because we don't know the OID (and in cases involving
     367             :      * relfilenode swaps, it's not always clear which table OID to forget,
     368             :      * anyway).
     369             :      */
     370             : 
     371             :     /*
     372             :      * Send a shared-inval message to force other backends to close any
     373             :      * dangling smgr references they may have for this rel.  We should do this
     374             :      * before starting the actual unlinking, in case we fail partway through
     375             :      * that step.  Note that the sinval message will eventually come back to
     376             :      * this backend, too, and thereby provide a backstop that we closed our
     377             :      * own smgr rel.
     378             :      */
     379           0 :     CacheInvalidateSmgr(rnode);
     380             : 
     381             :     /*
     382             :      * Delete the physical file(s).
     383             :      *
     384             :      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     385             :      * ERROR, because we've already decided to commit or abort the current
     386             :      * xact.
     387             :      */
     388           0 :     smgrsw[which].smgr_unlink(rnode, InvalidForkNumber, isRedo);
     389           0 : }
     390             : 
     391             : /*
     392             :  *  smgrdounlinkall() -- Immediately unlink all forks of all given relations
     393             :  *
     394             :  *      All forks of all given relations are removed from the store.  This
     395             :  *      should not be used during transactional operations, since it can't be
     396             :  *      undone.
     397             :  *
     398             :  *      If isRedo is true, it is okay for the underlying file(s) to be gone
     399             :  *      already.
     400             :  *
     401             :  *      This is equivalent to calling smgrdounlink for each relation, but it's
     402             :  *      significantly quicker so should be preferred when possible.
     403             :  */
     404             : void
     405       12282 : smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
     406             : {
     407       12282 :     int         i = 0;
     408             :     RelFileNodeBackend *rnodes;
     409             :     ForkNumber  forknum;
     410             : 
     411       12282 :     if (nrels == 0)
     412          66 :         return;
     413             : 
     414             :     /*
     415             :      * create an array which contains all relations to be dropped, and close
     416             :      * each relation's forks at the smgr level while at it
     417             :      */
     418       12216 :     rnodes = palloc(sizeof(RelFileNodeBackend) * nrels);
     419       53656 :     for (i = 0; i < nrels; i++)
     420             :     {
     421       41440 :         RelFileNodeBackend rnode = rels[i]->smgr_rnode;
     422       41440 :         int         which = rels[i]->smgr_which;
     423             : 
     424       41440 :         rnodes[i] = rnode;
     425             : 
     426             :         /* Close the forks at smgr level */
     427      207200 :         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     428      165760 :             smgrsw[which].smgr_close(rels[i], forknum);
     429             :     }
     430             : 
     431             :     /*
     432             :      * Get rid of any remaining buffers for the relations.  bufmgr will just
     433             :      * drop them without bothering to write the contents.
     434             :      */
     435       12216 :     DropRelFileNodesAllBuffers(rnodes, nrels);
     436             : 
     437             :     /*
     438             :      * It'd be nice to tell the stats collector to forget them immediately,
     439             :      * too. But we can't because we don't know the OIDs.
     440             :      */
     441             : 
     442             :     /*
     443             :      * Send a shared-inval message to force other backends to close any
     444             :      * dangling smgr references they may have for these rels.  We should do
     445             :      * this before starting the actual unlinking, in case we fail partway
     446             :      * through that step.  Note that the sinval messages will eventually come
     447             :      * back to this backend, too, and thereby provide a backstop that we
     448             :      * closed our own smgr rel.
     449             :      */
     450       53656 :     for (i = 0; i < nrels; i++)
     451       41440 :         CacheInvalidateSmgr(rnodes[i]);
     452             : 
     453             :     /*
     454             :      * Delete the physical file(s).
     455             :      *
     456             :      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     457             :      * ERROR, because we've already decided to commit or abort the current
     458             :      * xact.
     459             :      */
     460             : 
     461       53656 :     for (i = 0; i < nrels; i++)
     462             :     {
     463       41440 :         int         which = rels[i]->smgr_which;
     464             : 
     465      207200 :         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     466      165760 :             smgrsw[which].smgr_unlink(rnodes[i], forknum, isRedo);
     467             :     }
     468             : 
     469       12216 :     pfree(rnodes);
     470             : }
     471             : 
     472             : /*
     473             :  *  smgrextend() -- Add a new block to a file.
     474             :  *
     475             :  *      The semantics are nearly the same as smgrwrite(): write at the
     476             :  *      specified position.  However, this is to be used for the case of
     477             :  *      extending a relation (i.e., blocknum is at or beyond the current
     478             :  *      EOF).  Note that we assume writing a block beyond current EOF
     479             :  *      causes intervening file space to become filled with zeroes.
     480             :  */
     481             : void
     482      555426 : smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     483             :            char *buffer, bool skipFsync)
     484             : {
     485      555426 :     smgrsw[reln->smgr_which].smgr_extend(reln, forknum, blocknum,
     486             :                                          buffer, skipFsync);
     487      555426 : }
     488             : 
     489             : /*
     490             :  *  smgrprefetch() -- Initiate asynchronous read of the specified block of a relation.
     491             :  */
     492             : void
     493          84 : smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
     494             : {
     495          84 :     smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum);
     496          84 : }
     497             : 
     498             : /*
     499             :  *  smgrread() -- read a particular block from a relation into the supplied
     500             :  *                buffer.
     501             :  *
     502             :  *      This routine is called from the buffer manager in order to
     503             :  *      instantiate pages in the shared buffer cache.  All storage managers
     504             :  *      return pages in the format that POSTGRES expects.
     505             :  */
     506             : void
     507      469836 : smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     508             :          char *buffer)
     509             : {
     510      469836 :     smgrsw[reln->smgr_which].smgr_read(reln, forknum, blocknum, buffer);
     511      469836 : }
     512             : 
     513             : /*
     514             :  *  smgrwrite() -- Write the supplied buffer out.
     515             :  *
     516             :  *      This is to be used only for updating already-existing blocks of a
     517             :  *      relation (ie, those before the current EOF).  To extend a relation,
     518             :  *      use smgrextend().
     519             :  *
     520             :  *      This is not a synchronous write -- the block is not necessarily
     521             :  *      on disk at return, only dumped out to the kernel.  However,
     522             :  *      provisions will be made to fsync the write before the next checkpoint.
     523             :  *
     524             :  *      skipFsync indicates that the caller will make other provisions to
     525             :  *      fsync the relation, so we needn't bother.  Temporary relations also
     526             :  *      do not require fsync.
     527             :  */
     528             : void
     529      501042 : smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     530             :           char *buffer, bool skipFsync)
     531             : {
     532      501042 :     smgrsw[reln->smgr_which].smgr_write(reln, forknum, blocknum,
     533             :                                         buffer, skipFsync);
     534      501042 : }
     535             : 
     536             : 
     537             : /*
     538             :  *  smgrwriteback() -- Trigger kernel writeback for the supplied range of
     539             :  *                     blocks.
     540             :  */
     541             : void
     542      152984 : smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     543             :               BlockNumber nblocks)
     544             : {
     545      152984 :     smgrsw[reln->smgr_which].smgr_writeback(reln, forknum, blocknum,
     546             :                                             nblocks);
     547      152984 : }
     548             : 
     549             : /*
     550             :  *  smgrnblocks() -- Calculate the number of blocks in the
     551             :  *                   supplied relation.
     552             :  */
     553             : BlockNumber
     554     3627578 : smgrnblocks(SMgrRelation reln, ForkNumber forknum)
     555             : {
     556     3627578 :     return smgrsw[reln->smgr_which].smgr_nblocks(reln, forknum);
     557             : }
     558             : 
     559             : /*
     560             :  *  smgrtruncate() -- Truncate supplied relation to the specified number
     561             :  *                    of blocks
     562             :  *
     563             :  * The truncation is done immediately, so this can't be rolled back.
     564             :  */
     565             : void
     566         612 : smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
     567             : {
     568             :     /*
     569             :      * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
     570             :      * just drop them without bothering to write the contents.
     571             :      */
     572         612 :     DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nblocks);
     573             : 
     574             :     /*
     575             :      * Send a shared-inval message to force other backends to close any smgr
     576             :      * references they may have for this rel.  This is useful because they
     577             :      * might have open file pointers to segments that got removed, and/or
     578             :      * smgr_targblock variables pointing past the new rel end.  (The inval
     579             :      * message will come back to our backend, too, causing a
     580             :      * probably-unnecessary local smgr flush.  But we don't expect that this
     581             :      * is a performance-critical path.)  As in the unlink code, we want to be
     582             :      * sure the message is sent before we start changing things on-disk.
     583             :      */
     584         612 :     CacheInvalidateSmgr(reln->smgr_rnode);
     585             : 
     586             :     /*
     587             :      * Do the truncation.
     588             :      */
     589         612 :     smgrsw[reln->smgr_which].smgr_truncate(reln, forknum, nblocks);
     590         612 : }
     591             : 
     592             : /*
     593             :  *  smgrimmedsync() -- Force the specified relation to stable storage.
     594             :  *
     595             :  *      Synchronously force all previous writes to the specified relation
     596             :  *      down to disk.
     597             :  *
     598             :  *      This is useful for building completely new relations (eg, new
     599             :  *      indexes).  Instead of incrementally WAL-logging the index build
     600             :  *      steps, we can just write completed index pages to disk with smgrwrite
     601             :  *      or smgrextend, and then fsync the completed index file before
     602             :  *      committing the transaction.  (This is sufficient for purposes of
     603             :  *      crash recovery, since it effectively duplicates forcing a checkpoint
     604             :  *      for the completed index.  But it is *not* sufficient if one wishes
     605             :  *      to use the WAL log for PITR or replication purposes: in that case
     606             :  *      we have to make WAL entries as well.)
     607             :  *
     608             :  *      The preceding writes should specify skipFsync = true to avoid
     609             :  *      duplicative fsyncs.
     610             :  *
     611             :  *      Note that you need to do FlushRelationBuffers() first if there is
     612             :  *      any possibility that there are dirty buffers for the relation;
     613             :  *      otherwise the sync is not very meaningful.
     614             :  */
     615             : void
     616       70620 : smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
     617             : {
     618       70620 :     smgrsw[reln->smgr_which].smgr_immedsync(reln, forknum);
     619       70620 : }
     620             : 
     621             : /*
     622             :  * AtEOXact_SMgr
     623             :  *
     624             :  * This routine is called during transaction commit or abort (it doesn't
     625             :  * particularly care which).  All transient SMgrRelation objects are closed.
     626             :  *
     627             :  * We do this as a compromise between wanting transient SMgrRelations to
     628             :  * live awhile (to amortize the costs of blind writes of multiple blocks)
     629             :  * and needing them to not live forever (since we're probably holding open
     630             :  * a kernel file descriptor for the underlying file, and we need to ensure
     631             :  * that gets closed reasonably soon if the file gets deleted).
     632             :  */
     633             : void
     634      459844 : AtEOXact_SMgr(void)
     635             : {
     636             :     dlist_mutable_iter iter;
     637             : 
     638             :     /*
     639             :      * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
     640             :      * one from the list.
     641             :      */
     642      461156 :     dlist_foreach_modify(iter, &unowned_relns)
     643             :     {
     644        1312 :         SMgrRelation rel = dlist_container(SMgrRelationData, node,
     645             :                                            iter.cur);
     646             : 
     647             :         Assert(rel->smgr_owner == NULL);
     648             : 
     649        1312 :         smgrclose(rel);
     650             :     }
     651      459844 : }

Generated by: LCOV version 1.13