PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
smgr.h File Reference
#include "fmgr.h"
#include "storage/block.h"
#include "storage/relfilenode.h"
Include dependency graph for smgr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SMgrRelationData
 

Macros

#define SmgrIsTemp(smgr)   RelFileNodeBackendIsTemp((smgr)->smgr_rnode)
 

Typedefs

typedef struct SMgrRelationData SMgrRelationData
 
typedef SMgrRelationDataSMgrRelation
 

Functions

void smgrinit (void)
 
SMgrRelation smgropen (RelFileNode rnode, BackendId backend)
 
bool smgrexists (SMgrRelation reln, ForkNumber forknum)
 
void smgrsetowner (SMgrRelation *owner, SMgrRelation reln)
 
void smgrclearowner (SMgrRelation *owner, SMgrRelation reln)
 
void smgrclose (SMgrRelation reln)
 
void smgrcloseall (void)
 
void smgrclosenode (RelFileNodeBackend rnode)
 
void smgrcreate (SMgrRelation reln, ForkNumber forknum, bool isRedo)
 
void smgrdounlink (SMgrRelation reln, bool isRedo)
 
void smgrdounlinkall (SMgrRelation *rels, int nrels, bool isRedo)
 
void smgrdounlinkfork (SMgrRelation reln, ForkNumber forknum, bool isRedo)
 
