From 91d20ff7aa4c61e570cf652bb3a48fd18fcf9d9d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 31 May 2004 20:31:33 +0000 Subject: [PATCH] Additional mop-up for sync-to-fsync changes: avoid issuing fsyncs for temp tables, and avoid WAL-logging truncations of temp tables. Do issue fsync on truncated files (not sure this is necessary but it seems like a good idea). --- src/backend/storage/buffer/bufmgr.c | 17 ++++--- src/backend/storage/buffer/localbuf.c | 5 +- src/backend/storage/smgr/md.c | 32 +++++++++--- src/backend/storage/smgr/smgr.c | 72 ++++++++++++++++----------- src/include/storage/smgr.h | 20 +++++--- 5 files changed, 94 insertions(+), 52 deletions(-) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index bc6c0f6993..400fbcf1ff 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.168 2004/05/31 19:24:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.169 2004/05/31 20:31:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -182,7 +182,8 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum, { /* new buffers are zero-filled */ MemSet((char *) MAKE_PTR(bufHdr->data), 0, BLCKSZ); - smgrextend(reln->rd_smgr, blockNum, (char *) MAKE_PTR(bufHdr->data)); + smgrextend(reln->rd_smgr, blockNum, (char *) MAKE_PTR(bufHdr->data), + reln->rd_istemp); } else { @@ -915,8 +916,8 @@ BufferGetFileNode(Buffer buffer) * NOTE: this actually just passes the buffer contents to the kernel; the * real write to disk won't happen until the kernel feels like it. This * is okay from our point of view since we can redo the changes from WAL. - * However, we will need to force the changes to disk via sync/fsync - * before we can checkpoint WAL. + * However, we will need to force the changes to disk via fsync before + * we can checkpoint WAL. * * BufMgrLock must be held at entry, and the buffer must be pinned. The * caller is also responsible for doing StartBufferIO/TerminateBufferIO. @@ -979,7 +980,8 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln) */ smgrwrite(reln, buf->tag.blockNum, - (char *) MAKE_PTR(buf->data)); + (char *) MAKE_PTR(buf->data), + false); /* Pop the error context stack */ error_context_stack = errcontext.previous; @@ -1033,7 +1035,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks) rel->rd_targblock = InvalidBlockNumber; /* Do the real work */ - smgrtruncate(rel->rd_smgr, nblocks); + smgrtruncate(rel->rd_smgr, nblocks, rel->rd_istemp); } /* --------------------------------------------------------------------- @@ -1351,7 +1353,8 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock) smgrwrite(rel->rd_smgr, bufHdr->tag.blockNum, - (char *) MAKE_PTR(bufHdr->data)); + (char *) MAKE_PTR(bufHdr->data), + true); bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED); bufHdr->cntxDirty = false; diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index ba4be8750c..95e86e955d 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.54 2004/04/22 07:21:55 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.55 2004/05/31 20:31:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -111,7 +111,8 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) /* And write... */ smgrwrite(reln, bufHdr->tag.blockNum, - (char *) MAKE_PTR(bufHdr->data)); + (char *) MAKE_PTR(bufHdr->data), + true); LocalBufferFlushCount++; } diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 5ac5868f69..1a0218c4e5 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.105 2004/05/31 03:48:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.106 2004/05/31 20:31:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -270,7 +270,7 @@ mdunlink(RelFileNode rnode, bool isRedo) * already. Might as well pass in the position and save a seek. */ bool -mdextend(SMgrRelation reln, BlockNumber blocknum, char *buffer) +mdextend(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp) { long seekpos; int nbytes; @@ -311,8 +311,11 @@ mdextend(SMgrRelation reln, BlockNumber blocknum, char *buffer) return false; } - if (!register_dirty_segment(reln, v)) - return false; + if (!isTemp) + { + if (!register_dirty_segment(reln, v)) + return false; + } #ifndef LET_OS_MANAGE_FILESIZE Assert(_mdnblocks(v->mdfd_vfd, BLCKSZ) <= ((BlockNumber) RELSEG_SIZE)); @@ -465,7 +468,7 @@ mdread(SMgrRelation reln, BlockNumber blocknum, char *buffer) * mdwrite() -- Write the supplied block at the appropriate location. */ bool -mdwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer) +mdwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp) { long seekpos; MdfdVec *v; @@ -485,8 +488,11 @@ mdwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer) if (FileWrite(v->mdfd_vfd, buffer, BLCKSZ) != BLCKSZ) return false; - if (!register_dirty_segment(reln, v)) - return false; + if (!isTemp) + { + if (!register_dirty_segment(reln, v)) + return false; + } return true; } @@ -565,7 +571,7 @@ mdnblocks(SMgrRelation reln) * Returns # of blocks or InvalidBlockNumber on error. */ BlockNumber -mdtruncate(SMgrRelation reln, BlockNumber nblocks) +mdtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp) { MdfdVec *v; BlockNumber curnblk; @@ -624,6 +630,11 @@ mdtruncate(SMgrRelation reln, BlockNumber nblocks) if (FileTruncate(v->mdfd_vfd, lastsegblocks * BLCKSZ) < 0) return InvalidBlockNumber; + if (!isTemp) + { + if (!register_dirty_segment(reln, v)) + return InvalidBlockNumber; + } v = v->mdfd_chain; ov->mdfd_chain = NULL; } @@ -640,6 +651,11 @@ mdtruncate(SMgrRelation reln, BlockNumber nblocks) #else if (FileTruncate(v->mdfd_vfd, nblocks * BLCKSZ) < 0) return InvalidBlockNumber; + if (!isTemp) + { + if (!register_dirty_segment(reln, v)) + return InvalidBlockNumber; + } #endif return nblocks; diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index c204e2796c..5320532be4 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.71 2004/05/31 03:48:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.72 2004/05/31 20:31:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -40,13 +40,14 @@ typedef struct f_smgr bool (*smgr_create) (SMgrRelation reln, bool isRedo); bool (*smgr_unlink) (RelFileNode rnode, bool isRedo); bool (*smgr_extend) (SMgrRelation reln, BlockNumber blocknum, - char *buffer); + char *buffer, bool isTemp); bool (*smgr_read) (SMgrRelation reln, BlockNumber blocknum, - char *buffer); + char *buffer); bool (*smgr_write) (SMgrRelation reln, BlockNumber blocknum, - char *buffer); + char *buffer, bool isTemp); BlockNumber (*smgr_nblocks) (SMgrRelation reln); - BlockNumber (*smgr_truncate) (SMgrRelation reln, BlockNumber nblocks); + BlockNumber (*smgr_truncate) (SMgrRelation reln, BlockNumber nblocks, + bool isTemp); bool (*smgr_commit) (void); /* may be NULL */ bool (*smgr_abort) (void); /* may be NULL */ bool (*smgr_sync) (void); /* may be NULL */ @@ -438,9 +439,10 @@ smgr_internal_unlink(RelFileNode rnode, int which, bool isTemp, bool isRedo) * failure we clean up by truncating. */ void -smgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer) +smgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp) { - if (! (*(smgrsw[reln->smgr_which].smgr_extend)) (reln, blocknum, buffer)) + if (! (*(smgrsw[reln->smgr_which].smgr_extend)) (reln, blocknum, buffer, + isTemp)) ereport(ERROR, (errcode_for_file_access(), errmsg("could not extend relation %u/%u: %m", @@ -473,12 +475,18 @@ smgrread(SMgrRelation reln, BlockNumber blocknum, char *buffer) * smgrwrite() -- Write the supplied buffer out. * * This is not a synchronous write -- the block is not necessarily - * on disk at return, only dumped out to the kernel. + * on disk at return, only dumped out to the kernel. However, + * provisions will be made to fsync the write before the next checkpoint. + * + * isTemp indicates that the relation is a temp table (ie, is managed + * by the local-buffer manager). In this case no provisions need be + * made to fsync the write before checkpointing. */ void -smgrwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer) +smgrwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp) { - if (! (*(smgrsw[reln->smgr_which].smgr_write)) (reln, blocknum, buffer)) + if (! (*(smgrsw[reln->smgr_which].smgr_write)) (reln, blocknum, buffer, + isTemp)) ereport(ERROR, (errcode_for_file_access(), errmsg("could not write block %u of relation %u/%u: %m", @@ -525,12 +533,9 @@ smgrnblocks(SMgrRelation reln) * transaction on failure. */ BlockNumber -smgrtruncate(SMgrRelation reln, BlockNumber nblocks) +smgrtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp) { BlockNumber newblks; - XLogRecPtr lsn; - XLogRecData rdata; - xl_smgr_truncate xlrec; /* * Tell the free space map to forget anything it may have stored @@ -540,7 +545,8 @@ smgrtruncate(SMgrRelation reln, BlockNumber nblocks) FreeSpaceMapTruncateRel(&reln->smgr_rnode, nblocks); /* Do the truncation */ - newblks = (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, nblocks); + newblks = (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, nblocks, + isTemp); if (newblks == InvalidBlockNumber) ereport(ERROR, (errcode_for_file_access(), @@ -549,20 +555,29 @@ smgrtruncate(SMgrRelation reln, BlockNumber nblocks) reln->smgr_rnode.relNode, nblocks))); - /* - * Make a non-transactional XLOG entry showing the file truncation. It's - * non-transactional because we should replay it whether the transaction - * commits or not; the underlying file change is certainly not reversible. - */ - xlrec.blkno = newblks; - xlrec.rnode = reln->smgr_rnode; + if (!isTemp) + { + /* + * Make a non-transactional XLOG entry showing the file truncation. + * It's non-transactional because we should replay it whether the + * transaction commits or not; the underlying file change is certainly + * not reversible. + */ + XLogRecPtr lsn; + XLogRecData rdata; + xl_smgr_truncate xlrec; - rdata.buffer = InvalidBuffer; - rdata.data = (char *) &xlrec; - rdata.len = sizeof(xlrec); - rdata.next = NULL; + xlrec.blkno = newblks; + xlrec.rnode = reln->smgr_rnode; - lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLOG_NO_TRAN, &rdata); + rdata.buffer = InvalidBuffer; + rdata.data = (char *) &xlrec; + rdata.len = sizeof(xlrec); + rdata.next = NULL; + + lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLOG_NO_TRAN, + &rdata); + } return newblks; } @@ -725,7 +740,8 @@ smgr_redo(XLogRecPtr lsn, XLogRecord *record) /* Do the truncation */ newblks = (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, - xlrec->blkno); + xlrec->blkno, + false); if (newblks == InvalidBlockNumber) ereport(WARNING, (errcode_for_file_access(), diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h index 6a28c3824f..6999635dc4 100644 --- a/src/include/storage/smgr.h +++ b/src/include/storage/smgr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/smgr.h,v 1.42 2004/05/31 03:48:10 tgl Exp $ + * $PostgreSQL: pgsql/src/include/storage/smgr.h,v 1.43 2004/05/31 20:31:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -55,11 +55,14 @@ extern void smgrclosenode(RelFileNode rnode); extern void smgrcreate(SMgrRelation reln, bool isTemp, bool isRedo); extern void smgrscheduleunlink(SMgrRelation reln, bool isTemp); extern void smgrdounlink(SMgrRelation reln, bool isTemp, bool isRedo); -extern void smgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer); +extern void smgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer, + bool isTemp); extern void smgrread(SMgrRelation reln, BlockNumber blocknum, char *buffer); -extern void smgrwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer); +extern void smgrwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer, + bool isTemp); extern BlockNumber smgrnblocks(SMgrRelation reln); -extern BlockNumber smgrtruncate(SMgrRelation reln, BlockNumber nblocks); +extern BlockNumber smgrtruncate(SMgrRelation reln, BlockNumber nblocks, + bool isTemp); extern void smgrDoPendingDeletes(bool isCommit); extern int smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr); extern void smgrcommit(void); @@ -78,11 +81,14 @@ extern bool mdinit(void); extern bool mdclose(SMgrRelation reln); extern bool mdcreate(SMgrRelation reln, bool isRedo); extern bool mdunlink(RelFileNode rnode, bool isRedo); -extern bool mdextend(SMgrRelation reln, BlockNumber blocknum, char *buffer); +extern bool mdextend(SMgrRelation reln, BlockNumber blocknum, char *buffer, + bool isTemp); extern bool mdread(SMgrRelation reln, BlockNumber blocknum, char *buffer); -extern bool mdwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer); +extern bool mdwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer, + bool isTemp); extern BlockNumber mdnblocks(SMgrRelation reln); -extern BlockNumber mdtruncate(SMgrRelation reln, BlockNumber nblocks); +extern BlockNumber mdtruncate(SMgrRelation reln, BlockNumber nblocks, + bool isTemp); extern bool mdsync(void); extern void RememberFsyncRequest(RelFileNode rnode, BlockNumber segno);