Header And Logo

PostgreSQL
| The world's most advanced open source database.

smgr.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * smgr.c
00004  *    public interface routines to storage manager switch.
00005  *
00006  *    All file system operations in POSTGRES dispatch through these
00007  *    routines.
00008  *
00009  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00010  * Portions Copyright (c) 1994, Regents of the University of California
00011  *
00012  *
00013  * IDENTIFICATION
00014  *    src/backend/storage/smgr/smgr.c
00015  *
00016  *-------------------------------------------------------------------------
00017  */
00018 #include "postgres.h"
00019 
00020 #include "commands/tablespace.h"
00021 #include "storage/bufmgr.h"
00022 #include "storage/ipc.h"
00023 #include "storage/smgr.h"
00024 #include "utils/hsearch.h"
00025 #include "utils/inval.h"
00026 
00027 
00028 /*
00029  * This struct of function pointers defines the API between smgr.c and
00030  * any individual storage manager module.  Note that smgr subfunctions are
00031  * generally expected to report problems via elog(ERROR).  An exception is
00032  * that smgr_unlink should use elog(WARNING), rather than erroring out,
00033  * because we normally unlink relations during post-commit/abort cleanup,
00034  * and so it's too late to raise an error.  Also, various conditions that
00035  * would normally be errors should be allowed during bootstrap and/or WAL
00036  * recovery --- see comments in md.c for details.
00037  */
00038 typedef struct f_smgr
00039 {
00040     void        (*smgr_init) (void);    /* may be NULL */
00041     void        (*smgr_shutdown) (void);        /* may be NULL */
00042     void        (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
00043     void        (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
00044                                             bool isRedo);
00045     bool        (*smgr_exists) (SMgrRelation reln, ForkNumber forknum);
00046     void        (*smgr_unlink) (RelFileNodeBackend rnode, ForkNumber forknum,
00047                                             bool isRedo);
00048     void        (*smgr_extend) (SMgrRelation reln, ForkNumber forknum,
00049                          BlockNumber blocknum, char *buffer, bool skipFsync);
00050     void        (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
00051                                               BlockNumber blocknum);
00052     void        (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
00053                                           BlockNumber blocknum, char *buffer);
00054     void        (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
00055                          BlockNumber blocknum, char *buffer, bool skipFsync);
00056     BlockNumber (*smgr_nblocks) (SMgrRelation reln, ForkNumber forknum);
00057     void        (*smgr_truncate) (SMgrRelation reln, ForkNumber forknum,
00058                                               BlockNumber nblocks);
00059     void        (*smgr_immedsync) (SMgrRelation reln, ForkNumber forknum);
00060     void        (*smgr_pre_ckpt) (void);        /* may be NULL */
00061     void        (*smgr_sync) (void);    /* may be NULL */
00062     void        (*smgr_post_ckpt) (void);       /* may be NULL */
00063 } f_smgr;
00064 
00065 
00066 static const f_smgr smgrsw[] = {
00067     /* magnetic disk */
00068     {mdinit, NULL, mdclose, mdcreate, mdexists, mdunlink, mdextend,
00069         mdprefetch, mdread, mdwrite, mdnblocks, mdtruncate, mdimmedsync,
00070         mdpreckpt, mdsync, mdpostckpt
00071     }
00072 };
00073 
00074 static const int NSmgr = lengthof(smgrsw);
00075 
00076 
00077 /*
00078  * Each backend has a hashtable that stores all extant SMgrRelation objects.
00079  * In addition, "unowned" SMgrRelation objects are chained together in a list.
00080  */
00081 static HTAB *SMgrRelationHash = NULL;
00082 
00083 static SMgrRelation first_unowned_reln = NULL;
00084 
00085 /* local function prototypes */
00086 static void smgrshutdown(int code, Datum arg);
00087 static void remove_from_unowned_list(SMgrRelation reln);
00088 
00089 
00090 /*
00091  *  smgrinit(), smgrshutdown() -- Initialize or shut down storage
00092  *                                managers.
00093  *
00094  * Note: smgrinit is called during backend startup (normal or standalone
00095  * case), *not* during postmaster start.  Therefore, any resources created
00096  * here or destroyed in smgrshutdown are backend-local.
00097  */
00098 void
00099 smgrinit(void)
00100 {
00101     int         i;
00102 
00103     for (i = 0; i < NSmgr; i++)
00104     {
00105         if (smgrsw[i].smgr_init)
00106             (*(smgrsw[i].smgr_init)) ();
00107     }
00108 
00109     /* register the shutdown proc */
00110     on_proc_exit(smgrshutdown, 0);
00111 }
00112 
00113 /*
00114  * on_proc_exit hook for smgr cleanup during backend shutdown
00115  */
00116 static void
00117 smgrshutdown(int code, Datum arg)
00118 {
00119     int         i;
00120 
00121     for (i = 0; i < NSmgr; i++)
00122     {
00123         if (smgrsw[i].smgr_shutdown)
00124             (*(smgrsw[i].smgr_shutdown)) ();
00125     }
00126 }
00127 
00128 /*
00129  *  smgropen() -- Return an SMgrRelation object, creating it if need be.
00130  *
00131  *      This does not attempt to actually open the underlying file.
00132  */
00133 SMgrRelation
00134 smgropen(RelFileNode rnode, BackendId backend)
00135 {
00136     RelFileNodeBackend brnode;
00137     SMgrRelation reln;
00138     bool        found;
00139 
00140     if (SMgrRelationHash == NULL)
00141     {
00142         /* First time through: initialize the hash table */
00143         HASHCTL     ctl;
00144 
00145         MemSet(&ctl, 0, sizeof(ctl));
00146         ctl.keysize = sizeof(RelFileNodeBackend);
00147         ctl.entrysize = sizeof(SMgrRelationData);
00148         ctl.hash = tag_hash;
00149         SMgrRelationHash = hash_create("smgr relation table", 400,
00150                                        &ctl, HASH_ELEM | HASH_FUNCTION);
00151         first_unowned_reln = NULL;
00152     }
00153 
00154     /* Look up or create an entry */
00155     brnode.node = rnode;
00156     brnode.backend = backend;
00157     reln = (SMgrRelation) hash_search(SMgrRelationHash,
00158                                       (void *) &brnode,
00159                                       HASH_ENTER, &found);
00160 
00161     /* Initialize it if not present before */
00162     if (!found)
00163     {
00164         int         forknum;
00165 
00166         /* hash_search already filled in the lookup key */
00167         reln->smgr_owner = NULL;
00168         reln->smgr_targblock = InvalidBlockNumber;
00169         reln->smgr_fsm_nblocks = InvalidBlockNumber;
00170         reln->smgr_vm_nblocks = InvalidBlockNumber;
00171         reln->smgr_which = 0;   /* we only have md.c at present */
00172 
00173         /* mark it not open */
00174         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
00175             reln->md_fd[forknum] = NULL;
00176 
00177         /* place it at head of unowned list (to make smgrsetowner cheap) */
00178         reln->next_unowned_reln = first_unowned_reln;
00179         first_unowned_reln = reln;
00180     }
00181 
00182     return reln;
00183 }
00184 
00185 /*
00186  * smgrsetowner() -- Establish a long-lived reference to an SMgrRelation object
00187  *
00188  * There can be only one owner at a time; this is sufficient since currently
00189  * the only such owners exist in the relcache.
00190  */
00191 void
00192 smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
00193 {
00194     /* We don't currently support "disowning" an SMgrRelation here */
00195     Assert(owner != NULL);
00196 
00197     /*
00198      * First, unhook any old owner.  (Normally there shouldn't be any, but it
00199      * seems possible that this can happen during swap_relation_files()
00200      * depending on the order of processing.  It's ok to close the old
00201      * relcache entry early in that case.)
00202      *
00203      * If there isn't an old owner, then the reln should be in the unowned
00204      * list, and we need to remove it.
00205      */
00206     if (reln->smgr_owner)
00207         *(reln->smgr_owner) = NULL;
00208     else
00209         remove_from_unowned_list(reln);
00210 
00211     /* Now establish the ownership relationship. */
00212     reln->smgr_owner = owner;
00213     *owner = reln;
00214 }
00215 
00216 /*
00217  * remove_from_unowned_list -- unlink an SMgrRelation from the unowned list
00218  *
00219  * If the reln is not present in the list, nothing happens.  Typically this
00220  * would be caller error, but there seems no reason to throw an error.
00221  *
00222  * In the worst case this could be rather slow; but in all the cases that seem
00223  * likely to be performance-critical, the reln being sought will actually be
00224  * first in the list.  Furthermore, the number of unowned relns touched in any
00225  * one transaction shouldn't be all that high typically.  So it doesn't seem
00226  * worth expending the additional space and management logic needed for a
00227  * doubly-linked list.
00228  */
00229 static void
00230 remove_from_unowned_list(SMgrRelation reln)
00231 {
00232     SMgrRelation *link;
00233     SMgrRelation cur;
00234 
00235     for (link = &first_unowned_reln, cur = *link;
00236          cur != NULL;
00237          link = &cur->next_unowned_reln, cur = *link)
00238     {
00239         if (cur == reln)
00240         {
00241             *link = cur->next_unowned_reln;
00242             cur->next_unowned_reln = NULL;
00243             break;
00244         }
00245     }
00246 }
00247 
00248 /*
00249  *  smgrexists() -- Does the underlying file for a fork exist?
00250  */
00251 bool
00252 smgrexists(SMgrRelation reln, ForkNumber forknum)
00253 {
00254     return (*(smgrsw[reln->smgr_which].smgr_exists)) (reln, forknum);
00255 }
00256 
00257 /*
00258  *  smgrclose() -- Close and delete an SMgrRelation object.
00259  */
00260 void
00261 smgrclose(SMgrRelation reln)
00262 {
00263     SMgrRelation *owner;
00264     ForkNumber  forknum;
00265 
00266     for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
00267         (*(smgrsw[reln->smgr_which].smgr_close)) (reln, forknum);
00268 
00269     owner = reln->smgr_owner;
00270 
00271     if (!owner)
00272         remove_from_unowned_list(reln);
00273 
00274     if (hash_search(SMgrRelationHash,
00275                     (void *) &(reln->smgr_rnode),
00276                     HASH_REMOVE, NULL) == NULL)
00277         elog(ERROR, "SMgrRelation hashtable corrupted");
00278 
00279     /*
00280      * Unhook the owner pointer, if any.  We do this last since in the remote
00281      * possibility of failure above, the SMgrRelation object will still exist.
00282      */
00283     if (owner)
00284         *owner = NULL;
00285 }
00286 
00287 /*
00288  *  smgrcloseall() -- Close all existing SMgrRelation objects.
00289  */
00290 void
00291 smgrcloseall(void)
00292 {
00293     HASH_SEQ_STATUS status;
00294     SMgrRelation reln;
00295 
00296     /* Nothing to do if hashtable not set up */
00297     if (SMgrRelationHash == NULL)
00298         return;
00299 
00300     hash_seq_init(&status, SMgrRelationHash);
00301 
00302     while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
00303         smgrclose(reln);
00304 }
00305 
00306 /*
00307  *  smgrclosenode() -- Close SMgrRelation object for given RelFileNode,
00308  *                     if one exists.
00309  *
00310  * This has the same effects as smgrclose(smgropen(rnode)), but it avoids
00311  * uselessly creating a hashtable entry only to drop it again when no
00312  * such entry exists already.
00313  */
00314 void
00315 smgrclosenode(RelFileNodeBackend rnode)
00316 {
00317     SMgrRelation reln;
00318 
00319     /* Nothing to do if hashtable not set up */
00320     if (SMgrRelationHash == NULL)
00321         return;
00322 
00323     reln = (SMgrRelation) hash_search(SMgrRelationHash,
00324                                       (void *) &rnode,
00325                                       HASH_FIND, NULL);
00326     if (reln != NULL)
00327         smgrclose(reln);
00328 }
00329 
00330 /*
00331  *  smgrcreate() -- Create a new relation.
00332  *
00333  *      Given an already-created (but presumably unused) SMgrRelation,
00334  *      cause the underlying disk file or other storage for the fork
00335  *      to be created.
00336  *
00337  *      If isRedo is true, it is okay for the underlying file to exist
00338  *      already because we are in a WAL replay sequence.
00339  */
00340 void
00341 smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
00342 {
00343     /*
00344      * Exit quickly in WAL replay mode if we've already opened the file. If
00345      * it's open, it surely must exist.
00346      */
00347     if (isRedo && reln->md_fd[forknum] != NULL)
00348         return;
00349 
00350     /*
00351      * We may be using the target table space for the first time in this
00352      * database, so create a per-database subdirectory if needed.
00353      *
00354      * XXX this is a fairly ugly violation of module layering, but this seems
00355      * to be the best place to put the check.  Maybe TablespaceCreateDbspace
00356      * should be here and not in commands/tablespace.c?  But that would imply
00357      * importing a lot of stuff that smgr.c oughtn't know, either.
00358      */
00359     TablespaceCreateDbspace(reln->smgr_rnode.node.spcNode,
00360                             reln->smgr_rnode.node.dbNode,
00361                             isRedo);
00362 
00363     (*(smgrsw[reln->smgr_which].smgr_create)) (reln, forknum, isRedo);
00364 }
00365 
00366 /*
00367  *  smgrdounlink() -- Immediately unlink all forks of a relation.
00368  *
00369  *      All forks of the relation are removed from the store.  This should
00370  *      not be used during transactional operations, since it can't be undone.
00371  *
00372  *      If isRedo is true, it is okay for the underlying file(s) to be gone
00373  *      already.
00374  *
00375  *      This is equivalent to calling smgrdounlinkfork for each fork, but
00376  *      it's significantly quicker so should be preferred when possible.
00377  */
00378 void
00379 smgrdounlink(SMgrRelation reln, bool isRedo)
00380 {
00381     RelFileNodeBackend rnode = reln->smgr_rnode;
00382     int         which = reln->smgr_which;
00383     ForkNumber  forknum;
00384 
00385     /* Close the forks at smgr level */
00386     for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
00387         (*(smgrsw[which].smgr_close)) (reln, forknum);
00388 
00389     /*
00390      * Get rid of any remaining buffers for the relation.  bufmgr will just
00391      * drop them without bothering to write the contents.
00392      */
00393     DropRelFileNodesAllBuffers(&rnode, 1);
00394 
00395     /*
00396      * It'd be nice to tell the stats collector to forget it immediately, too.
00397      * But we can't because we don't know the OID (and in cases involving
00398      * relfilenode swaps, it's not always clear which table OID to forget,
00399      * anyway).
00400      */
00401 
00402     /*
00403      * Send a shared-inval message to force other backends to close any
00404      * dangling smgr references they may have for this rel.  We should do this
00405      * before starting the actual unlinking, in case we fail partway through
00406      * that step.  Note that the sinval message will eventually come back to
00407      * this backend, too, and thereby provide a backstop that we closed our
00408      * own smgr rel.
00409      */
00410     CacheInvalidateSmgr(rnode);
00411 
00412     /*
00413      * Delete the physical file(s).
00414      *
00415      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
00416      * ERROR, because we've already decided to commit or abort the current
00417      * xact.
00418      */
00419     (*(smgrsw[which].smgr_unlink)) (rnode, InvalidForkNumber, isRedo);
00420 }
00421 
00422 /*
00423  *  smgrdounlinkall() -- Immediately unlink all forks of all given relations
00424  *
00425  *      All forks of all given relations are removed from the store.  This
00426  *      should not be used during transactional operations, since it can't be
00427  *      undone.
00428  *
00429  *      If isRedo is true, it is okay for the underlying file(s) to be gone
00430  *      already.
00431  *
00432  *      This is equivalent to calling smgrdounlink for each relation, but it's
00433  *      significantly quicker so should be preferred when possible.
00434  */
00435 void
00436 smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
00437 {
00438     int     i = 0;
00439     RelFileNodeBackend *rnodes;
00440     ForkNumber  forknum;
00441 
00442     if (nrels == 0)
00443         return;
00444 
00445     /*
00446      * create an array which contains all relations to be dropped, and
00447      * close each relation's forks at the smgr level while at it
00448      */
00449     rnodes = palloc(sizeof(RelFileNodeBackend) * nrels);
00450     for (i = 0; i < nrels; i++)
00451     {
00452         RelFileNodeBackend rnode = rels[i]->smgr_rnode;
00453         int         which = rels[i]->smgr_which;
00454 
00455         rnodes[i] = rnode;
00456 
00457         /* Close the forks at smgr level */
00458         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
00459             (*(smgrsw[which].smgr_close)) (rels[i], forknum);
00460     }
00461 
00462     /*
00463      * Get rid of any remaining buffers for the relations.  bufmgr will just
00464      * drop them without bothering to write the contents.
00465      */
00466     DropRelFileNodesAllBuffers(rnodes, nrels);
00467 
00468     /*
00469      * It'd be nice to tell the stats collector to forget them immediately, too.
00470      * But we can't because we don't know the OIDs.
00471      */
00472 
00473     /*
00474      * Send a shared-inval message to force other backends to close any
00475      * dangling smgr references they may have for these rels.  We should do
00476      * this before starting the actual unlinking, in case we fail partway
00477      * through that step.  Note that the sinval messages will eventually come
00478      * back to this backend, too, and thereby provide a backstop that we closed
00479      * our own smgr rel.
00480      */
00481     for (i = 0; i < nrels; i++)
00482         CacheInvalidateSmgr(rnodes[i]);
00483 
00484     /*
00485      * Delete the physical file(s).
00486      *
00487      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
00488      * ERROR, because we've already decided to commit or abort the current
00489      * xact.
00490      */
00491 
00492     for (i = 0; i < nrels; i++)
00493     {
00494         int which = rels[i]->smgr_which;
00495         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
00496             (*(smgrsw[which].smgr_unlink)) (rnodes[i], forknum, isRedo);
00497     }
00498 
00499     pfree(rnodes);
00500 }
00501 
00502 /*
00503  *  smgrdounlinkfork() -- Immediately unlink one fork of a relation.
00504  *
00505  *      The specified fork of the relation is removed from the store.  This
00506  *      should not be used during transactional operations, since it can't be
00507  *      undone.
00508  *
00509  *      If isRedo is true, it is okay for the underlying file to be gone
00510  *      already.
00511  */
00512 void
00513 smgrdounlinkfork(SMgrRelation reln, ForkNumber forknum, bool isRedo)
00514 {
00515     RelFileNodeBackend rnode = reln->smgr_rnode;
00516     int         which = reln->smgr_which;
00517 
00518     /* Close the fork at smgr level */
00519     (*(smgrsw[which].smgr_close)) (reln, forknum);
00520 
00521     /*
00522      * Get rid of any remaining buffers for the fork.  bufmgr will just drop
00523      * them without bothering to write the contents.
00524      */
00525     DropRelFileNodeBuffers(rnode, forknum, 0);
00526 
00527     /*
00528      * It'd be nice to tell the stats collector to forget it immediately, too.
00529      * But we can't because we don't know the OID (and in cases involving
00530      * relfilenode swaps, it's not always clear which table OID to forget,
00531      * anyway).
00532      */
00533 
00534     /*
00535      * Send a shared-inval message to force other backends to close any
00536      * dangling smgr references they may have for this rel.  We should do this
00537      * before starting the actual unlinking, in case we fail partway through
00538      * that step.  Note that the sinval message will eventually come back to
00539      * this backend, too, and thereby provide a backstop that we closed our
00540      * own smgr rel.
00541      */
00542     CacheInvalidateSmgr(rnode);
00543 
00544     /*
00545      * Delete the physical file(s).
00546      *
00547      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
00548      * ERROR, because we've already decided to commit or abort the current
00549      * xact.
00550      */
00551     (*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
00552 }
00553 
00554 /*
00555  *  smgrextend() -- Add a new block to a file.
00556  *
00557  *      The semantics are nearly the same as smgrwrite(): write at the
00558  *      specified position.  However, this is to be used for the case of
00559  *      extending a relation (i.e., blocknum is at or beyond the current
00560  *      EOF).  Note that we assume writing a block beyond current EOF
00561  *      causes intervening file space to become filled with zeroes.
00562  */
00563 void
00564 smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
00565            char *buffer, bool skipFsync)
00566 {
00567     (*(smgrsw[reln->smgr_which].smgr_extend)) (reln, forknum, blocknum,
00568                                                buffer, skipFsync);
00569 }
00570 
00571 /*
00572  *  smgrprefetch() -- Initiate asynchronous read of the specified block of a relation.
00573  */
00574 void
00575 smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
00576 {
00577     (*(smgrsw[reln->smgr_which].smgr_prefetch)) (reln, forknum, blocknum);
00578 }
00579 
00580 /*
00581  *  smgrread() -- read a particular block from a relation into the supplied
00582  *                buffer.
00583  *
00584  *      This routine is called from the buffer manager in order to
00585  *      instantiate pages in the shared buffer cache.  All storage managers
00586  *      return pages in the format that POSTGRES expects.
00587  */
00588 void
00589 smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
00590          char *buffer)
00591 {
00592     (*(smgrsw[reln->smgr_which].smgr_read)) (reln, forknum, blocknum, buffer);
00593 }
00594 
00595 /*
00596  *  smgrwrite() -- Write the supplied buffer out.
00597  *
00598  *      This is to be used only for updating already-existing blocks of a
00599  *      relation (ie, those before the current EOF).  To extend a relation,
00600  *      use smgrextend().
00601  *
00602  *      This is not a synchronous write -- the block is not necessarily
00603  *      on disk at return, only dumped out to the kernel.  However,
00604  *      provisions will be made to fsync the write before the next checkpoint.
00605  *
00606  *      skipFsync indicates that the caller will make other provisions to
00607  *      fsync the relation, so we needn't bother.  Temporary relations also
00608  *      do not require fsync.
00609  */
00610 void
00611 smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
00612           char *buffer, bool skipFsync)
00613 {
00614     (*(smgrsw[reln->smgr_which].smgr_write)) (reln, forknum, blocknum,
00615                                               buffer, skipFsync);
00616 }
00617 
00618 /*
00619  *  smgrnblocks() -- Calculate the number of blocks in the
00620  *                   supplied relation.
00621  */
00622 BlockNumber
00623 smgrnblocks(SMgrRelation reln, ForkNumber forknum)
00624 {
00625     return (*(smgrsw[reln->smgr_which].smgr_nblocks)) (reln, forknum);
00626 }
00627 
00628 /*
00629  *  smgrtruncate() -- Truncate supplied relation to the specified number
00630  *                    of blocks
00631  *
00632  * The truncation is done immediately, so this can't be rolled back.
00633  */
00634 void
00635 smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
00636 {
00637     /*
00638      * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
00639      * just drop them without bothering to write the contents.
00640      */
00641     DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nblocks);
00642 
00643     /*
00644      * Send a shared-inval message to force other backends to close any smgr
00645      * references they may have for this rel.  This is useful because they
00646      * might have open file pointers to segments that got removed, and/or
00647      * smgr_targblock variables pointing past the new rel end.  (The inval
00648      * message will come back to our backend, too, causing a
00649      * probably-unnecessary local smgr flush.  But we don't expect that this
00650      * is a performance-critical path.)  As in the unlink code, we want to be
00651      * sure the message is sent before we start changing things on-disk.
00652      */
00653     CacheInvalidateSmgr(reln->smgr_rnode);
00654 
00655     /*
00656      * Do the truncation.
00657      */
00658     (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, forknum, nblocks);
00659 }
00660 
00661 /*
00662  *  smgrimmedsync() -- Force the specified relation to stable storage.
00663  *
00664  *      Synchronously force all previous writes to the specified relation
00665  *      down to disk.
00666  *
00667  *      This is useful for building completely new relations (eg, new
00668  *      indexes).  Instead of incrementally WAL-logging the index build
00669  *      steps, we can just write completed index pages to disk with smgrwrite
00670  *      or smgrextend, and then fsync the completed index file before
00671  *      committing the transaction.  (This is sufficient for purposes of
00672  *      crash recovery, since it effectively duplicates forcing a checkpoint
00673  *      for the completed index.  But it is *not* sufficient if one wishes
00674  *      to use the WAL log for PITR or replication purposes: in that case
00675  *      we have to make WAL entries as well.)
00676  *
00677  *      The preceding writes should specify skipFsync = true to avoid
00678  *      duplicative fsyncs.
00679  *
00680  *      Note that you need to do FlushRelationBuffers() first if there is
00681  *      any possibility that there are dirty buffers for the relation;
00682  *      otherwise the sync is not very meaningful.
00683  */
00684 void
00685 smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
00686 {
00687     (*(smgrsw[reln->smgr_which].smgr_immedsync)) (reln, forknum);
00688 }
00689 
00690 
00691 /*
00692  *  smgrpreckpt() -- Prepare for checkpoint.
00693  */
00694 void
00695 smgrpreckpt(void)
00696 {
00697     int         i;
00698 
00699     for (i = 0; i < NSmgr; i++)
00700     {
00701         if (smgrsw[i].smgr_pre_ckpt)
00702             (*(smgrsw[i].smgr_pre_ckpt)) ();
00703     }
00704 }
00705 
00706 /*
00707  *  smgrsync() -- Sync files to disk during checkpoint.
00708  */
00709 void
00710 smgrsync(void)
00711 {
00712     int         i;
00713 
00714     for (i = 0; i < NSmgr; i++)
00715     {
00716         if (smgrsw[i].smgr_sync)
00717             (*(smgrsw[i].smgr_sync)) ();
00718     }
00719 }
00720 
00721 /*
00722  *  smgrpostckpt() -- Post-checkpoint cleanup.
00723  */
00724 void
00725 smgrpostckpt(void)
00726 {
00727     int         i;
00728 
00729     for (i = 0; i < NSmgr; i++)
00730     {
00731         if (smgrsw[i].smgr_post_ckpt)
00732             (*(smgrsw[i].smgr_post_ckpt)) ();
00733     }
00734 }
00735 
00736 /*
00737  * AtEOXact_SMgr
00738  *
00739  * This routine is called during transaction commit or abort (it doesn't
00740  * particularly care which).  All transient SMgrRelation objects are closed.
00741  *
00742  * We do this as a compromise between wanting transient SMgrRelations to
00743  * live awhile (to amortize the costs of blind writes of multiple blocks)
00744  * and needing them to not live forever (since we're probably holding open
00745  * a kernel file descriptor for the underlying file, and we need to ensure
00746  * that gets closed reasonably soon if the file gets deleted).
00747  */
00748 void
00749 AtEOXact_SMgr(void)
00750 {
00751     /*
00752      * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
00753      * one from the list.
00754      */
00755     while (first_unowned_reln != NULL)
00756     {
00757         Assert(first_unowned_reln->smgr_owner == NULL);
00758         smgrclose(first_unowned_reln);
00759     }
00760 }