]> granicus.if.org Git - postgresql/blob - src/backend/postmaster/bgwriter.c
Replace the BufMgrLock with separate locks on the lookup hashtable and
[postgresql] / src / backend / postmaster / bgwriter.c
1 /*-------------------------------------------------------------------------
2  *
3  * bgwriter.c
4  *
5  * The background writer (bgwriter) is new in Postgres 8.0.  It attempts
6  * to keep regular backends from having to write out dirty shared buffers
7  * (which they would only do when needing to free a shared buffer to read in
8  * another page).  In the best scenario all writes from shared buffers will
9  * be issued by the background writer process.  However, regular backends are
10  * still empowered to issue writes if the bgwriter fails to maintain enough
11  * clean shared buffers.
12  *
13  * The bgwriter is also charged with handling all checkpoints.  It will
14  * automatically dispatch a checkpoint after a certain amount of time has
15  * elapsed since the last one, and it can be signaled to perform requested
16  * checkpoints as well.  (The GUC parameter that mandates a checkpoint every
17  * so many WAL segments is implemented by having backends signal the bgwriter
18  * when they fill WAL segments; the bgwriter itself doesn't watch for the
19  * condition.)
20  *
21  * The bgwriter is started by the postmaster as soon as the startup subprocess
22  * finishes.  It remains alive until the postmaster commands it to terminate.
23  * Normal termination is by SIGUSR2, which instructs the bgwriter to execute
24  * a shutdown checkpoint and then exit(0).      (All backends must be stopped
25  * before SIGUSR2 is issued!)  Emergency termination is by SIGQUIT; like any
26  * backend, the bgwriter will simply abort and exit on SIGQUIT.
27  *
28  * If the bgwriter exits unexpectedly, the postmaster treats that the same
29  * as a backend crash: shared memory may be corrupted, so remaining backends
30  * should be killed by SIGQUIT and then a recovery cycle started.  (Even if
31  * shared memory isn't corrupted, we have lost information about which
32  * files need to be fsync'd for the next checkpoint, and so a system
33  * restart needs to be forced.)
34  *
35  *
36  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
37  *
38  *
39  * IDENTIFICATION
40  *        $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.15 2005/03/04 20:21:06 tgl Exp $
41  *
42  *-------------------------------------------------------------------------
43  */
44 #include "postgres.h"
45
46 #include <signal.h>
47 #include <time.h>
48
49 #include "access/xlog.h"
50 #include "libpq/pqsignal.h"
51 #include "miscadmin.h"
52 #include "postmaster/bgwriter.h"
53 #include "storage/bufmgr.h"
54 #include "storage/freespace.h"
55 #include "storage/ipc.h"
56 #include "storage/pmsignal.h"
57 #include "storage/smgr.h"
58 #include "tcop/tcopprot.h"
59 #include "utils/guc.h"
60 #include "utils/memutils.h"
61
62
63 /*----------
64  * Shared memory area for communication between bgwriter and backends
65  *
66  * The ckpt counters allow backends to watch for completion of a checkpoint
67  * request they send.  Here's how it works:
68  *      * At start of a checkpoint, bgwriter increments ckpt_started.
69  *      * On completion of a checkpoint, bgwriter sets ckpt_done to
70  *        equal ckpt_started.
71  *      * On failure of a checkpoint, bgwrite first increments ckpt_failed,
72  *        then sets ckpt_done to equal ckpt_started.
73  * All three fields are declared sig_atomic_t to ensure they can be read
74  * and written without explicit locking.  The algorithm for backends is:
75  *      1. Record current values of ckpt_failed and ckpt_started (in that
76  *         order!).
77  *      2. Send signal to request checkpoint.
78  *      3. Sleep until ckpt_started changes.  Now you know a checkpoint has
79  *         begun since you started this algorithm (although *not* that it was
80  *         specifically initiated by your signal).
81  *      4. Record new value of ckpt_started.
82  *      5. Sleep until ckpt_done >= saved value of ckpt_started.  (Use modulo
83  *         arithmetic here in case counters wrap around.)  Now you know a
84  *         checkpoint has started and completed, but not whether it was
85  *         successful.
86  *      6. If ckpt_failed is different from the originally saved value,
87  *         assume request failed; otherwise it was definitely successful.
88  *
89  * The requests array holds fsync requests sent by backends and not yet
90  * absorbed by the bgwriter.
91  *----------
92  */
93 typedef struct
94 {
95         RelFileNode rnode;
96         BlockNumber segno;
97         /* might add a request-type field later */
98 } BgWriterRequest;
99
100 typedef struct
101 {
102         pid_t           bgwriter_pid;   /* PID of bgwriter (0 if not started) */
103
104         sig_atomic_t ckpt_started;      /* advances when checkpoint starts */
105         sig_atomic_t ckpt_done;         /* advances when checkpoint done */
106         sig_atomic_t ckpt_failed;       /* advances when checkpoint fails */
107
108         int                     num_requests;   /* current # of requests */
109         int                     max_requests;   /* allocated array size */
110         BgWriterRequest requests[1];    /* VARIABLE LENGTH ARRAY */
111 } BgWriterShmemStruct;
112
113 static BgWriterShmemStruct *BgWriterShmem;
114
115 /*
116  * GUC parameters
117  */
118 int                     BgWriterDelay = 200;
119 int                     CheckPointTimeout = 300;
120 int                     CheckPointWarning = 30;
121
122 /*
123  * Flags set by interrupt handlers for later service in the main loop.
124  */
125 static volatile sig_atomic_t got_SIGHUP = false;
126 static volatile sig_atomic_t checkpoint_requested = false;
127 static volatile sig_atomic_t shutdown_requested = false;
128
129 /*
130  * Private state
131  */
132 static bool am_bg_writer = false;
133
134 static bool ckpt_active = false;
135
136 static time_t last_checkpoint_time;
137
138
139 static void bg_quickdie(SIGNAL_ARGS);
140 static void BgSigHupHandler(SIGNAL_ARGS);
141 static void ReqCheckpointHandler(SIGNAL_ARGS);
142 static void ReqShutdownHandler(SIGNAL_ARGS);
143
144
145 /*
146  * Main entry point for bgwriter process
147  *
148  * This is invoked from BootstrapMain, which has already created the basic
149  * execution environment, but not enabled signals yet.
150  */
151 void
152 BackgroundWriterMain(void)
153 {
154         sigjmp_buf      local_sigjmp_buf;
155
156         Assert(BgWriterShmem != NULL);
157         BgWriterShmem->bgwriter_pid = MyProcPid;
158         am_bg_writer = true;
159
160         /*
161          * Properly accept or ignore signals the postmaster might send us
162          *
163          * Note: we deliberately ignore SIGTERM, because during a standard Unix
164          * system shutdown cycle, init will SIGTERM all processes at once.      We
165          * want to wait for the backends to exit, whereupon the postmaster
166          * will tell us it's okay to shut down (via SIGUSR2).
167          *
168          * SIGUSR1 is presently unused; keep it spare in case someday we want
169          * this process to participate in sinval messaging.
170          */
171         pqsignal(SIGHUP, BgSigHupHandler);      /* set flag to read config file */
172         pqsignal(SIGINT, ReqCheckpointHandler);         /* request checkpoint */
173         pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */
174         pqsignal(SIGQUIT, bg_quickdie);         /* hard crash time */
175         pqsignal(SIGALRM, SIG_IGN);
176         pqsignal(SIGPIPE, SIG_IGN);
177         pqsignal(SIGUSR1, SIG_IGN); /* reserve for sinval */
178         pqsignal(SIGUSR2, ReqShutdownHandler);          /* request shutdown */
179
180         /*
181          * Reset some signals that are accepted by postmaster but not here
182          */
183         pqsignal(SIGCHLD, SIG_DFL);
184         pqsignal(SIGTTIN, SIG_DFL);
185         pqsignal(SIGTTOU, SIG_DFL);
186         pqsignal(SIGCONT, SIG_DFL);
187         pqsignal(SIGWINCH, SIG_DFL);
188
189         /* We allow SIGQUIT (quickdie) at all times */
190 #ifdef HAVE_SIGPROCMASK
191         sigdelset(&BlockSig, SIGQUIT);
192 #else
193         BlockSig &= ~(sigmask(SIGQUIT));
194 #endif
195
196         /*
197          * Initialize so that first time-driven checkpoint happens at the
198          * correct time.
199          */
200         last_checkpoint_time = time(NULL);
201
202         /*
203          * If an exception is encountered, processing resumes here.
204          *
205          * See notes in postgres.c about the design of this coding.
206          */
207         if (sigsetjmp(local_sigjmp_buf, 1) != 0)
208         {
209                 /* Since not using PG_TRY, must reset error stack by hand */
210                 error_context_stack = NULL;
211
212                 /* Prevent interrupts while cleaning up */
213                 HOLD_INTERRUPTS();
214
215                 /* Report the error to the server log */
216                 EmitErrorReport();
217
218                 /*
219                  * These operations are really just a minimal subset of
220                  * AbortTransaction().  We don't have very many resources to worry
221                  * about in bgwriter, but we do have LWLocks and buffers.
222                  */
223                 LWLockReleaseAll();
224                 AbortBufferIO();
225                 UnlockBuffers();
226
227                 /* Warn any waiting backends that the checkpoint failed. */
228                 if (ckpt_active)
229                 {
230                         /* use volatile pointer to prevent code rearrangement */
231                         volatile BgWriterShmemStruct *bgs = BgWriterShmem;
232
233                         bgs->ckpt_failed++;
234                         bgs->ckpt_done = bgs->ckpt_started;
235                         ckpt_active = false;
236                 }
237
238                 /*
239                  * Now return to normal top-level context and clear ErrorContext
240                  * for next time.
241                  */
242                 MemoryContextSwitchTo(TopMemoryContext);
243                 FlushErrorState();
244
245                 /* Now we can allow interrupts again */
246                 RESUME_INTERRUPTS();
247
248                 /*
249                  * Sleep at least 1 second after any error.  A write error is
250                  * likely to be repeated, and we don't want to be filling the
251                  * error logs as fast as we can.  (XXX think about ways to make
252                  * progress when the LRU dirty buffer cannot be written...)
253                  */
254                 pg_usleep(1000000L);
255         }
256
257         /* We can now handle ereport(ERROR) */
258         PG_exception_stack = &local_sigjmp_buf;
259
260         /*
261          * Unblock signals (they were blocked when the postmaster forked us)
262          */
263         PG_SETMASK(&UnBlockSig);
264
265         /*
266          * Loop forever
267          */
268         for (;;)
269         {
270                 bool            do_checkpoint = false;
271                 bool            force_checkpoint = false;
272                 time_t          now;
273                 int                     elapsed_secs;
274                 long            udelay;
275
276                 /*
277                  * Emergency bailout if postmaster has died.  This is to avoid the
278                  * necessity for manual cleanup of all postmaster children.
279                  */
280                 if (!PostmasterIsAlive(true))
281                         exit(1);
282
283                 /*
284                  * Process any requests or signals received recently.
285                  */
286                 AbsorbFsyncRequests();
287
288                 if (got_SIGHUP)
289                 {
290                         got_SIGHUP = false;
291                         ProcessConfigFile(PGC_SIGHUP);
292                 }
293                 if (checkpoint_requested)
294                 {
295                         checkpoint_requested = false;
296                         do_checkpoint = true;
297                         force_checkpoint = true;
298                 }
299                 if (shutdown_requested)
300                 {
301                         ShutdownXLOG(0, 0);
302                         DumpFreeSpaceMap(0, 0);
303                         /* Normal exit from the bgwriter is here */
304                         proc_exit(0);           /* done */
305                 }
306
307                 /*
308                  * Do an unforced checkpoint if too much time has elapsed since
309                  * the last one.
310                  */
311                 now = time(NULL);
312                 elapsed_secs = now - last_checkpoint_time;
313                 if (elapsed_secs >= CheckPointTimeout)
314                         do_checkpoint = true;
315
316                 /*
317                  * Do a checkpoint if requested, otherwise do one cycle of
318                  * dirty-buffer writing.
319                  */
320                 if (do_checkpoint)
321                 {
322                         if (CheckPointWarning != 0)
323                         {
324                                 /*
325                                  * Ideally we should only warn if this checkpoint was
326                                  * requested due to running out of segment files, and not
327                                  * if it was manually requested.  However we can't tell
328                                  * the difference with the current signalling mechanism.
329                                  */
330                                 if (elapsed_secs < CheckPointWarning)
331                                         ereport(LOG,
332                                                         (errmsg("checkpoints are occurring too frequently (%d seconds apart)",
333                                                                         elapsed_secs),
334                                                          errhint("Consider increasing the configuration parameter \"checkpoint_segments\".")));
335                         }
336
337                         /*
338                          * Indicate checkpoint start to any waiting backends.
339                          */
340                         ckpt_active = true;
341                         BgWriterShmem->ckpt_started++;
342
343                         CreateCheckPoint(false, force_checkpoint);
344
345                         /*
346                          * After any checkpoint, close all smgr files.  This is so we
347                          * won't hang onto smgr references to deleted files
348                          * indefinitely.
349                          */
350                         smgrcloseall();
351
352                         /*
353                          * Indicate checkpoint completion to any waiting backends.
354                          */
355                         BgWriterShmem->ckpt_done = BgWriterShmem->ckpt_started;
356                         ckpt_active = false;
357
358                         /*
359                          * Note we record the checkpoint start time not end time as
360                          * last_checkpoint_time.  This is so that time-driven
361                          * checkpoints happen at a predictable spacing.
362                          */
363                         last_checkpoint_time = now;
364                 }
365                 else
366                         BgBufferSync();
367
368                 /*
369                  * Nap for the configured time, or sleep for 10 seconds if there
370                  * is no bgwriter activity configured.
371                  *
372                  * On some platforms, signals won't interrupt the sleep.  To ensure
373                  * we respond reasonably promptly when someone signals us, break
374                  * down the sleep into 1-second increments, and check for
375                  * interrupts after each nap.
376                  *
377                  * We absorb pending requests after each short sleep.
378                  */
379                 if ((bgwriter_all_percent > 0.0 && bgwriter_all_maxpages > 0) ||
380                         (bgwriter_lru_percent > 0.0 && bgwriter_lru_maxpages > 0))
381                         udelay = BgWriterDelay * 1000L;
382                 else
383                         udelay = 10000000L;
384                 while (udelay > 1000000L)
385                 {
386                         if (got_SIGHUP || checkpoint_requested || shutdown_requested)
387                                 break;
388                         pg_usleep(1000000L);
389                         AbsorbFsyncRequests();
390                         udelay -= 1000000L;
391                 }
392                 if (!(got_SIGHUP || checkpoint_requested || shutdown_requested))
393                         pg_usleep(udelay);
394         }
395 }
396
397
398 /* --------------------------------
399  *              signal handler routines
400  * --------------------------------
401  */
402
403 /*
404  * bg_quickdie() occurs when signalled SIGQUIT by the postmaster.
405  *
406  * Some backend has bought the farm,
407  * so we need to stop what we're doing and exit.
408  */
409 static void
410 bg_quickdie(SIGNAL_ARGS)
411 {
412         PG_SETMASK(&BlockSig);
413
414         /*
415          * DO NOT proc_exit() -- we're here because shared memory may be
416          * corrupted, so we don't want to try to clean up our transaction.
417          * Just nail the windows shut and get out of town.
418          *
419          * Note we do exit(1) not exit(0).      This is to force the postmaster into
420          * a system reset cycle if some idiot DBA sends a manual SIGQUIT to a
421          * random backend.      This is necessary precisely because we don't clean
422          * up our shared memory state.
423          */
424         exit(1);
425 }
426
427 /* SIGHUP: set flag to re-read config file at next convenient time */
428 static void
429 BgSigHupHandler(SIGNAL_ARGS)
430 {
431         got_SIGHUP = true;
432 }
433
434 /* SIGINT: set flag to run a normal checkpoint right away */
435 static void
436 ReqCheckpointHandler(SIGNAL_ARGS)
437 {
438         checkpoint_requested = true;
439 }
440
441 /* SIGUSR2: set flag to run a shutdown checkpoint and exit */
442 static void
443 ReqShutdownHandler(SIGNAL_ARGS)
444 {
445         shutdown_requested = true;
446 }
447
448
449 /* --------------------------------
450  *              communication with backends
451  * --------------------------------
452  */
453
454 /*
455  * BgWriterShmemSize
456  *              Compute space needed for bgwriter-related shared memory
457  */
458 int
459 BgWriterShmemSize(void)
460 {
461         /*
462          * Currently, the size of the requests[] array is arbitrarily set
463          * equal to NBuffers.  This may prove too large or small ...
464          */
465         return MAXALIGN(sizeof(BgWriterShmemStruct) +
466                                         (NBuffers - 1) *sizeof(BgWriterRequest));
467 }
468
469 /*
470  * BgWriterShmemInit
471  *              Allocate and initialize bgwriter-related shared memory
472  */
473 void
474 BgWriterShmemInit(void)
475 {
476         bool            found;
477
478         BgWriterShmem = (BgWriterShmemStruct *)
479                 ShmemInitStruct("Background Writer Data",
480                                                 BgWriterShmemSize(),
481                                                 &found);
482         if (BgWriterShmem == NULL)
483                 ereport(FATAL,
484                                 (errcode(ERRCODE_OUT_OF_MEMORY),
485                                  errmsg("not enough shared memory for background writer")));
486         if (found)
487                 return;                                 /* already initialized */
488
489         MemSet(BgWriterShmem, 0, sizeof(BgWriterShmemStruct));
490         BgWriterShmem->max_requests = NBuffers;
491 }
492
493 /*
494  * RequestCheckpoint
495  *              Called in backend processes to request an immediate checkpoint
496  *
497  * If waitforit is true, wait until the checkpoint is completed
498  * before returning; otherwise, just signal the request and return
499  * immediately.
500  */
501 void
502 RequestCheckpoint(bool waitforit)
503 {
504         /* use volatile pointer to prevent code rearrangement */
505         volatile BgWriterShmemStruct *bgs = BgWriterShmem;
506         sig_atomic_t old_failed = bgs->ckpt_failed;
507         sig_atomic_t old_started = bgs->ckpt_started;
508
509         /*
510          * If in a standalone backend, just do it ourselves.
511          */
512         if (!IsPostmasterEnvironment)
513         {
514                 CreateCheckPoint(false, true);
515
516                 /*
517                  * After any checkpoint, close all smgr files.  This is so we
518                  * won't hang onto smgr references to deleted files
519                  * indefinitely.
520                  */
521                 smgrcloseall();
522
523                 return;
524         }
525
526         /*
527          * Send signal to request checkpoint.  When waitforit is false, we
528          * consider failure to send the signal to be nonfatal.
529          */
530         if (BgWriterShmem->bgwriter_pid == 0)
531                 elog(waitforit ? ERROR : LOG,
532                          "could not request checkpoint because bgwriter not running");
533         if (kill(BgWriterShmem->bgwriter_pid, SIGINT) != 0)
534                 elog(waitforit ? ERROR : LOG,
535                          "could not signal for checkpoint: %m");
536
537         /*
538          * If requested, wait for completion.  We detect completion according
539          * to the algorithm given above.
540          */
541         if (waitforit)
542         {
543                 while (bgs->ckpt_started == old_started)
544                 {
545                         CHECK_FOR_INTERRUPTS();
546                         pg_usleep(100000L);
547                 }
548                 old_started = bgs->ckpt_started;
549
550                 /*
551                  * We are waiting for ckpt_done >= old_started, in a modulo sense.
552                  * This is a little tricky since we don't know the width or
553                  * signedness of sig_atomic_t.  We make the lowest common
554                  * denominator assumption that it is only as wide as "char".  This
555                  * means that this algorithm will cope correctly as long as we
556                  * don't sleep for more than 127 completed checkpoints.  (If we
557                  * do, we will get another chance to exit after 128 more
558                  * checkpoints...)
559                  */
560                 while (((signed char) (bgs->ckpt_done - old_started)) < 0)
561                 {
562                         CHECK_FOR_INTERRUPTS();
563                         pg_usleep(100000L);
564                 }
565                 if (bgs->ckpt_failed != old_failed)
566                         ereport(ERROR,
567                                         (errmsg("checkpoint request failed"),
568                                          errhint("Consult the server log for details.")));
569         }
570 }
571
572 /*
573  * ForwardFsyncRequest
574  *              Forward a file-fsync request from a backend to the bgwriter
575  *
576  * Whenever a backend is compelled to write directly to a relation
577  * (which should be seldom, if the bgwriter is getting its job done),
578  * the backend calls this routine to pass over knowledge that the relation
579  * is dirty and must be fsync'd before next checkpoint.
580  *
581  * If we are unable to pass over the request (at present, this can happen
582  * if the shared memory queue is full), we return false.  That forces
583  * the backend to do its own fsync.  We hope that will be even more seldom.
584  *
585  * Note: we presently make no attempt to eliminate duplicate requests
586  * in the requests[] queue.  The bgwriter will have to eliminate dups
587  * internally anyway, so we may as well avoid holding the lock longer
588  * than we have to here.
589  */
590 bool
591 ForwardFsyncRequest(RelFileNode rnode, BlockNumber segno)
592 {
593         BgWriterRequest *request;
594
595         if (!IsUnderPostmaster)
596                 return false;                   /* probably shouldn't even get here */
597         Assert(BgWriterShmem != NULL);
598
599         LWLockAcquire(BgWriterCommLock, LW_EXCLUSIVE);
600         if (BgWriterShmem->bgwriter_pid == 0 ||
601                 BgWriterShmem->num_requests >= BgWriterShmem->max_requests)
602         {
603                 LWLockRelease(BgWriterCommLock);
604                 return false;
605         }
606         request = &BgWriterShmem->requests[BgWriterShmem->num_requests++];
607         request->rnode = rnode;
608         request->segno = segno;
609         LWLockRelease(BgWriterCommLock);
610         return true;
611 }
612
613 /*
614  * AbsorbFsyncRequests
615  *              Retrieve queued fsync requests and pass them to local smgr.
616  *
617  * This is exported because it must be called during CreateCheckPoint;
618  * we have to be sure we have accepted all pending requests *after* we
619  * establish the checkpoint redo pointer.  Since CreateCheckPoint
620  * sometimes runs in non-bgwriter processes, do nothing if not bgwriter.
621  */
622 void
623 AbsorbFsyncRequests(void)
624 {
625         BgWriterRequest *requests = NULL;
626         BgWriterRequest *request;
627         int                     n;
628
629         if (!am_bg_writer)
630                 return;
631
632         /*
633          * We try to avoid holding the lock for a long time by copying the
634          * request array.
635          */
636         LWLockAcquire(BgWriterCommLock, LW_EXCLUSIVE);
637
638         n = BgWriterShmem->num_requests;
639         if (n > 0)
640         {
641                 requests = (BgWriterRequest *) palloc(n * sizeof(BgWriterRequest));
642                 memcpy(requests, BgWriterShmem->requests, n * sizeof(BgWriterRequest));
643         }
644         BgWriterShmem->num_requests = 0;
645
646         LWLockRelease(BgWriterCommLock);
647
648         for (request = requests; n > 0; request++, n--)
649                 RememberFsyncRequest(request->rnode, request->segno);
650         if (requests)
651                 pfree(requests);
652 }