void smgrextend (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
 
void smgrprefetch (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
 
void smgrread (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
 
void smgrwrite (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
 
void smgrwriteback (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
 
BlockNumber smgrnblocks (SMgrRelation reln, ForkNumber forknum)
 
void smgrtruncate (SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
 
void smgrimmedsync (SMgrRelation reln, ForkNumber forknum)
 
void smgrpreckpt (void)
 
void smgrsync (void)
 
void smgrpostckpt (void)
 
void AtEOXact_SMgr (void)
 
void mdinit (void)
 
void mdclose (SMgrRelation reln, ForkNumber forknum)
 
void mdcreate (SMgrRelation reln, ForkNumber forknum, bool isRedo)
 
bool mdexists (SMgrRelation reln, ForkNumber forknum)
 
void mdunlink (RelFileNodeBackend rnode, ForkNumber forknum, bool isRedo)
 
void mdextend (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
 
void mdprefetch (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
 
void mdread (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
 
void mdwrite (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
 
void mdwriteback (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
 
BlockNumber mdnblocks (SMgrRelation reln, ForkNumber forknum)
 
void mdtruncate (SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
 
void mdimmedsync (SMgrRelation reln, ForkNumber forknum)
 
void mdpreckpt (void)
 
void mdsync (void)
 
void mdpostckpt (void)
 
void SetForwardFsyncRequests (void)
 
void RememberFsyncRequest (RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
 
void ForgetRelationFsyncRequests (RelFileNode rnode, ForkNumber forknum)
 
void ForgetDatabaseFsyncRequests (Oid dbid)
 

Macro Definition Documentation

#define SmgrIsTemp (   smgr)    RelFileNodeBackendIsTemp((smgr)->smgr_rnode)

Definition at line 80 of file smgr.h.

Referenced by mdextend(), mdtruncate(), mdwrite(), ReadBuffer_common(), and register_dirty_segment().

Typedef Documentation

Definition at line 78 of file smgr.h.

Function Documentation

void AtEOXact_SMgr ( void  )

Definition at line 798 of file smgr.c.

References Assert, NULL, SMgrRelationData::smgr_owner, and smgrclose().

Referenced by AbortTransaction(), BackgroundWriterMain(), CheckpointerMain(), CommitTransaction(), PrepareTransaction(), and WalWriterMain().

799 {
800  /*
801  * Zap all unowned SMgrRelations. We rely on smgrclose() to remove each
802  * one from the list.
803  */
804  while (first_unowned_reln != NULL)
805  {
808  }
809 }
void smgrclose(SMgrRelation reln)
Definition: smgr.c:296
struct SMgrRelationData ** smgr_owner
Definition: smgr.h:46
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static SMgrRelation first_unowned_reln
Definition: smgr.c:85
void ForgetDatabaseFsyncRequests ( Oid  dbid)

Definition at line 1684 of file md.c.

References RelFileNode::dbNode, FORGET_DATABASE_FSYNC, ForwardFsyncRequest(), InvalidForkNumber, IsUnderPostmaster, pg_usleep(), RelFileNode::relNode, RememberFsyncRequest(), and RelFileNode::spcNode.

Referenced by dbase_redo(), and dropdb().

1685 {
1686  RelFileNode rnode;
1687 
1688  rnode.dbNode = dbid;
1689  rnode.spcNode = 0;
1690  rnode.relNode = 0;
1691 
1692  if (pendingOpsTable)
1693  {
1694  /* standalone backend or startup process: fsync state is local */
1696  }
1697  else if (IsUnderPostmaster)
1698  {
1699  /* see notes in ForgetRelationFsyncRequests */
1700  while (!ForwardFsyncRequest(rnode, InvalidForkNumber,
1702  pg_usleep(10000L); /* 10 msec seems a good number */
1703  }
1704 }
void RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1513
bool ForwardFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
static HTAB * pendingOpsTable
Definition: md.c:154
void pg_usleep(long microsec)
Definition: signal.c:53
#define FORGET_DATABASE_FSYNC
Definition: md.c:54
bool IsUnderPostmaster
Definition: globals.c:100
void ForgetRelationFsyncRequests ( RelFileNode  rnode,
ForkNumber  forknum 
)

Definition at line 1651 of file md.c.

References FORGET_RELATION_FSYNC, ForwardFsyncRequest(), IsUnderPostmaster, pg_usleep(), and RememberFsyncRequest().

Referenced by mdunlink().

1652 {
1653  if (pendingOpsTable)
1654  {
1655  /* standalone backend or startup process: fsync state is local */
1657  }
1658  else if (IsUnderPostmaster)
1659  {
1660  /*
1661  * Notify the checkpointer about it. If we fail to queue the cancel
1662  * message, we have to sleep and try again ... ugly, but hopefully
1663  * won't happen often.
1664  *
1665  * XXX should we CHECK_FOR_INTERRUPTS in this loop? Escaping with an
1666  * error would leave the no-longer-used file still present on disk,
1667  * which would be bad, so I'm inclined to assume that the checkpointer
1668  * will always empty the queue soon.
1669  */
1670  while (!ForwardFsyncRequest(rnode, forknum, FORGET_RELATION_FSYNC))
1671  pg_usleep(10000L); /* 10 msec seems a good number */
1672 
1673  /*
1674  * Note we don't wait for the checkpointer to actually absorb the
1675  * cancel message; see mdsync() for the implications.
1676  */
1677  }
1678 }
void RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1513
bool ForwardFsyncRequest(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
static HTAB * pendingOpsTable
Definition: md.c:154
#define FORGET_RELATION_FSYNC
Definition: md.c:53
void pg_usleep(long microsec)
Definition: signal.c:53
bool IsUnderPostmaster
Definition: globals.c:100
void mdclose ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 627 of file md.c.

References _fdvec_resize(), FileClose(), SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, and _MdfdVec::mdfd_vfd.

Referenced by mdexists().

628 {
629  int nopensegs = reln->md_num_open_segs[forknum];
630 
631  /* No work if already closed */
632  if (nopensegs == 0)
633  return;
634 
635  /* close segments starting from the end */
636  while (nopensegs > 0)
637  {
638  MdfdVec *v = &reln->md_seg_fds[forknum][nopensegs - 1];
639 
640  /* if not closed already */
641  if (v->mdfd_vfd >= 0)
642  {
643  FileClose(v->mdfd_vfd);
644  v->mdfd_vfd = -1;
645  }
646 
647  nopensegs--;
648  }
649 
650  /* resize just once, avoids pointless reallocations */
651  _fdvec_resize(reln, forknum, 0);
652 }
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1711
Definition: md.c:108
void FileClose(File file)
Definition: fd.c:1456
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:71
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:72
File mdfd_vfd
Definition: md.c:110
void mdcreate ( SMgrRelation  reln,
ForkNumber  forknum,
bool  isRedo 
)

Definition at line 293 of file md.c.

References _fdvec_resize(), Assert, ereport, errcode_for_file_access(), errmsg(), ERROR, fd(), IsBootstrapProcessingMode, SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_segno, _MdfdVec::mdfd_vfd, PathNameOpenFile(), pfree(), PG_BINARY, relpath, and SMgrRelationData::smgr_rnode.

294 {
295  MdfdVec *mdfd;
296  char *path;
297  File fd;
298 
299  if (isRedo && reln->md_num_open_segs[forkNum] > 0)
300  return; /* created and opened already... */
301 
302  Assert(reln->md_num_open_segs[forkNum] == 0);
303 
304  path = relpath(reln->smgr_rnode, forkNum);
305 
306  fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, 0600);
307 
308  if (fd < 0)
309  {
310  int save_errno = errno;
311 
312  /*
313  * During bootstrap, there are cases where a system relation will be
314  * accessed (by internal backend processes) before the bootstrap
315  * script nominally creates it. Therefore, allow the file to exist
316  * already, even if isRedo is not set. (See also mdopen)
317  */
318  if (isRedo || IsBootstrapProcessingMode())
319  fd = PathNameOpenFile(path, O_RDWR | PG_BINARY, 0600);
320  if (fd < 0)
321  {
322  /* be sure to report the error reported by create, not open */
323  errno = save_errno;
324  ereport(ERROR,
326  errmsg("could not create file \"%s\": %m", path)));
327  }
328  }
329 
330  pfree(path);
331 
332  _fdvec_resize(reln, forkNum, 1);
333  mdfd = &reln->md_seg_fds[forkNum][0];
334  mdfd->mdfd_vfd = fd;
335  mdfd->mdfd_segno = 0;
336 }
File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
Definition: fd.c:1266
BlockNumber mdfd_segno
Definition: md.c:111
static int fd(const char *x, int i)
Definition: preproc-init.c:105
#define PG_BINARY
Definition: c.h:1038
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1711
Definition: md.c:108
#define Assert(condition)
Definition: c.h:671
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:71
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define relpath(rnode, forknum)
Definition: relpath.h:71
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:72
File mdfd_vfd
Definition: md.c:110
int File
Definition: fd.h:51
bool mdexists ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 276 of file md.c.

References EXTENSION_RETURN_NULL, mdclose(), mdopen(), and NULL.

277 {
278  /*
279  * Close it first, to ensure that we notice if the fork has been unlinked
280  * since we opened it.
281  */
282  mdclose(reln, forkNum);
283 
284  return (mdopen(reln, forkNum, EXTENSION_RETURN_NULL) != NULL);
285 }
#define EXTENSION_RETURN_NULL
Definition: md.c:166
static MdfdVec * mdopen(SMgrRelation reln, ForkNumber forknum, int behavior)
Definition: md.c:573
#define NULL
Definition: c.h:226
void mdclose(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:627
void mdextend ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer,
bool  skipFsync 
)

Definition at line 494 of file md.c.

References _mdfd_getseg(), _mdnblocks(), Assert, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, EXTENSION_CREATE, FilePathName(), FileSeek(), FileWrite(), InvalidBlockNumber, _MdfdVec::mdfd_vfd, mdnblocks(), register_dirty_segment(), relpath, SMgrRelationData::smgr_rnode, and SmgrIsTemp.

Referenced by _mdfd_getseg().

496 {
497  off_t seekpos;
498  int nbytes;
499  MdfdVec *v;
500 
501  /* This assert is too expensive to have on normally ... */
502 #ifdef CHECK_WRITE_VS_EXTEND
503  Assert(blocknum >= mdnblocks(reln, forknum));
504 #endif
505 
506  /*
507  * If a relation manages to grow to 2^32-1 blocks, refuse to extend it any
508  * more --- we mustn't create a block whose number actually is
509  * InvalidBlockNumber.
510  */
511  if (blocknum == InvalidBlockNumber)
512  ereport(ERROR,
513  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
514  errmsg("cannot extend file \"%s\" beyond %u blocks",
515  relpath(reln->smgr_rnode, forknum),
517 
518  v = _mdfd_getseg(reln, forknum, blocknum, skipFsync, EXTENSION_CREATE);
519 
520  seekpos = (off_t) BLCKSZ *(blocknum % ((BlockNumber) RELSEG_SIZE));
521 
522  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
523 
524  /*
525  * Note: because caller usually obtained blocknum by calling mdnblocks,
526  * which did a seek(SEEK_END), this seek is often redundant and will be
527  * optimized away by fd.c. It's not redundant, however, if there is a
528  * partial page at the end of the file. In that case we want to try to
529  * overwrite the partial page with a full page. It's also not redundant
530  * if bufmgr.c had to dump another buffer of the same file to make room
531  * for the new page's buffer.
532  */
533  if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)
534  ereport(ERROR,
536  errmsg("could not seek to block %u in file \"%s\": %m",
537  blocknum, FilePathName(v->mdfd_vfd))));
538 
539  if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ)
540  {
541  if (nbytes < 0)
542  ereport(ERROR,
544  errmsg("could not extend file \"%s\": %m",
545  FilePathName(v->mdfd_vfd)),
546  errhint("Check free disk space.")));
547  /* short write: complain appropriately */
548  ereport(ERROR,
549  (errcode(ERRCODE_DISK_FULL),
550  errmsg("could not extend file \"%s\": wrote only %d of %d bytes at block %u",
552  nbytes, BLCKSZ, blocknum),
553  errhint("Check free disk space.")));
554  }
555 
556  if (!skipFsync && !SmgrIsTemp(reln))
557  register_dirty_segment(reln, forknum, v);
558 
559  Assert(_mdnblocks(reln, forknum, v) <= ((BlockNumber) RELSEG_SIZE));
560 }
int FileWrite(File file, char *buffer, int amount)
Definition: fd.c:1666
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1812
int errhint(const char *fmt,...)
Definition: elog.c:987
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:872
int errcode(int sqlerrcode)
Definition: elog.c:575
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:1923
#define SmgrIsTemp(smgr)
Definition: smgr.h:80
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: md.c:108
#define EXTENSION_CREATE
Definition: md.c:168
#define Assert(condition)
Definition: c.h:671
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1940
#define InvalidBlockNumber
Definition: block.h:33
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define relpath(rnode, forknum)
Definition: relpath.h:71
off_t FileSeek(File file, off_t offset, int whence)
Definition: fd.c:1802
File mdfd_vfd
Definition: md.c:110
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1428
void mdimmedsync ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 1024 of file md.c.

References ereport, errcode_for_file_access(), errmsg(), ERROR, FilePathName(), FileSync(), SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_vfd, and mdnblocks().

1025 {
1026  int segno;
1027 
1028  /*
1029  * NOTE: mdnblocks makes sure we have opened all active segments, so that
1030  * fsync loop will get them all!
1031  */
1032  mdnblocks(reln, forknum);
1033 
1034  segno = reln->md_num_open_segs[forknum];
1035 
1036  while (segno > 0)
1037  {
1038  MdfdVec *v = &reln->md_seg_fds[forknum][segno - 1];
1039 
1040  if (FileSync(v->mdfd_vfd) < 0)
1041  ereport(ERROR,
1043  errmsg("could not fsync file \"%s\": %m",
1044  FilePathName(v->mdfd_vfd))));
1045  segno--;
1046  }
1047 }
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:872
int FileSync(File file)
Definition: fd.c:1785
char * FilePathName(File file)
Definition: fd.c:1923
#define ERROR
Definition: elog.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: md.c:108
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:71
int errmsg(const char *fmt,...)
Definition: elog.c:797
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:72
File mdfd_vfd
Definition: md.c:110
void mdinit ( void  )

Definition at line 205 of file md.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), AmCheckpointerProcess, AmStartupProcess, HASHCTL::entrysize, HASH_BLOBS, HASH_CONTEXT, hash_create(), HASH_ELEM, HASHCTL::hcxt, IsUnderPostmaster, HASHCTL::keysize, MemoryContextAllowInCriticalSection(), MemSet, NIL, pendingOpsCxt, and TopMemoryContext.

206 {
208  "MdSmgr",
210 
211  /*
212  * Create pending-operations hashtable if we need it. Currently, we need
213  * it if we are standalone (not under a postmaster) or if we are a startup
214  * or checkpointer auxiliary process.
215  */
217  {
218  HASHCTL hash_ctl;
219 
220  /*
221  * XXX: The checkpointer needs to add entries to the pending ops table
222  * when absorbing fsync requests. That is done within a critical
223  * section, which isn't usually allowed, but we make an exception. It
224  * means that there's a theoretical possibility that you run out of
225  * memory while absorbing fsync requests, which leads to a PANIC.
226  * Fortunately the hash table is small so that's unlikely to happen in
227  * practice.
228  */
230  "Pending ops context",
233 
234  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
235  hash_ctl.keysize = sizeof(RelFileNode);
236  hash_ctl.entrysize = sizeof(PendingOperationEntry);
237  hash_ctl.hcxt = pendingOpsCxt;
238  pendingOpsTable = hash_create("Pending Ops Table",
239  100L,
240  &hash_ctl,
243  }
244 }
#define NIL
Definition: pg_list.h:69
#define AmStartupProcess()
Definition: miscadmin.h:403
#define HASH_CONTEXT
Definition: hsearch.h:93
void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
Definition: mcxt.c:374
#define HASH_ELEM
Definition: hsearch.h:87
MemoryContext hcxt
Definition: hsearch.h:78
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:853
static HTAB * pendingOpsTable
Definition: md.c:154
static MemoryContext MdCxt
Definition: md.c:114
#define AmCheckpointerProcess()
Definition: miscadmin.h:405
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:145
struct RelFileNode RelFileNode
bool IsUnderPostmaster
Definition: globals.c:100
MemoryContext TopMemoryContext
Definition: mcxt.c:43
#define HASH_BLOBS
Definition: hsearch.h:88
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Size keysize
Definition: hsearch.h:72
static MemoryContext pendingOpsCxt
Definition: md.c:156
static List * pendingUnlinks
Definition: md.c:155
BlockNumber mdnblocks ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 872 of file md.c.

References _mdfd_openseg(), _mdnblocks(), Assert, elog, EXTENSION_FAIL, FATAL, SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, mdopen(), and NULL.

Referenced by mdextend(), mdimmedsync(), mdtruncate(), and mdwrite().

873 {
874  MdfdVec *v = mdopen(reln, forknum, EXTENSION_FAIL);
875  BlockNumber nblocks;
876  BlockNumber segno = 0;
877 
878  /* mdopen has opened the first segment */
879  Assert(reln->md_num_open_segs[forknum] > 0);
880 
881  /*
882  * Start from the last open segments, to avoid redundant seeks. We have
883  * previously verified that these segments are exactly RELSEG_SIZE long,
884  * and it's useless to recheck that each time.
885  *
886  * NOTE: this assumption could only be wrong if another backend has
887  * truncated the relation. We rely on higher code levels to handle that
888  * scenario by closing and re-opening the md fd, which is handled via
889  * relcache flush. (Since the checkpointer doesn't participate in
890  * relcache flush, it could have segment entries for inactive segments;
891  * that's OK because the checkpointer never needs to compute relation
892  * size.)
893  */
894  segno = reln->md_num_open_segs[forknum] - 1;
895  v = &reln->md_seg_fds[forknum][segno];
896 
897  for (;;)
898  {
899  nblocks = _mdnblocks(reln, forknum, v);
900  if (nblocks > ((BlockNumber) RELSEG_SIZE))
901  elog(FATAL, "segment too big");
902  if (nblocks < ((BlockNumber) RELSEG_SIZE))
903  return (segno * ((BlockNumber) RELSEG_SIZE)) + nblocks;
904 
905  /*
906  * If segment is exactly RELSEG_SIZE, advance to next one.
907  */
908  segno++;
909 
910  /*
911  * We used to pass O_CREAT here, but that's has the disadvantage that
912  * it might create a segment which has vanished through some operating
913  * system misadventure. In such a case, creating the segment here
914  * undermines _mdfd_getseg's attempts to notice and report an error
915  * upon access to a missing segment.
916  */
917  v = _mdfd_openseg(reln, forknum, segno, 0);
918  if (v == NULL)
919  return segno * ((BlockNumber) RELSEG_SIZE);
920  }
921 }
uint32 BlockNumber
Definition: block.h:31
#define EXTENSION_FAIL
Definition: md.c:164
#define FATAL
Definition: elog.h:52
static MdfdVec * mdopen(SMgrRelation reln, ForkNumber forknum, int behavior)
Definition: md.c:573
Definition: md.c:108
static MdfdVec * _mdfd_openseg(SMgrRelation reln, ForkNumber forkno, BlockNumber segno, int oflags)
Definition: md.c:1772
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static BlockNumber _mdnblocks(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1940
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:71
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:72
#define elog
Definition: elog.h:219
void mdpostckpt ( void  )

Definition at line 1360 of file md.c.

References AbsorbFsyncRequests(), PendingUnlinkEntry::cycle_ctr, ereport, errcode_for_file_access(), errmsg(), linitial, list_delete_first(), MAIN_FORKNUM, mdckpt_cycle_ctr, NIL, pfree(), relpathperm, PendingUnlinkEntry::rnode, unlink(), UNLINKS_PER_ABSORB, and WARNING.

1361 {
1362  int absorb_counter;
1363 
1364  absorb_counter = UNLINKS_PER_ABSORB;
1365  while (pendingUnlinks != NIL)
1366  {
1368  char *path;
1369 
1370  /*
1371  * New entries are appended to the end, so if the entry is new we've
1372  * reached the end of old entries.
1373  *
1374  * Note: if just the right number of consecutive checkpoints fail, we
1375  * could be fooled here by cycle_ctr wraparound. However, the only
1376  * consequence is that we'd delay unlinking for one more checkpoint,
1377  * which is perfectly tolerable.
1378  */
1379  if (entry->cycle_ctr == mdckpt_cycle_ctr)
1380  break;
1381 
1382  /* Unlink the file */
1383  path = relpathperm(entry->rnode, MAIN_FORKNUM);
1384  if (unlink(path) < 0)
1385  {
1386  /*
1387  * There's a race condition, when the database is dropped at the
1388  * same time that we process the pending unlink requests. If the
1389  * DROP DATABASE deletes the file before we do, we will get ENOENT
1390  * here. rmtree() also has to ignore ENOENT errors, to deal with
1391  * the possibility that we delete the file first.
1392  */
1393  if (errno != ENOENT)
1394  ereport(WARNING,
1396  errmsg("could not remove file \"%s\": %m", path)));
1397  }
1398  pfree(path);
1399 
1400  /* And remove the list entry */
1402  pfree(entry);
1403 
1404  /*
1405  * As in mdsync, we don't want to stop absorbing fsync requests for a
1406  * long time when there are many deletions to be done. We can safely
1407  * call AbsorbFsyncRequests() at this point in the loop (note it might
1408  * try to delete list entries).
1409  */
1410  if (--absorb_counter <= 0)
1411  {
1413  absorb_counter = UNLINKS_PER_ABSORB;
1414  }
1415  }
1416 }
#define NIL
Definition: pg_list.h:69
#define relpathperm(rnode, forknum)
Definition: relpath.h:67
CycleCtr cycle_ctr
Definition: md.c:151
static CycleCtr mdckpt_cycle_ctr
Definition: md.c:159
void pfree(void *pointer)
Definition: mcxt.c:992
#define linitial(l)
Definition: pg_list.h:110
RelFileNode rnode
Definition: md.c:150
int errcode_for_file_access(void)
Definition: elog.c:598
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:797
void AbsorbFsyncRequests(void)
#define UNLINKS_PER_ABSORB
Definition: md.c:44
static List * pendingUnlinks
Definition: md.c:155
List * list_delete_first(List *list)
Definition: list.c:666
void mdpreckpt ( void  )

Definition at line 1345 of file md.c.

References mdckpt_cycle_ctr.

1346 {
1347  /*
1348  * Any unlink requests arriving after this point will be assigned the next
1349  * cycle counter, and won't be unlinked until next checkpoint.
1350  */
1351  mdckpt_cycle_ctr++;
1352 }
static CycleCtr mdckpt_cycle_ctr
Definition: md.c:159
void mdprefetch ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum 
)

Definition at line 658 of file md.c.

References _mdfd_getseg(), Assert, EXTENSION_FAIL, FilePrefetch(), and _MdfdVec::mdfd_vfd.

659 {
660 #ifdef USE_PREFETCH
661  off_t seekpos;
662  MdfdVec *v;
663 
664  v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL);
665 
666  seekpos = (off_t) BLCKSZ *(blocknum % ((BlockNumber) RELSEG_SIZE));
667 
668  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
669 
670  (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ);
671 #endif /* USE_PREFETCH */
672 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1812
uint32 BlockNumber
Definition: block.h:31
#define EXTENSION_FAIL
Definition: md.c:164
int FilePrefetch(File file, off_t offset, int amount)
Definition: fd.c:1553
Definition: md.c:108
#define Assert(condition)
Definition: c.h:671
File mdfd_vfd
Definition: md.c:110
void mdread ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer 
)

Definition at line 730 of file md.c.

References _mdfd_getseg(), Assert, RelFileNodeBackend::backend, RelFileNode::dbNode, ereport, errcode(), errcode_for_file_access(), errmsg(), ERROR, EXTENSION_CREATE_RECOVERY, EXTENSION_FAIL, FilePathName(), FileRead(), FileSeek(), InRecovery, _MdfdVec::mdfd_vfd, MemSet, RelFileNodeBackend::node, RelFileNode::relNode, SMgrRelationData::smgr_rnode, RelFileNode::spcNode, and zero_damaged_pages.

732 {
733  off_t seekpos;
734  int nbytes;
735  MdfdVec *v;
736 
737  TRACE_POSTGRESQL_SMGR_MD_READ_START(forknum, blocknum,
738  reln->smgr_rnode.node.spcNode,
739  reln->smgr_rnode.node.dbNode,
740  reln->smgr_rnode.node.relNode,
741  reln->smgr_rnode.backend);
742 
743  v = _mdfd_getseg(reln, forknum, blocknum, false,
745 
746  seekpos = (off_t) BLCKSZ *(blocknum % ((BlockNumber) RELSEG_SIZE));
747 
748  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
749 
750  if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)
751  ereport(ERROR,
753  errmsg("could not seek to block %u in file \"%s\": %m",
754  blocknum, FilePathName(v->mdfd_vfd))));
755 
756  nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ);
757 
758  TRACE_POSTGRESQL_SMGR_MD_READ_DONE(forknum, blocknum,
759  reln->smgr_rnode.node.spcNode,
760  reln->smgr_rnode.node.dbNode,
761  reln->smgr_rnode.node.relNode,
762  reln->smgr_rnode.backend,
763  nbytes,
764  BLCKSZ);
765 
766  if (nbytes != BLCKSZ)
767  {
768  if (nbytes < 0)
769  ereport(ERROR,
771  errmsg("could not read block %u in file \"%s\": %m",
772  blocknum, FilePathName(v->mdfd_vfd))));
773 
774  /*
775  * Short read: we are at or past EOF, or we read a partial block at
776  * EOF. Normally this is an error; upper levels should never try to
777  * read a nonexistent block. However, if zero_damaged_pages is ON or
778  * we are InRecovery, we should instead return zeroes without
779  * complaining. This allows, for example, the case of trying to
780  * update a block that was later truncated away.
781  */
783  MemSet(buffer, 0, BLCKSZ);
784  else
785  ereport(ERROR,
786  (errcode(ERRCODE_DATA_CORRUPTED),
787  errmsg("could not read block %u in file \"%s\": read only %d of %d bytes",
788  blocknum, FilePathName(v->mdfd_vfd),
789  nbytes, BLCKSZ)));
790  }
791 }
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1812
bool InRecovery
Definition: xlog.c:191
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:853
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:1923
#define EXTENSION_FAIL
Definition: md.c:164
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
#define EXTENSION_CREATE_RECOVERY
Definition: md.c:170
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: md.c:108
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:671
BackendId backend
Definition: relfilenode.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:797
off_t FileSeek(File file, off_t offset, int whence)
Definition: fd.c:1802
File mdfd_vfd
Definition: md.c:110
int FileRead(File file, char *buffer, int amount)
Definition: fd.c:1604
bool zero_damaged_pages
Definition: bufmgr.c:108
void mdsync ( void  )

Definition at line 1053 of file md.c.

References _mdfd_getseg(), _mdfd_segpath(), AbsorbFsyncRequests(), Assert, bms_first_member(), bms_free(), PendingOperationEntry::canceled, CheckpointStats, CheckpointStatsData::ckpt_agg_sync_time, CheckpointStatsData::ckpt_longest_sync, CheckpointStatsData::ckpt_sync_rels, PendingOperationEntry::cycle_ctr, DEBUG1, elog, enableFsync, ereport, errcode_for_file_access(), errmsg(), ERROR, EXTENSION_DONT_CHECK_SIZE, EXTENSION_RETURN_NULL, FILE_POSSIBLY_DELETED, FilePathName(), FileSync(), FSYNCS_PER_ABSORB, HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), INSTR_TIME_GET_MICROSEC, INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, InvalidBackendId, log_checkpoints, longest(), MAX_FORKNUM, _MdfdVec::mdfd_vfd, mdsync_cycle_ctr, NULL, pfree(), PendingOperationEntry::requests, PendingOperationEntry::rnode, and smgropen().

Referenced by SetForwardFsyncRequests().

1054 {
1055  static bool mdsync_in_progress = false;
1056 
1057  HASH_SEQ_STATUS hstat;
1058  PendingOperationEntry *entry;
1059  int absorb_counter;
1060 
1061  /* Statistics on sync times */
1062  int processed = 0;
1063  instr_time sync_start,
1064  sync_end,
1065  sync_diff;
1066  uint64 elapsed;
1067  uint64 longest = 0;
1068  uint64 total_elapsed = 0;
1069 
1070  /*
1071  * This is only called during checkpoints, and checkpoints should only
1072  * occur in processes that have created a pendingOpsTable.
1073  */
1074  if (!pendingOpsTable)
1075  elog(ERROR, "cannot sync without a pendingOpsTable");
1076 
1077  /*
1078  * If we are in the checkpointer, the sync had better include all fsync
1079  * requests that were queued by backends up to this point. The tightest
1080  * race condition that could occur is that a buffer that must be written
1081  * and fsync'd for the checkpoint could have been dumped by a backend just
1082  * before it was visited by BufferSync(). We know the backend will have
1083  * queued an fsync request before clearing the buffer's dirtybit, so we
1084  * are safe as long as we do an Absorb after completing BufferSync().
1085  */
1087 
1088  /*
1089  * To avoid excess fsync'ing (in the worst case, maybe a never-terminating
1090  * checkpoint), we want to ignore fsync requests that are entered into the
1091  * hashtable after this point --- they should be processed next time,
1092  * instead. We use mdsync_cycle_ctr to tell old entries apart from new
1093  * ones: new ones will have cycle_ctr equal to the incremented value of
1094  * mdsync_cycle_ctr.
1095  *
1096  * In normal circumstances, all entries present in the table at this point
1097  * will have cycle_ctr exactly equal to the current (about to be old)
1098  * value of mdsync_cycle_ctr. However, if we fail partway through the
1099  * fsync'ing loop, then older values of cycle_ctr might remain when we
1100  * come back here to try again. Repeated checkpoint failures would
1101  * eventually wrap the counter around to the point where an old entry
1102  * might appear new, causing us to skip it, possibly allowing a checkpoint
1103  * to succeed that should not have. To forestall wraparound, any time the
1104  * previous mdsync() failed to complete, run through the table and
1105  * forcibly set cycle_ctr = mdsync_cycle_ctr.
1106  *
1107  * Think not to merge this loop with the main loop, as the problem is
1108  * exactly that that loop may fail before having visited all the entries.
1109  * From a performance point of view it doesn't matter anyway, as this path
1110  * will never be taken in a system that's functioning normally.
1111  */
1112  if (mdsync_in_progress)
1113  {
1114  /* prior try failed, so update any stale cycle_ctr values */
1115  hash_seq_init(&hstat, pendingOpsTable);
1116  while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
1117  {
1118  entry->cycle_ctr = mdsync_cycle_ctr;
1119  }
1120  }
1121 
1122  /* Advance counter so that new hashtable entries are distinguishable */
1123  mdsync_cycle_ctr++;
1124 
1125  /* Set flag to detect failure if we don't reach the end of the loop */
1126  mdsync_in_progress = true;
1127 
1128  /* Now scan the hashtable for fsync requests to process */
1129  absorb_counter = FSYNCS_PER_ABSORB;
1130  hash_seq_init(&hstat, pendingOpsTable);
1131  while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
1132  {
1133  ForkNumber forknum;
1134 
1135  /*
1136  * If the entry is new then don't process it this time; it might
1137  * contain multiple fsync-request bits, but they are all new. Note
1138  * "continue" bypasses the hash-remove call at the bottom of the loop.
1139  */
1140  if (entry->cycle_ctr == mdsync_cycle_ctr)
1141  continue;
1142 
1143  /* Else assert we haven't missed it */
1144  Assert((CycleCtr) (entry->cycle_ctr + 1) == mdsync_cycle_ctr);
1145 
1146  /*
1147  * Scan over the forks and segments represented by the entry.
1148  *
1149  * The bitmap manipulations are slightly tricky, because we can call
1150  * AbsorbFsyncRequests() inside the loop and that could result in
1151  * bms_add_member() modifying and even re-palloc'ing the bitmapsets.
1152  * This is okay because we unlink each bitmapset from the hashtable
1153  * entry before scanning it. That means that any incoming fsync
1154  * requests will be processed now if they reach the table before we
1155  * begin to scan their fork.
1156  */
1157  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
1158  {
1159  Bitmapset *requests = entry->requests[forknum];
1160  int segno;
1161 
1162  entry->requests[forknum] = NULL;
1163  entry->canceled[forknum] = false;
1164 
1165  while ((segno = bms_first_member(requests)) >= 0)
1166  {
1167  int failures;
1168 
1169  /*
1170  * If fsync is off then we don't have to bother opening the
1171  * file at all. (We delay checking until this point so that
1172  * changing fsync on the fly behaves sensibly.)
1173  */
1174  if (!enableFsync)
1175  continue;
1176 
1177  /*
1178  * If in checkpointer, we want to absorb pending requests
1179  * every so often to prevent overflow of the fsync request
1180  * queue. It is unspecified whether newly-added entries will
1181  * be visited by hash_seq_search, but we don't care since we
1182  * don't need to process them anyway.
1183  */
1184  if (--absorb_counter <= 0)
1185  {
1187  absorb_counter = FSYNCS_PER_ABSORB;
1188  }
1189 
1190  /*
1191  * The fsync table could contain requests to fsync segments
1192  * that have been deleted (unlinked) by the time we get to
1193  * them. Rather than just hoping an ENOENT (or EACCES on
1194  * Windows) error can be ignored, what we do on error is
1195  * absorb pending requests and then retry. Since mdunlink()
1196  * queues a "cancel" message before actually unlinking, the
1197  * fsync request is guaranteed to be marked canceled after the
1198  * absorb if it really was this case. DROP DATABASE likewise
1199  * has to tell us to forget fsync requests before it starts
1200  * deletions.
1201  */
1202  for (failures = 0;; failures++) /* loop exits at "break" */
1203  {
1204  SMgrRelation reln;
1205  MdfdVec *seg;
1206  char *path;
1207  int save_errno;
1208 
1209  /*
1210  * Find or create an smgr hash entry for this relation.
1211  * This may seem a bit unclean -- md calling smgr? But
1212  * it's really the best solution. It ensures that the
1213  * open file reference isn't permanently leaked if we get
1214  * an error here. (You may say "but an unreferenced
1215  * SMgrRelation is still a leak!" Not really, because the
1216  * only case in which a checkpoint is done by a process
1217  * that isn't about to shut down is in the checkpointer,
1218  * and it will periodically do smgrcloseall(). This fact
1219  * justifies our not closing the reln in the success path
1220  * either, which is a good thing since in non-checkpointer
1221  * cases we couldn't safely do that.)
1222  */
1223  reln = smgropen(entry->rnode, InvalidBackendId);
1224 
1225  /* Attempt to open and fsync the target segment */
1226  seg = _mdfd_getseg(reln, forknum,
1227  (BlockNumber) segno * (BlockNumber) RELSEG_SIZE,
1228  false,
1231 
1232  INSTR_TIME_SET_CURRENT(sync_start);
1233 
1234  if (seg != NULL &&
1235  FileSync(seg->mdfd_vfd) >= 0)
1236  {
1237  /* Success; update statistics about sync timing */
1238  INSTR_TIME_SET_CURRENT(sync_end);
1239  sync_diff = sync_end;
1240  INSTR_TIME_SUBTRACT(sync_diff, sync_start);
1241  elapsed = INSTR_TIME_GET_MICROSEC(sync_diff);
1242  if (elapsed > longest)
1243  longest = elapsed;
1244  total_elapsed += elapsed;
1245  processed++;
1246  if (log_checkpoints)
1247  elog(DEBUG1, "checkpoint sync: number=%d file=%s time=%.3f msec",
1248  processed,
1249  FilePathName(seg->mdfd_vfd),
1250  (double) elapsed / 1000);
1251 
1252  break; /* out of retry loop */
1253  }
1254 
1255  /* Compute file name for use in message */
1256  save_errno = errno;
1257  path = _mdfd_segpath(reln, forknum, (BlockNumber) segno);
1258  errno = save_errno;
1259 
1260  /*
1261  * It is possible that the relation has been dropped or
1262  * truncated since the fsync request was entered.
1263  * Therefore, allow ENOENT, but only if we didn't fail
1264  * already on this file. This applies both for
1265  * _mdfd_getseg() and for FileSync, since fd.c might have
1266  * closed the file behind our back.
1267  *
1268  * XXX is there any point in allowing more than one retry?
1269  * Don't see one at the moment, but easy to change the
1270  * test here if so.
1271  */
1272  if (!FILE_POSSIBLY_DELETED(errno) ||
1273  failures > 0)
1274  ereport(ERROR,
1276  errmsg("could not fsync file \"%s\": %m",
1277  path)));
1278  else
1279  ereport(DEBUG1,
1281  errmsg("could not fsync file \"%s\" but retrying: %m",
1282  path)));
1283  pfree(path);
1284 
1285  /*
1286  * Absorb incoming requests and check to see if a cancel
1287  * arrived for this relation fork.
1288  */
1290  absorb_counter = FSYNCS_PER_ABSORB; /* might as well... */
1291 
1292  if (entry->canceled[forknum])
1293  break;
1294  } /* end retry loop */
1295  }
1296  bms_free(requests);
1297  }
1298 
1299  /*
1300  * We've finished everything that was requested before we started to
1301  * scan the entry. If no new requests have been inserted meanwhile,
1302  * remove the entry. Otherwise, update its cycle counter, as all the
1303  * requests now in it must have arrived during this cycle.
1304  */
1305  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
1306  {
1307  if (entry->requests[forknum] != NULL)
1308  break;
1309  }
1310  if (forknum <= MAX_FORKNUM)
1311  entry->cycle_ctr = mdsync_cycle_ctr;
1312  else
1313  {
1314  /* Okay to remove it */
1315  if (hash_search(pendingOpsTable, &entry->rnode,
1316  HASH_REMOVE, NULL) == NULL)
1317  elog(ERROR, "pendingOpsTable corrupted");
1318  }
1319  } /* end loop over hashtable entries */
1320 
1321  /* Return sync performance metrics for report at checkpoint end */
1322  CheckpointStats.ckpt_sync_rels = processed;
1324  CheckpointStats.ckpt_agg_sync_time = total_elapsed;
1325 
1326  /* Flag successful completion of mdsync */
1327  mdsync_in_progress = false;
1328 }
uint64 ckpt_agg_sync_time
Definition: xlog.h:213
bool log_checkpoints
Definition: xlog.c:101
int bms_first_member(Bitmapset *a)
Definition: bitmapset.c:855
int ckpt_sync_rels
Definition: xlog.h:211
#define DEBUG1
Definition: elog.h:25
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1812
#define EXTENSION_DONT_CHECK_SIZE
Definition: md.c:178
static CycleCtr mdsync_cycle_ctr
Definition: md.c:158
#define FSYNCS_PER_ABSORB
Definition: md.c:43
struct timeval instr_time
Definition: instr_time.h:147
RelFileNode rnode
Definition: md.c:140
int FileSync(File file)
Definition: fd.c:1785
uint32 BlockNumber
Definition: block.h:31
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
char * FilePathName(File file)
Definition: fd.c:1923
CycleCtr cycle_ctr
Definition: md.c:141
static HTAB * pendingOpsTable
Definition: md.c:154
bool canceled[MAX_FORKNUM+1]
Definition: md.c:145
void pfree(void *pointer)
Definition: mcxt.c:992
#define ERROR
Definition: elog.h:43
#define EXTENSION_RETURN_NULL
Definition: md.c:166
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:167
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:137
ForkNumber
Definition: relpath.h:24
#define InvalidBackendId
Definition: backendid.h:23
Definition: md.c:108
void bms_free(Bitmapset *a)
Definition: bitmapset.c:200
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define INSTR_TIME_GET_MICROSEC(t)
Definition: instr_time.h:202
CheckpointStatsData CheckpointStats
Definition: xlog.c:172
#define MAX_FORKNUM
Definition: relpath.h:39
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:153
static chr * longest(struct vars *v, struct dfa *d, chr *start, chr *stop, int *hitstopp)
Definition: rege_dfa.c:42
bool enableFsync
Definition: globals.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:797
Bitmapset * requests[MAX_FORKNUM+1]
Definition: md.c:143
#define elog
Definition: elog.h:219
void AbsorbFsyncRequests(void)
File mdfd_vfd
Definition: md.c:110
uint16 CycleCtr
Definition: md.c:136
#define FILE_POSSIBLY_DELETED(err)
Definition: md.c:65
static char * _mdfd_segpath(SMgrRelation reln, ForkNumber forknum, BlockNumber segno)
Definition: md.c:1749
uint64 ckpt_longest_sync
Definition: xlog.h:212
void mdtruncate ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  nblocks 
)

Definition at line 927 of file md.c.

References _fdvec_resize(), Assert, ereport, errcode_for_file_access(), errmsg(), ERROR, FileClose(), FilePathName(), FileTruncate(), InRecovery, SMgrRelationData::md_num_open_segs, SMgrRelationData::md_seg_fds, _MdfdVec::mdfd_vfd, mdnblocks(), register_dirty_segment(), relpath, SMgrRelationData::smgr_rnode, and SmgrIsTemp.

928 {
929  BlockNumber curnblk;
930  BlockNumber priorblocks;
931  int curopensegs;
932 
933  /*
934  * NOTE: mdnblocks makes sure we have opened all active segments, so that
935  * truncation loop will get them all!
936  */
937  curnblk = mdnblocks(reln, forknum);
938  if (nblocks > curnblk)
939  {
940  /* Bogus request ... but no complaint if InRecovery */
941  if (InRecovery)
942  return;
943  ereport(ERROR,
944  (errmsg("could not truncate file \"%s\" to %u blocks: it's only %u blocks now",
945  relpath(reln->smgr_rnode, forknum),
946  nblocks, curnblk)));
947  }
948  if (nblocks == curnblk)
949  return; /* no work */
950 
951  /*
952  * Truncate segments, starting at the last one. Starting at the end makes
953  * managing the memory for the fd array easier, should there be errors.
954  */
955  curopensegs = reln->md_num_open_segs[forknum];
956  while (curopensegs > 0)
957  {
958  MdfdVec *v;
959 
960  priorblocks = (curopensegs - 1) * RELSEG_SIZE;
961 
962  v = &reln->md_seg_fds[forknum][curopensegs - 1];
963 
964  if (priorblocks > nblocks)
965  {
966  /*
967  * This segment is no longer active. We truncate the file, but do
968  * not delete it, for reasons explained in the header comments.
969  */
970  if (FileTruncate(v->mdfd_vfd, 0) < 0)
971  ereport(ERROR,
973  errmsg("could not truncate file \"%s\": %m",
974  FilePathName(v->mdfd_vfd))));
975 
976  if (!SmgrIsTemp(reln))
977  register_dirty_segment(reln, forknum, v);
978 
979  /* we never drop the 1st segment */
980  Assert(v != &reln->md_seg_fds[forknum][0]);
981 
982  FileClose(v->mdfd_vfd);
983  _fdvec_resize(reln, forknum, curopensegs - 1);
984  }
985  else if (priorblocks + ((BlockNumber) RELSEG_SIZE) > nblocks)
986  {
987  /*
988  * This is the last segment we want to keep. Truncate the file to
989  * the right length. NOTE: if nblocks is exactly a multiple K of
990  * RELSEG_SIZE, we will truncate the K+1st segment to 0 length but
991  * keep it. This adheres to the invariant given in the header
992  * comments.
993  */
994  BlockNumber lastsegblocks = nblocks - priorblocks;
995 
996  if (FileTruncate(v->mdfd_vfd, (off_t) lastsegblocks * BLCKSZ) < 0)
997  ereport(ERROR,
999  errmsg("could not truncate file \"%s\" to %u blocks: %m",
1000  FilePathName(v->mdfd_vfd),
1001  nblocks)));
1002  if (!SmgrIsTemp(reln))
1003  register_dirty_segment(reln, forknum, v);
1004  }
1005  else
1006  {
1007  /*
1008  * We still need this segment, so nothing to do for this and any
1009  * earlier segment.
1010  */
1011  break;
1012  }
1013  curopensegs--;
1014  }
1015 }
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:872
bool InRecovery
Definition: xlog.c:191
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:1923
#define SmgrIsTemp(smgr)
Definition: smgr.h:80
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int FileTruncate(File file, off_t offset)
Definition: fd.c:1890
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
static void _fdvec_resize(SMgrRelation reln, ForkNumber forknum, int nseg)
Definition: md.c:1711
Definition: md.c:108
void FileClose(File file)
Definition: fd.c:1456
#define Assert(condition)
Definition: c.h:671
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:71
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define relpath(rnode, forknum)
Definition: relpath.h:71
struct _MdfdVec * md_seg_fds[MAX_FORKNUM+1]
Definition: smgr.h:72
File mdfd_vfd
Definition: md.c:110
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1428
void mdunlink ( RelFileNodeBackend  rnode,
ForkNumber  forknum,
bool  isRedo 
)

Definition at line 386 of file md.c.

References ForgetRelationFsyncRequests(), InvalidForkNumber, MAX_FORKNUM, mdunlinkfork(), RelFileNodeBackend::node, and RelFileNodeBackendIsTemp.

387 {
388  /*
389  * We have to clean out any pending fsync requests for the doomed
390  * relation, else the next mdsync() will fail. There can't be any such
391  * requests for a temp relation, though. We can send just one request
392  * even when deleting multiple forks, since the fsync queuing code accepts
393  * the "InvalidForkNumber = all forks" convention.
394  */
395  if (!RelFileNodeBackendIsTemp(rnode))
396  ForgetRelationFsyncRequests(rnode.node, forkNum);
397 
398  /* Now do the per-fork work */
399  if (forkNum == InvalidForkNumber)
400  {
401  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
402  mdunlinkfork(rnode, forkNum, isRedo);
403  }
404  else
405  mdunlinkfork(rnode, forkNum, isRedo);
406 }
#define RelFileNodeBackendIsTemp(rnode)
Definition: relfilenode.h:78
void ForgetRelationFsyncRequests(RelFileNode rnode, ForkNumber forknum)
Definition: md.c:1651
static void mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
Definition: md.c:409
RelFileNode node
Definition: relfilenode.h:74
#define MAX_FORKNUM
Definition: relpath.h:39
void mdwrite ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer,
bool  skipFsync 
)

