diff -rcN postgresql_with_9fujii_patch/src/backend/access/transam/xlog.c postgresql_with_patch/src/backend/access/transam/xlog.c *** postgresql_with_9fujii_patch/src/backend/access/transam/xlog.c 2011-10-06 06:06:19.000000000 +0900 --- postgresql_with_patch/src/backend/access/transam/xlog.c 2011-10-11 14:58:50.000000000 +0900 *************** *** 364,369 **** --- 364,372 ---- bool exclusiveBackup; int nonExclusiveBackups; XLogRecPtr lastBackupStart; + + /* the startup or the walwriter is logged to its own FPW */ + bool fullPageWrites; } XLogCtlInsert; /* *************** *** 453,458 **** --- 456,464 ---- bool recoveryPause; slock_t info_lck; /* locks shared variables shown above */ + + /* latest LSN that has recovered a WAL which fpw is 'off' */ + XLogRecPtr lastFpwDisabledLSN; } XLogCtlData; static XLogCtlData *XLogCtl = NULL; *************** *** 574,579 **** --- 580,586 ---- int max_prepared_xacts; int max_locks_per_xact; int wal_level; + bool fullPageWrites; } xl_parameter_change; /* logs restore point */ *************** *** 612,618 **** static void SetLatestXTime(TimestampTz xtime); static TimestampTz GetLatestXTime(void); static void CheckRequiredParameterValues(void); - static void XLogReportParameters(void); static void LocalSetXLogInsertAllowed(void); static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags); static void KeepLogSeg(XLogRecPtr recptr, uint32 *logId, uint32 *logSeg); --- 619,624 ---- *************** *** 763,769 **** * don't yet have the insert lock, forcePageWrites could change under us, * but we'll recheck it once we have the lock. */ ! doPageWrites = fullPageWrites || Insert->forcePageWrites; INIT_CRC32(rdata_crc); len = 0; --- 769,775 ---- * don't yet have the insert lock, forcePageWrites could change under us, * but we'll recheck it once we have the lock. */ ! doPageWrites = Insert->fullPageWrites || Insert->forcePageWrites; INIT_CRC32(rdata_crc); len = 0; *************** *** 909,915 **** * just turned off, we could recompute the record without full pages, but * we choose not to bother.) */ ! if (Insert->forcePageWrites && !doPageWrites) { /* Oops, must redo it with full-page data */ LWLockRelease(WALInsertLock); --- 915,921 ---- * just turned off, we could recompute the record without full pages, but * we choose not to bother.) */ ! if ((Insert->fullPageWrites || Insert->forcePageWrites) && !doPageWrites) { /* Oops, must redo it with full-page data */ LWLockRelease(WALInsertLock); *************** *** 6865,6870 **** --- 6871,6886 ---- /* Pre-scan prepared transactions to find out the range of XIDs present */ oldestActiveXID = PrescanPreparedTransactions(NULL, NULL); + /* + * The startup updates FPW in shaerd-memory after REDO. However, it must + * perform before writing the WAL of the CHECKPOINT. The reason is that + * it uses a value of fpw in shared-memory when it writes a WAL of its + * CHECKPOTNT. + */ + LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); + XLogCtl->Insert.fullPageWrites = fullPageWrites; + LWLockRelease(WALInsertLock); + if (InRecovery) { int rmid; *************** *** 6998,7004 **** * backends to write WAL. */ LocalSetXLogInsertAllowed(); ! XLogReportParameters(); /* * All done. Allow backends to write WAL. (Although the bool flag is --- 7014,7020 ---- * backends to write WAL. */ LocalSetXLogInsertAllowed(); ! XLogReportParameters(true); /* * All done. Allow backends to write WAL. (Although the bool flag is *************** *** 7856,7862 **** --- 7872,7881 ---- * Update checkPoint.nextXid since we have a later value */ if (!shutdown && XLogStandbyInfoActive()) + { LogStandbySnapshot(&checkPoint.oldestActiveXid, &checkPoint.nextXid); + XLogReportParameters(false); + } else checkPoint.oldestActiveXid = InvalidTransactionId; *************** *** 8381,8393 **** * Check if any of the GUC parameters that are critical for hot standby * have changed, and update the value in pg_control file if necessary. */ ! static void ! XLogReportParameters(void) { if (wal_level != ControlFile->wal_level || MaxConnections != ControlFile->MaxConnections || max_prepared_xacts != ControlFile->max_prepared_xacts || ! max_locks_per_xact != ControlFile->max_locks_per_xact) { /* * The change in number of backend slots doesn't need to be WAL-logged --- 8400,8422 ---- * Check if any of the GUC parameters that are critical for hot standby * have changed, and update the value in pg_control file if necessary. */ ! void ! XLogReportParameters(bool fpw_manager) { + bool fpw = fullPageWrites; + + if (!fpw_manager) + { + LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); + fpw = XLogCtl->Insert.fullPageWrites; + LWLockRelease(WALInsertLock); + } + if (wal_level != ControlFile->wal_level || MaxConnections != ControlFile->MaxConnections || max_prepared_xacts != ControlFile->max_prepared_xacts || ! max_locks_per_xact != ControlFile->max_locks_per_xact || ! !fpw) { /* * The change in number of backend slots doesn't need to be WAL-logged *************** *** 8396,8402 **** * values in pg_control either if wal_level=minimal, but seems better * to keep them up-to-date to avoid confusion. */ ! if (wal_level != ControlFile->wal_level || XLogIsNeeded()) { XLogRecData rdata; xl_parameter_change xlrec; --- 8425,8431 ---- * values in pg_control either if wal_level=minimal, but seems better * to keep them up-to-date to avoid confusion. */ ! if (wal_level != ControlFile->wal_level || XLogIsNeeded() || !fpw) { XLogRecData rdata; xl_parameter_change xlrec; *************** *** 8405,8410 **** --- 8434,8440 ---- xlrec.max_prepared_xacts = max_prepared_xacts; xlrec.max_locks_per_xact = max_locks_per_xact; xlrec.wal_level = wal_level; + xlrec.fullPageWrites = fpw; rdata.buffer = InvalidBuffer; rdata.data = (char *) &xlrec; *************** *** 8420,8425 **** --- 8450,8463 ---- ControlFile->wal_level = wal_level; UpdateControlFile(); } + + /* update own fpw in shared-memory when it has managed fpw */ + if (fpw_manager) + { + LWLockAcquire(WALInsertLock, LW_EXCLUSIVE); + XLogCtl->Insert.fullPageWrites = fullPageWrites; + LWLockRelease(WALInsertLock); + } } /* *************** *** 8604,8609 **** --- 8642,8650 ---- } else if (info == XLOG_PARAMETER_CHANGE) { + /* use volatile pointer to prevent code rearrangement */ + volatile XLogCtlData *xlogctl = XLogCtl; + xl_parameter_change xlrec; /* Update our copy of the parameters in pg_control */ *************** *** 8633,8638 **** --- 8674,8687 ---- UpdateControlFile(); LWLockRelease(ControlFileLock); + /* record the LSN when FPW is false on master */ + if (!xlrec.fullPageWrites) + { + SpinLockAcquire(&xlogctl->info_lck); + xlogctl->lastFpwDisabledLSN = lsn; + SpinLockRelease(&xlogctl->info_lck); + } + /* Check to see if any changes to max_connections give problems */ CheckRequiredParameterValues(); } *************** *** 8711,8721 **** } } ! appendStringInfo(buf, "parameter change: max_connections=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s", xlrec.MaxConnections, xlrec.max_prepared_xacts, xlrec.max_locks_per_xact, ! wal_level_str); } else appendStringInfo(buf, "UNKNOWN"); --- 8760,8771 ---- } } ! appendStringInfo(buf, "parameter change: max_connections=%d max_prepared_xacts=%d max_locks_per_xact=%d wal_level=%s full_page_writes=%s", xlrec.MaxConnections, xlrec.max_prepared_xacts, xlrec.max_locks_per_xact, ! wal_level_str, ! xlrec.fullPageWrites ? "true" : "false"); } else appendStringInfo(buf, "UNKNOWN"); *************** *** 9089,9094 **** --- 9139,9152 ---- gotUniqueStartpoint = true; } while (!gotUniqueStartpoint); + /* + * check whether the master's FPW is 'off' since latest CHECKPOINT. + */ + if (recovery_in_progress && XLByteLE(startpoint, XLogCtl->lastFpwDisabledLSN)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("full_page_writes on master is set invalid at least once since latest checkpoint"))); + XLByteToSeg(startpoint, _logId, _logSeg); XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg); *************** *** 9372,9377 **** --- 9430,9441 ---- "though pg_start_backup() was executed during recovery"), errhint("The database backup will not be usable."))); + /* check whether the master's FPW is 'off' since pg_start_backup. */ + if (recovery_in_progress && XLByteLE(startpoint, XLogCtl->lastFpwDisabledLSN)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("full_page_writes on master is set invalid at least once during online backup"))); + /* * During recovery, we don't write an end-of-backup record. We can * assume that pg_control was backed up just before pg_stop_backup() diff -rcN postgresql_with_9fujii_patch/src/backend/postmaster/walwriter.c postgresql_with_patch/src/backend/postmaster/walwriter.c *** postgresql_with_9fujii_patch/src/backend/postmaster/walwriter.c 2011-10-06 06:05:45.000000000 +0900 --- postgresql_with_patch/src/backend/postmaster/walwriter.c 2011-10-11 14:53:58.000000000 +0900 *************** *** 216,221 **** --- 216,227 ---- PG_SETMASK(&UnBlockSig); /* + * After the startup process, the walwriter manages the FPW. Because + * the walwriter may have not received a SIGHUP then, it updates the FPW. + */ + XLogReportParameters(true); + + /* * Loop forever */ for (;;) *************** *** 236,241 **** --- 242,253 ---- { got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); + + /* + * The walwriter manages the FPW. When the walwriter has received + * a SIGHUP, it updates the FPW. + */ + XLogReportParameters(true); } if (shutdown_requested) { diff -rcN postgresql_with_9fujii_patch/src/include/access/xlog.h postgresql_with_patch/src/include/access/xlog.h *** postgresql_with_9fujii_patch/src/include/access/xlog.h 2011-10-06 06:05:45.000000000 +0900 --- postgresql_with_patch/src/include/access/xlog.h 2011-10-11 14:53:58.000000000 +0900 *************** *** 306,311 **** --- 306,312 ---- extern bool CreateRestartPoint(int flags); extern void XLogPutNextOid(Oid nextOid); extern XLogRecPtr XLogRestorePoint(const char *rpName); + extern void XLogReportParameters(bool fpw_manager); extern XLogRecPtr GetRedoRecPtr(void); extern XLogRecPtr GetInsertRecPtr(void); extern XLogRecPtr GetFlushRecPtr(void);