Definition at line 801 of file md.c.

References _mdfd_getseg(), Assert, RelFileNodeBackend::backend, RelFileNode::dbNode, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, EXTENSION_CREATE_RECOVERY, EXTENSION_FAIL, FilePathName(), FileSeek(), FileWrite(), _MdfdVec::mdfd_vfd, mdnblocks(), RelFileNodeBackend::node, register_dirty_segment(), RelFileNode::relNode, SMgrRelationData::smgr_rnode, SmgrIsTemp, and RelFileNode::spcNode.

803 {
804  off_t seekpos;
805  int nbytes;
806  MdfdVec *v;
807 
808  /* This assert is too expensive to have on normally ... */
809 #ifdef CHECK_WRITE_VS_EXTEND
810  Assert(blocknum < mdnblocks(reln, forknum));
811 #endif
812 
813  TRACE_POSTGRESQL_SMGR_MD_WRITE_START(forknum, blocknum,
814  reln->smgr_rnode.node.spcNode,
815  reln->smgr_rnode.node.dbNode,
816  reln->smgr_rnode.node.relNode,
817  reln->smgr_rnode.backend);
818 
819  v = _mdfd_getseg(reln, forknum, blocknum, skipFsync,
821 
822  seekpos = (off_t) BLCKSZ *(blocknum % ((BlockNumber) RELSEG_SIZE));
823 
824  Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
825 
826  if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)
827  ereport(ERROR,
829  errmsg("could not seek to block %u in file \"%s\": %m",
830  blocknum, FilePathName(v->mdfd_vfd))));
831 
832  nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ);
833 
834  TRACE_POSTGRESQL_SMGR_MD_WRITE_DONE(forknum, blocknum,
835  reln->smgr_rnode.node.spcNode,
836  reln->smgr_rnode.node.dbNode,
837  reln->smgr_rnode.node.relNode,
838  reln->smgr_rnode.backend,
839  nbytes,
840  BLCKSZ);
841 
842  if (nbytes != BLCKSZ)
843  {
844  if (nbytes < 0)
845  ereport(ERROR,
847  errmsg("could not write block %u in file \"%s\": %m",
848  blocknum, FilePathName(v->mdfd_vfd))));
849  /* short write: complain appropriately */
850  ereport(ERROR,
851  (errcode(ERRCODE_DISK_FULL),
852  errmsg("could not write block %u in file \"%s\": wrote only %d of %d bytes",
853  blocknum,
855  nbytes, BLCKSZ),
856  errhint("Check free disk space.")));
857  }
858 
859  if (!skipFsync && !SmgrIsTemp(reln))
860  register_dirty_segment(reln, forknum, v);
861 }
int FileWrite(File file, char *buffer, int amount)
Definition: fd.c:1666
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1812
int errhint(const char *fmt,...)
Definition: elog.c:987
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: md.c:872
int errcode(int sqlerrcode)
Definition: elog.c:575
uint32 BlockNumber
Definition: block.h:31
char * FilePathName(File file)
Definition: fd.c:1923
#define EXTENSION_FAIL
Definition: md.c:164
#define SmgrIsTemp(smgr)
Definition: smgr.h:80
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int errcode_for_file_access(void)
Definition: elog.c:598
#define EXTENSION_CREATE_RECOVERY
Definition: md.c:170
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: md.c:108
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:671
BackendId backend
Definition: relfilenode.h:75
int errmsg(const char *fmt,...)
Definition: elog.c:797
off_t FileSeek(File file, off_t offset, int whence)
Definition: fd.c:1802
File mdfd_vfd
Definition: md.c:110
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, MdfdVec *seg)
Definition: md.c:1428
void mdwriteback ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
BlockNumber  nblocks 
)

Definition at line 681 of file md.c.

References _mdfd_getseg(), Assert, EXTENSION_RETURN_NULL, FileWriteback(), and _MdfdVec::mdfd_vfd.

683 {
684  /*
685  * Issue flush requests in as few requests as possible; have to split at
686  * segment boundaries though, since those are actually separate files.
687  */
688  while (nblocks > 0)
689  {
690  BlockNumber nflush = nblocks;
691  off_t seekpos;
692  MdfdVec *v;
693  int segnum_start,
694  segnum_end;
695 
696  v = _mdfd_getseg(reln, forknum, blocknum, true /* not used */ ,
698 
699  /*
700  * We might be flushing buffers of already removed relations, that's
701  * ok, just ignore that case.
702  */
703  if (!v)
704  return;
705 
706  /* compute offset inside the current segment */
707  segnum_start = blocknum / RELSEG_SIZE;
708 
709  /* compute number of desired writes within the current segment */
710  segnum_end = (blocknum + nblocks - 1) / RELSEG_SIZE;
711  if (segnum_start != segnum_end)
712  nflush = RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE));
713 
714  Assert(nflush >= 1);
715  Assert(nflush <= nblocks);
716 
717  seekpos = (off_t) BLCKSZ *(blocknum % ((BlockNumber) RELSEG_SIZE));
718 
719  FileWriteback(v->mdfd_vfd, seekpos, (off_t) BLCKSZ * nflush);
720 
721  nblocks -= nflush;
722  blocknum += nflush;
723  }
724 }
void FileWriteback(File file, off_t offset, off_t nbytes)
Definition: fd.c:1579
static MdfdVec * _mdfd_getseg(SMgrRelation reln, ForkNumber forkno, BlockNumber blkno, bool skipFsync, int behavior)
Definition: md.c:1812
uint32 BlockNumber
Definition: block.h:31
#define EXTENSION_RETURN_NULL
Definition: md.c:166
Definition: md.c:108
#define Assert(condition)
Definition: c.h:671
File mdfd_vfd
Definition: md.c:110
void RememberFsyncRequest ( RelFileNode  rnode,
ForkNumber  forknum,
BlockNumber  segno 
)

Definition at line 1513 of file md.c.

References Assert, bms_add_member(), bms_free(), PendingOperationEntry::canceled, PendingOperationEntry::cycle_ctr, PendingUnlinkEntry::cycle_ctr, RelFileNode::dbNode, FORGET_DATABASE_FSYNC, FORGET_RELATION_FSYNC, HASH_ENTER, HASH_FIND, hash_search(), hash_seq_init(), hash_seq_search(), InvalidForkNumber, lappend(), lfirst, list_delete_cell(), list_head(), lnext, MAIN_FORKNUM, MAX_FORKNUM, mdckpt_cycle_ctr, mdsync_cycle_ctr, MemoryContextSwitchTo(), MemSet, next, NULL, palloc(), pfree(), PendingOperationEntry::requests, PendingOperationEntry::rnode, PendingUnlinkEntry::rnode, and UNLINK_RELATION_REQUEST.

Referenced by AbsorbFsyncRequests(), ForgetDatabaseFsyncRequests(), ForgetRelationFsyncRequests(), register_dirty_segment(), and register_unlink().

1514 {
1516 
1517  if (segno == FORGET_RELATION_FSYNC)
1518  {
1519  /* Remove any pending requests for the relation (one or all forks) */
1520  PendingOperationEntry *entry;
1521 
1523  &rnode,
1524  HASH_FIND,
1525  NULL);
1526  if (entry)
1527  {
1528  /*
1529  * We can't just delete the entry since mdsync could have an
1530  * active hashtable scan. Instead we delete the bitmapsets; this
1531  * is safe because of the way mdsync is coded. We also set the
1532  * "canceled" flags so that mdsync can tell that a cancel arrived
1533  * for the fork(s).
1534  */
1535  if (forknum == InvalidForkNumber)
1536  {
1537  /* remove requests for all forks */
1538  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
1539  {
1540  bms_free(entry->requests[forknum]);
1541  entry->requests[forknum] = NULL;
1542  entry->canceled[forknum] = true;
1543  }
1544  }
1545  else
1546  {
1547  /* remove requests for single fork */
1548  bms_free(entry->requests[forknum]);
1549  entry->requests[forknum] = NULL;
1550  entry->canceled[forknum] = true;
1551  }
1552  }
1553  }
1554  else if (segno == FORGET_DATABASE_FSYNC)
1555  {
1556  /* Remove any pending requests for the entire database */
1557  HASH_SEQ_STATUS hstat;
1558  PendingOperationEntry *entry;
1559  ListCell *cell,
1560  *prev,
1561  *next;
1562 
1563  /* Remove fsync requests */
1564  hash_seq_init(&hstat, pendingOpsTable);
1565  while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
1566  {
1567  if (entry->rnode.dbNode == rnode.dbNode)
1568  {
1569  /* remove requests for all forks */
1570  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
1571  {
1572  bms_free(entry->requests[forknum]);
1573  entry->requests[forknum] = NULL;
1574  entry->canceled[forknum] = true;
1575  }
1576  }
1577  }
1578 
1579  /* Remove unlink requests */
1580  prev = NULL;
1581  for (cell = list_head(pendingUnlinks); cell; cell = next)
1582  {
1583  PendingUnlinkEntry *entry = (PendingUnlinkEntry *) lfirst(cell);
1584 
1585  next = lnext(cell);
1586  if (entry->rnode.dbNode == rnode.dbNode)
1587  {
1589  pfree(entry);
1590  }
1591  else
1592  prev = cell;
1593  }
1594  }
1595  else if (segno == UNLINK_RELATION_REQUEST)
1596  {
1597  /* Unlink request: put it in the linked list */
1599  PendingUnlinkEntry *entry;
1600 
1601  /* PendingUnlinkEntry doesn't store forknum, since it's always MAIN */
1602  Assert(forknum == MAIN_FORKNUM);
1603 
1604  entry = palloc(sizeof(PendingUnlinkEntry));
1605  entry->rnode = rnode;
1606  entry->cycle_ctr = mdckpt_cycle_ctr;
1607 
1609 
1610  MemoryContextSwitchTo(oldcxt);
1611  }
1612  else
1613  {
1614  /* Normal case: enter a request to fsync this segment */
1616  PendingOperationEntry *entry;
1617  bool found;
1618 
1620  &rnode,
1621  HASH_ENTER,
1622  &found);
1623  /* if new entry, initialize it */
1624  if (!found)
1625  {
1626  entry->cycle_ctr = mdsync_cycle_ctr;
1627  MemSet(entry->requests, 0, sizeof(entry->requests));
1628  MemSet(entry->canceled, 0, sizeof(entry->canceled));
1629  }
1630 
1631  /*
1632  * NB: it's intentional that we don't change cycle_ctr if the entry
1633  * already exists. The cycle_ctr must represent the oldest fsync
1634  * request that could be in the entry.
1635  */
1636 
1637  entry->requests[forknum] = bms_add_member(entry->requests[forknum],
1638  (int) segno);
1639 
1640  MemoryContextSwitchTo(oldcxt);
1641  }
1642 }
#define UNLINK_RELATION_REQUEST
Definition: md.c:55
CycleCtr cycle_ctr
Definition: md.c:151
static int32 next
Definition: blutils.c:210
static CycleCtr mdsync_cycle_ctr
Definition: md.c:158
RelFileNode rnode
Definition: md.c:140
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static CycleCtr mdckpt_cycle_ctr
Definition: md.c:159
#define MemSet(start, val, len)
Definition: c.h:853
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
CycleCtr cycle_ctr
Definition: md.c:141
static HTAB * pendingOpsTable
Definition: md.c:154
bool canceled[MAX_FORKNUM+1]
Definition: md.c:145
#define FORGET_RELATION_FSYNC
Definition: md.c:53
void pfree(void *pointer)
Definition: mcxt.c:992
RelFileNode rnode
Definition: md.c:150
#define FORGET_DATABASE_FSYNC
Definition: md.c:54
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
List * lappend(List *list, void *datum)
Definition: list.c:128
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
void bms_free(Bitmapset *a)
Definition: bitmapset.c:200
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
#define MAX_FORKNUM
Definition: relpath.h:39
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
void * palloc(Size size)
Definition: mcxt.c:891
Bitmapset * requests[MAX_FORKNUM+1]
Definition: md.c:143
static MemoryContext pendingOpsCxt
Definition: md.c:156
static List * pendingUnlinks
Definition: md.c:155
void SetForwardFsyncRequests ( void  )

Definition at line 253 of file md.c.

References Assert, hash_destroy(), mdsync(), NIL, and NULL.

Referenced by StartupXLOG().

254 {
255  /* Perform any pending fsyncs we may have queued up, then drop table */
256  if (pendingOpsTable)
257  {
258  mdsync();
260  }
262 
263  /*
264  * We should not have any pending unlink requests, since mdunlink doesn't
265  * queue unlink requests when isRedo.
266  */
268 }
#define NIL
Definition: pg_list.h:69
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
void mdsync(void)
Definition: md.c:1053
static HTAB * pendingOpsTable
Definition: md.c:154
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static List * pendingUnlinks
Definition: md.c:155
void smgrclearowner ( SMgrRelation owner,
SMgrRelation  reln 
)

Definition at line 222 of file smgr.c.

References add_to_unowned_list(), NULL, and SMgrRelationData::smgr_owner.

Referenced by FreeFakeRelcacheEntry().

223 {
224  /* Do nothing if the SMgrRelation object is not owned by the owner */
225  if (reln->smgr_owner != owner)
226  return;
227 
228  /* unset the owner's reference */
229  *owner = NULL;
230 
231  /* unset our reference to the owner */
232  reln->smgr_owner = NULL;
233 
234  add_to_unowned_list(reln);
235 }
static void add_to_unowned_list(SMgrRelation reln)
Definition: smgr.c:244
struct SMgrRelationData ** smgr_owner
Definition: smgr.h:46
#define NULL
Definition: c.h:226
void smgrclose ( SMgrRelation  reln)

Definition at line 296 of file smgr.c.

References elog, ERROR, HASH_REMOVE, hash_search(), MAX_FORKNUM, NULL, remove_from_unowned_list(), f_smgr::smgr_close, SMgrRelationData::smgr_owner, SMgrRelationData::smgr_rnode, and SMgrRelationData::smgr_which.

Referenced by AtEOXact_SMgr(), ATExecSetTableSpace(), FinishPreparedTransaction(), smgrcloseall(), smgrclosenode(), smgrDoPendingDeletes(), xact_redo_abort(), and xact_redo_commit().

297 {
298  SMgrRelation *owner;
299  ForkNumber forknum;
300 
301  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
302  (*(smgrsw[reln->smgr_which].smgr_close)) (reln, forknum);
303 
304  owner = reln->smgr_owner;
305 
306  if (!owner)
308 
310  (void *) &(reln->smgr_rnode),
311  HASH_REMOVE, NULL) == NULL)
312  elog(ERROR, "SMgrRelation hashtable corrupted");
313 
314  /*
315  * Unhook the owner pointer, if any. We do this last since in the remote
316  * possibility of failure above, the SMgrRelation object will still exist.
317  */
318  if (owner)
319  *owner = NULL;
320 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
static void remove_from_unowned_list(SMgrRelation reln)
Definition: smgr.c:265
static HTAB * SMgrRelationHash
Definition: smgr.c:83
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define ERROR
Definition: elog.h:43
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
ForkNumber
Definition: relpath.h:24
struct SMgrRelationData ** smgr_owner
Definition: smgr.h:46
int smgr_which
Definition: smgr.h:65
void(* smgr_close)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:42
#define NULL
Definition: c.h:226
#define MAX_FORKNUM
Definition: relpath.h:39
#define elog
Definition: elog.h:219
void smgrcloseall ( void  )

Definition at line 326 of file smgr.c.

References hash_seq_init(), hash_seq_search(), NULL, smgrclose(), and status().

Referenced by BackgroundWriterMain(), CheckpointerMain(), RelationCacheInvalidate(), RequestCheckpoint(), WalWriterMain(), and XLogDropDatabase().

327 {
329  SMgrRelation reln;
330 
331  /* Nothing to do if hashtable not set up */
332  if (SMgrRelationHash == NULL)
333  return;
334 
336 
337  while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
338  smgrclose(reln);
339 }
void smgrclose(SMgrRelation reln)
Definition: smgr.c:296
static HTAB * SMgrRelationHash
Definition: smgr.c:83
#define NULL
Definition: c.h:226
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
void smgrclosenode ( RelFileNodeBackend  rnode)

Definition at line 350 of file smgr.c.

References HASH_FIND, hash_search(), NULL, and smgrclose().

Referenced by LocalExecuteInvalidationMessage(), and RelationSetNewRelfilenode().

351 {
352  SMgrRelation reln;
353 
354  /* Nothing to do if hashtable not set up */
355  if (SMgrRelationHash == NULL)
356  return;
357 
359  (void *) &rnode,
360  HASH_FIND, NULL);
361  if (reln != NULL)
362  smgrclose(reln);
363 }
void smgrclose(SMgrRelation reln)
Definition: smgr.c:296
SMgrRelationData * SMgrRelation
Definition: smgr.h:78
static HTAB * SMgrRelationHash
Definition: smgr.c:83
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define NULL
Definition: c.h:226
void smgrcreate ( SMgrRelation  reln,
ForkNumber  forknum,
bool  isRedo 
)

Definition at line 376 of file smgr.c.

References RelFileNode::dbNode, SMgrRelationData::md_num_open_segs, RelFileNodeBackend::node, f_smgr::smgr_create, SMgrRelationData::smgr_rnode, SMgrRelationData::smgr_which, RelFileNode::spcNode, and TablespaceCreateDbspace().

Referenced by ATExecSetTableSpace(), fsm_extend(), heap_create_init_fork(), index_build(), RelationCreateStorage(), smgr_redo(), vm_extend(), and XLogReadBufferExtended().

377 {
378  /*
379  * Exit quickly in WAL replay mode if we've already opened the file. If
380  * it's open, it surely must exist.
381  */
382  if (isRedo && reln->md_num_open_segs[forknum] > 0)
383  return;
384 
385  /*
386  * We may be using the target table space for the first time in this
387  * database, so create a per-database subdirectory if needed.
388  *
389  * XXX this is a fairly ugly violation of module layering, but this seems
390  * to be the best place to put the check. Maybe TablespaceCreateDbspace
391  * should be here and not in commands/tablespace.c? But that would imply
392  * importing a lot of stuff that smgr.c oughtn't know, either.
393  */
395  reln->smgr_rnode.node.dbNode,
396  isRedo);
397 
398  (*(smgrsw[reln->smgr_which].smgr_create)) (reln, forknum, isRedo);
399 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int smgr_which
Definition: smgr.h:65
RelFileNode node
Definition: relfilenode.h:74
void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
Definition: tablespace.c:115
void(* smgr_create)(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:43
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:71
void smgrdounlink ( SMgrRelation  reln,
bool  isRedo 
)

Definition at line 414 of file smgr.c.

References CacheInvalidateSmgr(), DropRelFileNodesAllBuffers(), InvalidForkNumber, MAX_FORKNUM, SMgrRelationData::smgr_rnode, f_smgr::smgr_unlink, and SMgrRelationData::smgr_which.

Referenced by FinishPreparedTransaction(), xact_redo_abort(), and xact_redo_commit().

415 {
416  RelFileNodeBackend rnode = reln->smgr_rnode;
417  int which = reln->smgr_which;
418  ForkNumber forknum;
419 
420  /* Close the forks at smgr level */
421  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
422  (*(smgrsw[which].smgr_close)) (reln, forknum);
423 
424  /*
425  * Get rid of any remaining buffers for the relation. bufmgr will just
426  * drop them without bothering to write the contents.
427  */
428  DropRelFileNodesAllBuffers(&rnode, 1);
429 
430  /*
431  * It'd be nice to tell the stats collector to forget it immediately, too.
432  * But we can't because we don't know the OID (and in cases involving
433  * relfilenode swaps, it's not always clear which table OID to forget,
434  * anyway).
435  */
436 
437  /*
438  * Send a shared-inval message to force other backends to close any
439  * dangling smgr references they may have for this rel. We should do this
440  * before starting the actual unlinking, in case we fail partway through
441  * that step. Note that the sinval message will eventually come back to
442  * this backend, too, and thereby provide a backstop that we closed our
443  * own smgr rel.
444  */
445  CacheInvalidateSmgr(rnode);
446 
447  /*
448  * Delete the physical file(s).
449  *
450  * Note: smgr_unlink must treat deletion failure as a WARNING, not an
451  * ERROR, because we've already decided to commit or abort the current
452  * xact.
453  */
454  (*(smgrsw[which].smgr_unlink)) (rnode, InvalidForkNumber, isRedo);
455 }
void CacheInvalidateSmgr(RelFileNodeBackend rnode)
Definition: inval.c:1324
void(* smgr_unlink)(RelFileNodeBackend rnode, ForkNumber forknum, bool isRedo)
Definition: smgr.c:46
static const f_smgr smgrsw[]
Definition: smgr.c:68
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
ForkNumber
Definition: relpath.h:24
void DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes)
Definition: bufmgr.c:2923
int smgr_which
Definition: smgr.h:65
#define MAX_FORKNUM
Definition: relpath.h:39
void smgrdounlinkall ( SMgrRelation rels,
int  nrels,
bool  isRedo 
)

Definition at line 471 of file smgr.c.

References CacheInvalidateSmgr(), DropRelFileNodesAllBuffers(), i, MAX_FORKNUM, palloc(), pfree(), SMgrRelationData::smgr_rnode, and SMgrRelationData::smgr_which.

Referenced by smgrDoPendingDeletes().

472 {
473  int i = 0;
474  RelFileNodeBackend *rnodes;
475  ForkNumber forknum;
476 
477  if (nrels == 0)
478  return;
479 
480  /*
481  * create an array which contains all relations to be dropped, and close
482  * each relation's forks at the smgr level while at it
483  */
484  rnodes = palloc(sizeof(RelFileNodeBackend) * nrels);
485  for (i = 0; i < nrels; i++)
486  {
487  RelFileNodeBackend rnode = rels[i]->smgr_rnode;
488  int which = rels[i]->smgr_which;
489 
490  rnodes[i] = rnode;
491 
492  /* Close the forks at smgr level */
493  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
494  (*(smgrsw[which].smgr_close)) (rels[i], forknum);
495  }
496 
497  /*
498  * Get rid of any remaining buffers for the relations. bufmgr will just
499  * drop them without bothering to write the contents.
500  */
501  DropRelFileNodesAllBuffers(rnodes, nrels);
502 
503  /*
504  * It'd be nice to tell the stats collector to forget them immediately,
505  * too. But we can't because we don't know the OIDs.
506  */
507 
508  /*
509  * Send a shared-inval message to force other backends to close any
510  * dangling smgr references they may have for these rels. We should do
511  * this before starting the actual unlinking, in case we fail partway
512  * through that step. Note that the sinval messages will eventually come
513  * back to this backend, too, and thereby provide a backstop that we
514  * closed our own smgr rel.
515  */
516  for (i = 0; i < nrels; i++)
517  CacheInvalidateSmgr(rnodes[i]);
518 
519  /*
520  * Delete the physical file(s).
521  *
522  * Note: smgr_unlink must treat deletion failure as a WARNING, not an
523  * ERROR, because we've already decided to commit or abort the current
524  * xact.
525  */
526 
527  for (i = 0; i < nrels; i++)
528  {
529  int which = rels[i]->smgr_which;
530 
531  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
532  (*(smgrsw[which].smgr_unlink)) (rnodes[i], forknum, isRedo);
533  }
534 
535  pfree(rnodes);
536 }
void CacheInvalidateSmgr(RelFileNodeBackend rnode)
Definition: inval.c:1324
static const f_smgr smgrsw[]
Definition: smgr.c:68
void pfree(void *pointer)
Definition: mcxt.c:992
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
ForkNumber
Definition: relpath.h:24
void DropRelFileNodesAllBuffers(RelFileNodeBackend *rnodes, int nnodes)
Definition: bufmgr.c:2923
int smgr_which
Definition: smgr.h:65
#define MAX_FORKNUM
Definition: relpath.h:39
void * palloc(Size size)
Definition: mcxt.c:891
int i
void smgrdounlinkfork ( SMgrRelation  reln,
ForkNumber  forknum,
bool  isRedo 
)

Definition at line 549 of file smgr.c.

References CacheInvalidateSmgr(), DropRelFileNodeBuffers(), f_smgr::smgr_close, SMgrRelationData::smgr_rnode, f_smgr::smgr_unlink, and SMgrRelationData::smgr_which.

550 {
551  RelFileNodeBackend rnode = reln->smgr_rnode;
552  int which = reln->smgr_which;
553 
554  /* Close the fork at smgr level */
555  (*(smgrsw[which].smgr_close)) (reln, forknum);
556 
557  /*
558  * Get rid of any remaining buffers for the fork. bufmgr will just drop
559  * them without bothering to write the contents.
560  */
561  DropRelFileNodeBuffers(rnode, forknum, 0);
562 
563  /*
564  * It'd be nice to tell the stats collector to forget it immediately, too.
565  * But we can't because we don't know the OID (and in cases involving
566  * relfilenode swaps, it's not always clear which table OID to forget,
567  * anyway).
568  */
569 
570  /*
571  * Send a shared-inval message to force other backends to close any
572  * dangling smgr references they may have for this rel. We should do this
573  * before starting the actual unlinking, in case we fail partway through
574  * that step. Note that the sinval message will eventually come back to
575  * this backend, too, and thereby provide a backstop that we closed our
576  * own smgr rel.
577  */
578  CacheInvalidateSmgr(rnode);
579 
580  /*
581  * Delete the physical file(s).
582  *
583  * Note: smgr_unlink must treat deletion failure as a WARNING, not an
584  * ERROR, because we've already decided to commit or abort the current
585  * xact.
586  */
587  (*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
588 }
void CacheInvalidateSmgr(RelFileNodeBackend rnode)
Definition: inval.c:1324
void(* smgr_unlink)(RelFileNodeBackend rnode, ForkNumber forknum, bool isRedo)
Definition: smgr.c:46
static const f_smgr smgrsw[]
Definition: smgr.c:68
void DropRelFileNodeBuffers(RelFileNodeBackend rnode, ForkNumber forkNum, BlockNumber firstDelBlock)
Definition: bufmgr.c:2866
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int smgr_which
Definition: smgr.h:65
void(* smgr_close)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:42
bool smgrexists ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 287 of file smgr.c.

References f_smgr::smgr_exists, and SMgrRelationData::smgr_which.

Referenced by ATExecSetTableSpace(), FreeSpaceMapTruncateRel(), fsm_extend(), fsm_readbuf(), index_build(), pg_prewarm(), RelationTruncate(), smgr_redo(), visibilitymap_truncate(), vm_extend(), and vm_readbuf().

288 {
289  return (*(smgrsw[reln->smgr_which].smgr_exists)) (reln, forknum);
290 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
bool(* smgr_exists)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:45
int smgr_which
Definition: smgr.h:65
void smgrextend ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer,
bool  skipFsync 
)

Definition at line 600 of file smgr.c.

References f_smgr::smgr_extend, and SMgrRelationData::smgr_which.

Referenced by _bt_blwritepage(), _hash_alloc_buckets(), copy_relation_data(), end_heap_rewrite(), fsm_extend(), raw_heap_insert(), ReadBuffer_common(), and vm_extend().

602 {
603  (*(smgrsw[reln->smgr_which].smgr_extend)) (reln, forknum, blocknum,
604  buffer, skipFsync);
605 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
void(* smgr_extend)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:48
int smgr_which
Definition: smgr.h:65
void smgrimmedsync ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 734 of file smgr.c.

References f_smgr::smgr_immedsync, and SMgrRelationData::smgr_which.

Referenced by _bt_load(), blbuildempty(), btbuildempty(), copy_relation_data(), heap_create_init_fork(), heap_sync(), and spgbuildempty().

735 {
736  (*(smgrsw[reln->smgr_which].smgr_immedsync)) (reln, forknum);
737 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
void(* smgr_immedsync)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:61
int smgr_which
Definition: smgr.h:65
void smgrinit ( void  )

Definition at line 102 of file smgr.c.

References i, NSmgr, on_proc_exit(), f_smgr::smgr_init, and smgrshutdown().

Referenced by BaseInit().

103 {
104  int i;
105 
106  for (i = 0; i < NSmgr; i++)
107  {
108  if (smgrsw[i].smgr_init)
109  (*(smgrsw[i].smgr_init)) ();
110  }
111 
112  /* register the shutdown proc */
114 }
void(* smgr_init)(void)
Definition: smgr.c:40
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:292
static const f_smgr smgrsw[]
Definition: smgr.c:68
static void smgrshutdown(int code, Datum arg)
Definition: smgr.c:120
static const int NSmgr
Definition: smgr.c:76
int i
BlockNumber smgrnblocks ( SMgrRelation  reln,
ForkNumber  forknum 
)

Definition at line 672 of file smgr.c.

References f_smgr::smgr_nblocks, and SMgrRelationData::smgr_which.

Referenced by copy_relation_data(), FreeSpaceMapTruncateRel(), fsm_extend(), fsm_readbuf(), gistBuildCallback(), ReadBuffer_common(), RelationGetNumberOfBlocksInFork(), visibilitymap_truncate(), vm_extend(), vm_readbuf(), and XLogReadBufferExtended().

673 {
674  return (*(smgrsw[reln->smgr_which].smgr_nblocks)) (reln, forknum);
675 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
int smgr_which
Definition: smgr.h:65
BlockNumber(* smgr_nblocks)(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:58
SMgrRelation smgropen ( RelFileNode  rnode,
BackendId  backend 
)

Definition at line 137 of file smgr.c.

References add_to_unowned_list(), RelFileNodeBackend::backend, HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), InvalidBlockNumber, HASHCTL::keysize, MAX_FORKNUM, SMgrRelationData::md_num_open_segs, MemSet, RelFileNodeBackend::node, NULL, SMgrRelationData::smgr_fsm_nblocks, SMgrRelationData::smgr_owner, SMgrRelationData::smgr_targblock, SMgrRelationData::smgr_vm_nblocks, and SMgrRelationData::smgr_which.

Referenced by ATExecSetTableSpace(), FinishPreparedTransaction(), FlushBuffer(), IssuePendingWritebacks(), LocalBufferAlloc(), mdsync(), ReadBufferWithoutRelcache(), RelationCreateStorage(), smgr_redo(), smgrDoPendingDeletes(), xact_redo_abort(), xact_redo_commit(), and XLogReadBufferExtended().

138 {
139  RelFileNodeBackend brnode;
140  SMgrRelation reln;
141  bool found;
142 
143  if (SMgrRelationHash == NULL)
144  {
145  /* First time through: initialize the hash table */
146  HASHCTL ctl;
147 
148  MemSet(&ctl, 0, sizeof(ctl));
149  ctl.keysize = sizeof(RelFileNodeBackend);
150  ctl.entrysize = sizeof(SMgrRelationData);
151  SMgrRelationHash = hash_create("smgr relation table", 400,
152  &ctl, HASH_ELEM | HASH_BLOBS);
154  }
155 
156  /* Look up or create an entry */
157  brnode.node = rnode;
158  brnode.backend = backend;
160  (void *) &brnode,
161  HASH_ENTER, &found);
162 
163  /* Initialize it if not present before */
164  if (!found)
165  {
166  int forknum;
167 
168  /* hash_search already filled in the lookup key */
169  reln->smgr_owner = NULL;
173  reln->smgr_which = 0; /* we only have md.c at present */
174 
175  /* mark it not open */
176  for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
177  reln->md_num_open_segs[forknum] = 0;
178 
179  /* it has no owner yet */
180  add_to_unowned_list(reln);
181  }
182 
183  return reln;
184 }
struct SMgrRelationData SMgrRelationData
BlockNumber smgr_vm_nblocks
Definition: smgr.h:57
#define HASH_ELEM
Definition: hsearch.h:87
SMgrRelationData * SMgrRelation
Definition: smgr.h:78
Size entrysize
Definition: hsearch.h:73
static HTAB * SMgrRelationHash
Definition: smgr.c:83
#define MemSet(start, val, len)
Definition: c.h:853
BlockNumber smgr_fsm_nblocks
Definition: smgr.h:56
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static void add_to_unowned_list(SMgrRelation reln)
Definition: smgr.c:244
struct SMgrRelationData ** smgr_owner
Definition: smgr.h:46
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
int smgr_which
Definition: smgr.h:65
struct RelFileNodeBackend RelFileNodeBackend
Size keysize
Definition: hsearch.h:72
RelFileNode node
Definition: relfilenode.h:74
#define NULL
Definition: c.h:226
BlockNumber smgr_targblock
Definition: smgr.h:55
BackendId backend
Definition: relfilenode.h:75
#define InvalidBlockNumber
Definition: block.h:33
#define MAX_FORKNUM
Definition: relpath.h:39
int md_num_open_segs[MAX_FORKNUM+1]
Definition: smgr.h:71
static SMgrRelation first_unowned_reln
Definition: smgr.c:85
void smgrpostckpt ( void  )

Definition at line 774 of file smgr.c.

References i, NSmgr, and f_smgr::smgr_post_ckpt.

Referenced by CreateCheckPoint().

775 {
776  int i;
777 
778  for (i = 0; i < NSmgr; i++)
779  {
780  if (smgrsw[i].smgr_post_ckpt)
781  (*(smgrsw[i].smgr_post_ckpt)) ();
782  }
783 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
static const int NSmgr
Definition: smgr.c:76
void(* smgr_post_ckpt)(void)
Definition: smgr.c:64
int i
void smgrpreckpt ( void  )

Definition at line 744 of file smgr.c.

References i, NSmgr, and f_smgr::smgr_pre_ckpt.

Referenced by CreateCheckPoint().

745 {
746  int i;
747 
748  for (i = 0; i < NSmgr; i++)
749  {
750  if (smgrsw[i].smgr_pre_ckpt)
751  (*(smgrsw[i].smgr_pre_ckpt)) ();
752  }
753 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
void(* smgr_pre_ckpt)(void)
Definition: smgr.c:62
static const int NSmgr
Definition: smgr.c:76
int i
void smgrprefetch ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum 
)

Definition at line 611 of file smgr.c.

References f_smgr::smgr_prefetch, and SMgrRelationData::smgr_which.

Referenced by LocalPrefetchBuffer(), and PrefetchBuffer().

612 {
613  (*(smgrsw[reln->smgr_which].smgr_prefetch)) (reln, forknum, blocknum);
614 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
void(* smgr_prefetch)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
Definition: smgr.c:50
int smgr_which
Definition: smgr.h:65
void smgrread ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer 
)

Definition at line 625 of file smgr.c.

References f_smgr::smgr_read, and SMgrRelationData::smgr_which.

Referenced by copy_relation_data(), pg_prewarm(), and ReadBuffer_common().

627 {
628  (*(smgrsw[reln->smgr_which].smgr_read)) (reln, forknum, blocknum, buffer);
629 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
int smgr_which
Definition: smgr.h:65
void(* smgr_read)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
Definition: smgr.c:52
void smgrsetowner ( SMgrRelation owner,
SMgrRelation  reln 
)

Definition at line 193 of file smgr.c.

References Assert, NULL, remove_from_unowned_list(), and SMgrRelationData::smgr_owner.

194 {
195  /* We don't support "disowning" an SMgrRelation here, use smgrclearowner */
196  Assert(owner != NULL);
197 
198  /*
199  * First, unhook any old owner. (Normally there shouldn't be any, but it
200  * seems possible that this can happen during swap_relation_files()
201  * depending on the order of processing. It's ok to close the old
202  * relcache entry early in that case.)
203  *
204  * If there isn't an old owner, then the reln should be in the unowned
205  * list, and we need to remove it.
206  */
207  if (reln->smgr_owner)
208  *(reln->smgr_owner) = NULL;
209  else
211 
212  /* Now establish the ownership relationship. */
213  reln->smgr_owner = owner;
214  *owner = reln;
215 }
static void remove_from_unowned_list(SMgrRelation reln)
Definition: smgr.c:265
struct SMgrRelationData ** smgr_owner
Definition: smgr.h:46
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void smgrsync ( void  )

Definition at line 759 of file smgr.c.

References i, NSmgr, and f_smgr::smgr_sync.

Referenced by CheckPointBuffers().

760 {
761  int i;
762 
763  for (i = 0; i < NSmgr; i++)
764  {
765  if (smgrsw[i].smgr_sync)
766  (*(smgrsw[i].smgr_sync)) ();
767  }
768 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
static const int NSmgr
Definition: smgr.c:76
void(* smgr_sync)(void)
Definition: smgr.c:63
int i
void smgrtruncate ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  nblocks 
)

Definition at line 684 of file smgr.c.

References CacheInvalidateSmgr(), DropRelFileNodeBuffers(), SMgrRelationData::smgr_rnode, f_smgr::smgr_truncate, and SMgrRelationData::smgr_which.

Referenced by FreeSpaceMapTruncateRel(), RelationTruncate(), smgr_redo(), and visibilitymap_truncate().

685 {
686  /*
687  * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
688  * just drop them without bothering to write the contents.
689  */
690  DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nblocks);
691 
692  /*
693  * Send a shared-inval message to force other backends to close any smgr
694  * references they may have for this rel. This is useful because they
695  * might have open file pointers to segments that got removed, and/or
696  * smgr_targblock variables pointing past the new rel end. (The inval
697  * message will come back to our backend, too, causing a
698  * probably-unnecessary local smgr flush. But we don't expect that this
699  * is a performance-critical path.) As in the unlink code, we want to be
700  * sure the message is sent before we start changing things on-disk.
701  */
703 
704  /*
705  * Do the truncation.
706  */
707  (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, forknum, nblocks);
708 }
void CacheInvalidateSmgr(RelFileNodeBackend rnode)
Definition: inval.c:1324
static const f_smgr smgrsw[]
Definition: smgr.c:68
void DropRelFileNodeBuffers(RelFileNodeBackend rnode, ForkNumber forkNum, BlockNumber firstDelBlock)
Definition: bufmgr.c:2866
void(* smgr_truncate)(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
Definition: smgr.c:59
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int smgr_which
Definition: smgr.h:65
void smgrwrite ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer,
bool  skipFsync 
)

Definition at line 647 of file smgr.c.

References SMgrRelationData::smgr_which, and f_smgr::smgr_write.

Referenced by _bt_blwritepage(), blbuildempty(), btbuildempty(), FlushBuffer(), FlushRelationBuffers(), LocalBufferAlloc(), and spgbuildempty().

649 {
650  (*(smgrsw[reln->smgr_which].smgr_write)) (reln, forknum, blocknum,
651  buffer, skipFsync);
652 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
void(* smgr_write)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:54
int smgr_which
Definition: smgr.h:65
void smgrwriteback ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
BlockNumber  nblocks 
)

Definition at line 660 of file smgr.c.

References SMgrRelationData::smgr_which, and f_smgr::smgr_writeback.

Referenced by IssuePendingWritebacks().

662 {
663  (*(smgrsw[reln->smgr_which].smgr_writeback)) (reln, forknum, blocknum,
664  nblocks);
665 }
static const f_smgr smgrsw[]
Definition: smgr.c:68
int smgr_which
Definition: smgr.h:65
void(* smgr_writeback)(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, BlockNumber nblocks)
Definition: smgr.c:56