PostgreSQL Source Code  git master
pg_checksums.c File Reference
#include "postgres_fe.h"
#include <dirent.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include "access/xlog_internal.h"
#include "common/controldata_utils.h"
#include "common/file_perm.h"
#include "common/file_utils.h"
#include "common/logging.h"
#include "getopt_long.h"
#include "pg_getopt.h"
#include "storage/bufpage.h"
#include "storage/checksum.h"
#include "storage/checksum_impl.h"
Include dependency graph for pg_checksums.c:

Go to the source code of this file.

Data Structures

struct  exclude_list_item
 

Macros

#define PG_TEMP_FILES_DIR   "pgsql_tmp"
 
#define PG_TEMP_FILE_PREFIX   "pgsql_tmp"
 

Enumerations

enum  PgChecksumMode { PG_MODE_CHECK, PG_MODE_DISABLE, PG_MODE_ENABLE }
 

Functions

static void usage (void)
 
static void progress_report (bool finished)
 
static bool skipfile (const char *fn)
 
static void scan_file (const char *fn, BlockNumber segmentno)
 
static int64 scan_directory (const char *basedir, const char *subdir, bool sizeonly)
 
int main (int argc, char *argv[])
 

Variables

static int64 files_scanned = 0
 
static int64 files_written = 0
 
static int64 blocks_scanned = 0
 
static int64 blocks_written = 0
 
static int64 badblocks = 0
 
static ControlFileDataControlFile
 
static char * only_filenode = NULL
 
static bool do_sync = true
 
static bool verbose = false
 
static bool showprogress = false
 
static PgChecksumMode mode = PG_MODE_CHECK
 
static const char * progname
 
int64 total_size = 0
 
int64 current_size = 0
 
static pg_time_t last_progress_report = 0
 
static const struct exclude_list_item skip []
 

Macro Definition Documentation

◆ PG_TEMP_FILE_PREFIX

#define PG_TEMP_FILE_PREFIX   "pgsql_tmp"

◆ PG_TEMP_FILES_DIR

#define PG_TEMP_FILES_DIR   "pgsql_tmp"

Enumeration Type Documentation

◆ PgChecksumMode

Enumerator
PG_MODE_CHECK 
PG_MODE_DISABLE 
PG_MODE_ENABLE 

Definition at line 46 of file pg_checksums.c.

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 470 of file pg_checksums.c.

References _, badblocks, ControlFileData::blcksz, blocks_scanned, blocks_written, ControlFileData::data_checksum_version, DataDir, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, do_sync, files_scanned, files_written, fprintf, get_controlfile(), get_progname(), getopt_long(), INT64_FORMAT, mode, no_argument, only_filenode, optarg, optind, PG_CONTROL_VERSION, ControlFileData::pg_control_version, PG_DATA_CHECKSUM_VERSION, pg_log_error, pg_log_info, pg_logging_init(), PG_MODE_CHECK, PG_MODE_DISABLE, PG_MODE_ENABLE, PG_TEXTDOMAIN, printf, progname, progress_report(), psprintf(), pstrdup(), required_argument, scan_directory(), set_pglocale_pgservice(), showprogress, ControlFileData::state, total_size, update_controlfile(), usage(), and verbose.

471 {
472  static struct option long_options[] = {
473  {"check", no_argument, NULL, 'c'},
474  {"pgdata", required_argument, NULL, 'D'},
475  {"disable", no_argument, NULL, 'd'},
476  {"enable", no_argument, NULL, 'e'},
477  {"filenode", required_argument, NULL, 'f'},
478  {"no-sync", no_argument, NULL, 'N'},
479  {"progress", no_argument, NULL, 'P'},
480  {"verbose", no_argument, NULL, 'v'},
481  {NULL, 0, NULL, 0}
482  };
483 
484  char *DataDir = NULL;
485  int c;
486  int option_index;
487  bool crc_ok;
488 
489  pg_logging_init(argv[0]);
490  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_checksums"));
491  progname = get_progname(argv[0]);
492 
493  if (argc > 1)
494  {
495  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
496  {
497  usage();
498  exit(0);
499  }
500  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
501  {
502  puts("pg_checksums (PostgreSQL) " PG_VERSION);
503  exit(0);
504  }
505  }
506 
507  while ((c = getopt_long(argc, argv, "cD:deNPf:v", long_options, &option_index)) != -1)
508  {
509  switch (c)
510  {
511  case 'c':
513  break;
514  case 'd':
516  break;
517  case 'e':
519  break;
520  case 'f':
521  if (atoi(optarg) == 0)
522  {
523  pg_log_error("invalid filenode specification, must be numeric: %s", optarg);
524  exit(1);
525  }
527  break;
528  case 'N':
529  do_sync = false;
530  break;
531  case 'v':
532  verbose = true;
533  break;
534  case 'D':
535  DataDir = optarg;
536  break;
537  case 'P':
538  showprogress = true;
539  break;
540  default:
541  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
542  exit(1);
543  }
544  }
545 
546  if (DataDir == NULL)
547  {
548  if (optind < argc)
549  DataDir = argv[optind++];
550  else
551  DataDir = getenv("PGDATA");
552 
553  /* If no DataDir was specified, and none could be found, error out */
554  if (DataDir == NULL)
555  {
556  pg_log_error("no data directory specified");
557  fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
558  exit(1);
559  }
560  }
561 
562  /* Complain if any arguments remain */
563  if (optind < argc)
564  {
565  pg_log_error("too many command-line arguments (first is \"%s\")",
566  argv[optind]);
567  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
568  progname);
569  exit(1);
570  }
571 
572  /* filenode checking only works in --check mode */
573  if (mode != PG_MODE_CHECK && only_filenode)
574  {
575  pg_log_error("option -f/--filenode can only be used with --check");
576  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
577  progname);
578  exit(1);
579  }
580 
581  /* Read the control file and check compatibility */
582  ControlFile = get_controlfile(DataDir, &crc_ok);
583  if (!crc_ok)
584  {
585  pg_log_error("pg_control CRC value is incorrect");
586  exit(1);
587  }
588 
590  {
591  pg_log_error("cluster is not compatible with this version of pg_checksums");
592  exit(1);
593  }
594 
595  if (ControlFile->blcksz != BLCKSZ)
596  {
597  pg_log_error("database cluster is not compatible");
598  fprintf(stderr, _("The database cluster was initialized with block size %u, but pg_checksums was compiled with block size %u.\n"),
599  ControlFile->blcksz, BLCKSZ);
600  exit(1);
601  }
602 
603  /*
604  * Check if cluster is running. A clean shutdown is required to avoid
605  * random checksum failures caused by torn pages. Note that this doesn't
606  * guard against someone starting the cluster concurrently.
607  */
608  if (ControlFile->state != DB_SHUTDOWNED &&
610  {
611  pg_log_error("cluster must be shut down");
612  exit(1);
613  }
614 
616  mode == PG_MODE_CHECK)
617  {
618  pg_log_error("data checksums are not enabled in cluster");
619  exit(1);
620  }
621 
624  {
625  pg_log_error("data checksums are already disabled in cluster");
626  exit(1);
627  }
628 
630  mode == PG_MODE_ENABLE)
631  {
632  pg_log_error("data checksums are already enabled in cluster");
633  exit(1);
634  }
635 
636  /* Operate on all files if checking or enabling checksums */
637  if (mode == PG_MODE_CHECK || mode == PG_MODE_ENABLE)
638  {
639  /*
640  * If progress status information is requested, we need to scan the
641  * directory tree twice: once to know how much total data needs to be
642  * processed and once to do the real work.
643  */
644  if (showprogress)
645  {
646  total_size = scan_directory(DataDir, "global", true);
647  total_size += scan_directory(DataDir, "base", true);
648  total_size += scan_directory(DataDir, "pg_tblspc", true);
649  }
650 
651  (void) scan_directory(DataDir, "global", false);
652  (void) scan_directory(DataDir, "base", false);
653  (void) scan_directory(DataDir, "pg_tblspc", false);
654 
655  if (showprogress)
656  progress_report(true);
657 
658  printf(_("Checksum operation completed\n"));
659  printf(_("Files scanned: %s\n"), psprintf(INT64_FORMAT, files_scanned));
660  printf(_("Blocks scanned: %s\n"), psprintf(INT64_FORMAT, blocks_scanned));
661  if (mode == PG_MODE_CHECK)
662  {
663  printf(_("Bad checksums: %s\n"), psprintf(INT64_FORMAT, badblocks));
664  printf(_("Data checksum version: %u\n"), ControlFile->data_checksum_version);
665 
666  if (badblocks > 0)
667  exit(1);
668  }
669  else if (mode == PG_MODE_ENABLE)
670  {
671  printf(_("Files written: %s\n"), psprintf(INT64_FORMAT, files_written));
672  printf(_("Blocks written: %s\n"), psprintf(INT64_FORMAT, blocks_written));
673  }
674  }
675 
676  /*
677  * Finally make the data durable on disk if enabling or disabling
678  * checksums. Flush first the data directory for safety, and then update
679  * the control file to keep the switch consistent.
680  */
682  {
685 
686  if (do_sync)
687  {
688  pg_log_info("syncing data directory");
689  fsync_pgdata(DataDir, PG_VERSION_NUM);
690  }
691 
692  pg_log_info("updating control file");
694 
695  if (verbose)
696  printf(_("Data checksum version: %u\n"), ControlFile->data_checksum_version);
697  if (mode == PG_MODE_ENABLE)
698  printf(_("Checksums enabled in cluster\n"));
699  else
700  printf(_("Checksums disabled in cluster\n"));
701  }
702 
703  return 0;
704 }
static PgChecksumMode mode
Definition: pg_checksums.c:63
static const char * progname
Definition: pg_checksums.c:65
const char * get_progname(const char *argv0)
Definition: path.c:453
#define pg_log_error(...)
Definition: logging.h:80
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
static void usage(void)
Definition: pg_checksums.c:75
char * pstrdup(const char *in)
Definition: mcxt.c:1299
void pg_logging_init(const char *argv0)
Definition: logging.c:81
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static ControlFileData * ControlFile
Definition: pg_checksums.c:39
static int64 blocks_scanned
Definition: pg_checksums.c:36
#define PG_CONTROL_VERSION
Definition: pg_control.h:25
uint32 pg_control_version
Definition: pg_control.h:121
#define printf(...)
Definition: port.h:222
static bool showprogress
Definition: pg_checksums.c:44
#define fprintf
Definition: port.h:220
void update_controlfile(const char *DataDir, ControlFileData *ControlFile, bool do_sync)
#define required_argument
Definition: getopt_long.h:25
int optind
Definition: getopt.c:50
uint32 data_checksum_version
Definition: pg_control.h:220
char * c
static int64 files_written
Definition: pg_checksums.c:35
static bool do_sync
Definition: pg_checksums.c:42
static int64 scan_directory(const char *basedir, const char *subdir, bool sizeonly)
Definition: pg_checksums.c:325
static bool verbose
Definition: pg_checksums.c:43
static int64 files_scanned
Definition: pg_checksums.c:34
#define no_argument
Definition: getopt_long.h:24
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1215
int64 total_size
Definition: pg_checksums.c:70
ControlFileData * get_controlfile(const char *DataDir, bool *crc_ok_p)
#define INT64_FORMAT
Definition: c.h:483
static int64 blocks_written
Definition: pg_checksums.c:37
static void progress_report(bool finished)
Definition: pg_checksums.c:130
static char * only_filenode
Definition: pg_checksums.c:41
static int64 badblocks
Definition: pg_checksums.c:38
#define PG_DATA_CHECKSUM_VERSION
Definition: bufpage.h:200
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:433
char * optarg
Definition: getopt.c:52
char * DataDir
Definition: globals.c:65
#define _(x)
Definition: elog.c:89
#define pg_log_info(...)
Definition: logging.h:88

◆ progress_report()

static void progress_report ( bool  finished)
static

Definition at line 130 of file pg_checksums.c.

References _, Assert, current_size, fprintf, INT64_FORMAT, last_progress_report, now(), showprogress, snprintf, and total_size.

Referenced by main(), and scan_file().

131 {
132  int percent;
133  char total_size_str[32];
134  char current_size_str[32];
135  pg_time_t now;
136 
138 
139  now = time(NULL);
140  if (now == last_progress_report && !finished)
141  return; /* Max once per second */
142 
143  /* Save current time */
145 
146  /* Adjust total size if current_size is larger */
147  if (current_size > total_size)
149 
150  /* Calculate current percentage of size done */
151  percent = total_size ? (int) ((current_size) * 100 / total_size) : 0;
152 
153  /*
154  * Separate step to keep platform-dependent format code out of
155  * translatable strings. And we only test for INT64_FORMAT availability
156  * in snprintf, not fprintf.
157  */
158  snprintf(total_size_str, sizeof(total_size_str), INT64_FORMAT,
159  total_size / (1024 * 1024));
160  snprintf(current_size_str, sizeof(current_size_str), INT64_FORMAT,
161  current_size / (1024 * 1024));
162 
163  fprintf(stderr, _("%*s/%s MB (%d%%) computed"),
164  (int) strlen(current_size_str), current_size_str, total_size_str,
165  percent);
166 
167  /*
168  * Stay on the same line if reporting to a terminal and we're not done
169  * yet.
170  */
171  fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
172 }
int64 pg_time_t
Definition: pgtime.h:23
static bool showprogress
Definition: pg_checksums.c:44
#define fprintf
Definition: port.h:220
int64 total_size
Definition: pg_checksums.c:70
#define Assert(condition)
Definition: c.h:804
static pg_time_t last_progress_report
Definition: pg_checksums.c:72
#define INT64_FORMAT
Definition: c.h:483
int64 current_size
Definition: pg_checksums.c:71
#define snprintf
Definition: port.h:216
#define _(x)
Definition: elog.c:89
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1544

◆ scan_directory()

static int64 scan_directory ( const char *  basedir,
const char *  subdir,
bool  sizeonly 
)
static

Definition at line 325 of file pg_checksums.c.

References closedir(), dirent::d_name, fn(), lstat, MAXPGPATH, only_filenode, opendir(), pg_log_error, PG_TEMP_FILE_PREFIX, PG_TEMP_FILES_DIR, pgwin32_is_junction(), readdir(), S_ISDIR, S_ISREG, scan_file(), skipfile(), snprintf, stat::st_mode, stat::st_size, strlcpy(), and TABLESPACE_VERSION_DIRECTORY.

Referenced by main().

326 {
327  int64 dirsize = 0;
328  char path[MAXPGPATH];
329  DIR *dir;
330  struct dirent *de;
331 
332  snprintf(path, sizeof(path), "%s/%s", basedir, subdir);
333  dir = opendir(path);
334  if (!dir)
335  {
336  pg_log_error("could not open directory \"%s\": %m", path);
337  exit(1);
338  }
339  while ((de = readdir(dir)) != NULL)
340  {
341  char fn[MAXPGPATH];
342  struct stat st;
343 
344  if (strcmp(de->d_name, ".") == 0 ||
345  strcmp(de->d_name, "..") == 0)
346  continue;
347 
348  /* Skip temporary files */
349  if (strncmp(de->d_name,
351  strlen(PG_TEMP_FILE_PREFIX)) == 0)
352  continue;
353 
354  /* Skip temporary folders */
355  if (strncmp(de->d_name,
357  strlen(PG_TEMP_FILES_DIR)) == 0)
358  continue;
359 
360  snprintf(fn, sizeof(fn), "%s/%s", path, de->d_name);
361  if (lstat(fn, &st) < 0)
362  {
363  pg_log_error("could not stat file \"%s\": %m", fn);
364  exit(1);
365  }
366  if (S_ISREG(st.st_mode))
367  {
368  char fnonly[MAXPGPATH];
369  char *forkpath,
370  *segmentpath;
371  BlockNumber segmentno = 0;
372 
373  if (skipfile(de->d_name))
374  continue;
375 
376  /*
377  * Cut off at the segment boundary (".") to get the segment number
378  * in order to mix it into the checksum. Then also cut off at the
379  * fork boundary, to get the filenode the file belongs to for
380  * filtering.
381  */
382  strlcpy(fnonly, de->d_name, sizeof(fnonly));
383  segmentpath = strchr(fnonly, '.');
384  if (segmentpath != NULL)
385  {
386  *segmentpath++ = '\0';
387  segmentno = atoi(segmentpath);
388  if (segmentno == 0)
389  {
390  pg_log_error("invalid segment number %d in file name \"%s\"",
391  segmentno, fn);
392  exit(1);
393  }
394  }
395 
396  forkpath = strchr(fnonly, '_');
397  if (forkpath != NULL)
398  *forkpath++ = '\0';
399 
400  if (only_filenode && strcmp(only_filenode, fnonly) != 0)
401  /* filenode not to be included */
402  continue;
403 
404  dirsize += st.st_size;
405 
406  /*
407  * No need to work on the file when calculating only the size of
408  * the items in the data folder.
409  */
410  if (!sizeonly)
411  scan_file(fn, segmentno);
412  }
413 #ifndef WIN32
414  else if (S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))
415 #else
416  else if (S_ISDIR(st.st_mode) || pgwin32_is_junction(fn))
417 #endif
418  {
419  /*
420  * If going through the entries of pg_tblspc, we assume to operate
421  * on tablespace locations where only TABLESPACE_VERSION_DIRECTORY
422  * is valid, resolving the linked locations and dive into them
423  * directly.
424  */
425  if (strncmp("pg_tblspc", subdir, strlen("pg_tblspc")) == 0)
426  {
427  char tblspc_path[MAXPGPATH];
428  struct stat tblspc_st;
429 
430  /*
431  * Resolve tablespace location path and check whether
432  * TABLESPACE_VERSION_DIRECTORY exists. Not finding a valid
433  * location is unexpected, since there should be no orphaned
434  * links and no links pointing to something else than a
435  * directory.
436  */
437  snprintf(tblspc_path, sizeof(tblspc_path), "%s/%s/%s",
439 
440  if (lstat(tblspc_path, &tblspc_st) < 0)
441  {
442  pg_log_error("could not stat file \"%s\": %m",
443  tblspc_path);
444  exit(1);
445  }
446 
447  /*
448  * Move backwards once as the scan needs to happen for the
449  * contents of TABLESPACE_VERSION_DIRECTORY.
450  */
451  snprintf(tblspc_path, sizeof(tblspc_path), "%s/%s",
452  path, de->d_name);
453 
454  /* Looks like a valid tablespace location */
455  dirsize += scan_directory(tblspc_path,
457  sizeonly);
458  }
459  else
460  {
461  dirsize += scan_directory(path, de->d_name, sizeonly);
462  }
463  }
464  }
465  closedir(dir);
466  return dirsize;
467 }
#define pg_log_error(...)
Definition: logging.h:80
int closedir(DIR *)
Definition: dirent.c:123
#define PG_TEMP_FILES_DIR
Definition: pg_checksums.c:60
uint32 BlockNumber
Definition: block.h:31
Definition: dirent.h:9
static char * basedir
Definition: dirent.c:25
#define PG_TEMP_FILE_PREFIX
Definition: pg_checksums.c:61
#define MAXPGPATH
DIR * opendir(const char *)
Definition: dirent.c:33
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
static int64 scan_directory(const char *basedir, const char *subdir, bool sizeonly)
Definition: pg_checksums.c:325
#define S_ISREG(m)
Definition: win32_port.h:319
static void * fn(void *arg)
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static void scan_file(const char *fn, BlockNumber segmentno)
Definition: pg_checksums.c:193
struct dirent * readdir(DIR *)
Definition: dirent.c:78
#define S_ISDIR(m)
Definition: win32_port.h:316
#define lstat(path, sb)
Definition: win32_port.h:276
static char * only_filenode
Definition: pg_checksums.c:41
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
static bool skipfile(const char *fn)
Definition: pg_checksums.c:175
bool pgwin32_is_junction(const char *path)

◆ scan_file()

static void scan_file ( const char *  fn,
BlockNumber  segmentno 
)
static

Definition at line 193 of file pg_checksums.c.

References Assert, badblocks, blocks_scanned, blocks_written, buf, close, current_size, PGAlignedBlock::data, ControlFileData::data_checksum_version, files_scanned, files_written, header(), mode, PageIsNew, PageHeaderData::pd_checksum, PG_BINARY, pg_checksum_page(), PG_DATA_CHECKSUM_VERSION, pg_log_error, pg_log_info, PG_MODE_CHECK, PG_MODE_ENABLE, progress_report(), read, showprogress, verbose, and write.

Referenced by scan_directory().

194 {
197  int f;
198  BlockNumber blockno;
199  int flags;
200  int64 blocks_written_in_file = 0;
201 
203  mode == PG_MODE_CHECK);
204 
205  flags = (mode == PG_MODE_ENABLE) ? O_RDWR : O_RDONLY;
206  f = open(fn, PG_BINARY | flags, 0);
207 
208  if (f < 0)
209  {
210  pg_log_error("could not open file \"%s\": %m", fn);
211  exit(1);
212  }
213 
214  files_scanned++;
215 
216  for (blockno = 0;; blockno++)
217  {
218  uint16 csum;
219  int r = read(f, buf.data, BLCKSZ);
220 
221  if (r == 0)
222  break;
223  if (r != BLCKSZ)
224  {
225  if (r < 0)
226  pg_log_error("could not read block %u in file \"%s\": %m",
227  blockno, fn);
228  else
229  pg_log_error("could not read block %u in file \"%s\": read %d of %d",
230  blockno, fn, r, BLCKSZ);
231  exit(1);
232  }
233  blocks_scanned++;
234 
235  /*
236  * Since the file size is counted as total_size for progress status
237  * information, the sizes of all pages including new ones in the file
238  * should be counted as current_size. Otherwise the progress reporting
239  * calculated using those counters may not reach 100%.
240  */
241  current_size += r;
242 
243  /* New pages have no checksum yet */
244  if (PageIsNew(header))
245  continue;
246 
247  csum = pg_checksum_page(buf.data, blockno + segmentno * RELSEG_SIZE);
248  if (mode == PG_MODE_CHECK)
249  {
250  if (csum != header->pd_checksum)
251  {
253  pg_log_error("checksum verification failed in file \"%s\", block %u: calculated checksum %X but block contains %X",
254  fn, blockno, csum, header->pd_checksum);
255  badblocks++;
256  }
257  }
258  else if (mode == PG_MODE_ENABLE)
259  {
260  int w;
261 
262  /*
263  * Do not rewrite if the checksum is already set to the expected
264  * value.
265  */
266  if (header->pd_checksum == csum)
267  continue;
268 
269  blocks_written_in_file++;
270 
271  /* Set checksum in page header */
272  header->pd_checksum = csum;
273 
274  /* Seek back to beginning of block */
275  if (lseek(f, -BLCKSZ, SEEK_CUR) < 0)
276  {
277  pg_log_error("seek failed for block %u in file \"%s\": %m", blockno, fn);
278  exit(1);
279  }
280 
281  /* Write block with checksum */
282  w = write(f, buf.data, BLCKSZ);
283  if (w != BLCKSZ)
284  {
285  if (w < 0)
286  pg_log_error("could not write block %u in file \"%s\": %m",
287  blockno, fn);
288  else
289  pg_log_error("could not write block %u in file \"%s\": wrote %d of %d",
290  blockno, fn, w, BLCKSZ);
291  exit(1);
292  }
293  }
294 
295  if (showprogress)
296  progress_report(false);
297  }
298 
299  if (verbose)
300  {
301  if (mode == PG_MODE_CHECK)
302  pg_log_info("checksums verified in file \"%s\"", fn);
303  if (mode == PG_MODE_ENABLE)
304  pg_log_info("checksums enabled in file \"%s\"", fn);
305  }
306 
307  /* Update write counters if any write activity has happened */
308  if (blocks_written_in_file > 0)
309  {
310  files_written++;
311  blocks_written += blocks_written_in_file;
312  }
313 
314  close(f);
315 }
static PgChecksumMode mode
Definition: pg_checksums.c:63
#define write(a, b, c)
Definition: win32.h:14
#define pg_log_error(...)
Definition: logging.h:80
static ControlFileData * ControlFile
Definition: pg_checksums.c:39
static int64 blocks_scanned
Definition: pg_checksums.c:36
uint32 BlockNumber
Definition: block.h:31
static bool showprogress
Definition: pg_checksums.c:44
#define PG_BINARY
Definition: c.h:1271
uint16 pd_checksum
Definition: bufpage.h:156
char data[BLCKSZ]
Definition: c.h:1141
unsigned short uint16
Definition: c.h:440
uint32 data_checksum_version
Definition: pg_control.h:220
static char * buf
Definition: pg_test_fsync.c:68
static int64 files_written
Definition: pg_checksums.c:35
static bool verbose
Definition: pg_checksums.c:43
static int64 files_scanned
Definition: pg_checksums.c:34
static void * fn(void *arg)
PageHeaderData * PageHeader
Definition: bufpage.h:166
#define Assert(condition)
Definition: c.h:804
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:210
static int64 blocks_written
Definition: pg_checksums.c:37
static void progress_report(bool finished)
Definition: pg_checksums.c:130
static int64 badblocks
Definition: pg_checksums.c:38
#define PG_DATA_CHECKSUM_VERSION
Definition: bufpage.h:200
#define PageIsNew(page)
Definition: bufpage.h:229
int64 current_size
Definition: pg_checksums.c:71
#define close(a)
Definition: win32.h:12
uint16 pg_checksum_page(char *page, BlockNumber blkno)
#define read(a, b, c)
Definition: win32.h:13
#define pg_log_info(...)
Definition: logging.h:88

◆ skipfile()

static bool skipfile ( const char *  fn)
static

Definition at line 175 of file pg_checksums.c.

References exclude_list_item::match_prefix, and exclude_list_item::name.

Referenced by scan_directory().

176 {
177  int excludeIdx;
178 
179  for (excludeIdx = 0; skip[excludeIdx].name != NULL; excludeIdx++)
180  {
181  int cmplen = strlen(skip[excludeIdx].name);
182 
183  if (!skip[excludeIdx].match_prefix)
184  cmplen++;
185  if (strncmp(skip[excludeIdx].name, fn, cmplen) == 0)
186  return true;
187  }
188 
189  return false;
190 }
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:114
static void * fn(void *arg)
const char * name
Definition: encode.c:515
const char * name
Definition: basebackup.c:141

◆ usage()

static void usage ( void  )
static

Definition at line 75 of file pg_checksums.c.

References _, exclude_list_item::match_prefix, exclude_list_item::name, printf, and progname.

Referenced by main().

76 {
77  printf(_("%s enables, disables, or verifies data checksums in a PostgreSQL database cluster.\n\n"), progname);
78  printf(_("Usage:\n"));
79  printf(_(" %s [OPTION]... [DATADIR]\n"), progname);
80  printf(_("\nOptions:\n"));
81  printf(_(" [-D, --pgdata=]DATADIR data directory\n"));
82  printf(_(" -c, --check check data checksums (default)\n"));
83  printf(_(" -d, --disable disable data checksums\n"));
84  printf(_(" -e, --enable enable data checksums\n"));
85  printf(_(" -f, --filenode=FILENODE check only relation with specified filenode\n"));
86  printf(_(" -N, --no-sync do not wait for changes to be written safely to disk\n"));
87  printf(_(" -P, --progress show progress information\n"));
88  printf(_(" -v, --verbose output verbose messages\n"));
89  printf(_(" -V, --version output version information, then exit\n"));
90  printf(_(" -?, --help show this help, then exit\n"));
91  printf(_("\nIf no data directory (DATADIR) is specified, "
92  "the environment variable PGDATA\nis used.\n\n"));
93  printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
94  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
95 }
static const char * progname
Definition: pg_checksums.c:65
#define printf(...)
Definition: port.h:222
#define _(x)
Definition: elog.c:89

Variable Documentation

◆ badblocks

int64 badblocks = 0
static

Definition at line 38 of file pg_checksums.c.

Referenced by main(), and scan_file().

◆ blocks_scanned

int64 blocks_scanned = 0
static

Definition at line 36 of file pg_checksums.c.

Referenced by main(), and scan_file().

◆ blocks_written

int64 blocks_written = 0
static

Definition at line 37 of file pg_checksums.c.

Referenced by main(), and scan_file().

◆ ControlFile

ControlFileData* ControlFile
static

Definition at line 39 of file pg_checksums.c.

◆ current_size

int64 current_size = 0

Definition at line 71 of file pg_checksums.c.

Referenced by progress_report(), scan_file(), and unicode_normalize().

◆ do_sync

bool do_sync = true
static

Definition at line 42 of file pg_checksums.c.

Referenced by main().

◆ files_scanned

int64 files_scanned = 0
static

Definition at line 34 of file pg_checksums.c.

Referenced by main(), and scan_file().

◆ files_written

int64 files_written = 0
static

Definition at line 35 of file pg_checksums.c.

Referenced by main(), and scan_file().

◆ last_progress_report

pg_time_t last_progress_report = 0
static

Definition at line 72 of file pg_checksums.c.

Referenced by progress_report().

◆ mode

Definition at line 63 of file pg_checksums.c.

Referenced by _allocAH(), _copyFunctionParameter(), _copyLockStmt(), _equalFunctionParameter(), _equalLockStmt(), be_lo_open(), bf_load(), from_char_set_mode(), get_mxact_status_for_lock(), GetLockmodeName(), GetMultiXactIdHintBits(), has_any_column_privilege_id(), has_any_column_privilege_id_id(), has_any_column_privilege_id_name(), has_any_column_privilege_name(), has_any_column_privilege_name_id(), has_any_column_privilege_name_name(), has_column_privilege_id_attnum(), has_column_privilege_id_id_attnum(), has_column_privilege_id_id_name(), has_column_privilege_id_name(), has_column_privilege_id_name_attnum(), has_column_privilege_id_name_name(), has_column_privilege_name_attnum(), has_column_privilege_name_id_attnum(), has_column_privilege_name_id_name(), has_column_privilege_name_name(), has_column_privilege_name_name_attnum(), has_column_privilege_name_name_name(), has_database_privilege_id(), has_database_privilege_id_id(), has_database_privilege_id_name(), has_database_privilege_name(), has_database_privilege_name_id(), has_database_privilege_name_name(), has_foreign_data_wrapper_privilege_id(), has_foreign_data_wrapper_privilege_id_id(), has_foreign_data_wrapper_privilege_id_name(), has_foreign_data_wrapper_privilege_name(), has_foreign_data_wrapper_privilege_name_id(), has_foreign_data_wrapper_privilege_name_name(), has_function_privilege_id(), has_function_privilege_id_id(), has_function_privilege_id_name(), has_function_privilege_name(), has_function_privilege_name_id(), has_function_privilege_name_name(), has_language_privilege_id(), has_language_privilege_id_id(), has_language_privilege_id_name(), has_language_privilege_name(), has_language_privilege_name_id(), has_language_privilege_name_name(), has_schema_privilege_id(), has_schema_privilege_id_id(), has_schema_privilege_id_name(), has_schema_privilege_name(), has_schema_privilege_name_id(), has_schema_privilege_name_name(), has_sequence_privilege_id(), has_sequence_privilege_id_id(), has_sequence_privilege_id_name(), has_sequence_privilege_name(), has_sequence_privilege_name_id(), has_sequence_privilege_name_name(), has_server_privilege_id(), has_server_privilege_id_id(), has_server_privilege_id_name(), has_server_privilege_name(), has_server_privilege_name_id(), has_server_privilege_name_name(), has_table_privilege_id(), has_table_privilege_id_id(), has_table_privilege_id_name(), has_table_privilege_name(), has_table_privilege_name_id(), has_table_privilege_name_name(), has_tablespace_privilege_id(), has_tablespace_privilege_id_id(), has_tablespace_privilege_id_name(), has_tablespace_privilege_name(), has_tablespace_privilege_name_id(), has_tablespace_privilege_name_name(), has_type_privilege_id(), has_type_privilege_id_id(), has_type_privilege_id_name(), has_type_privilege_name(), has_type_privilege_name_id(), has_type_privilege_name_name(), lo_creat(), lo_open(), main(), open_target_file(), pg_has_role_id(), pg_has_role_id_id(), pg_has_role_id_name(), pg_has_role_name(), pg_has_role_name_id(), pg_has_role_name_name(), pg_lock_status(), pgp_s2k_fill(), pgp_set_s2k_mode(), pgp_set_text_mode(), pgtls_verify_peer_name_matches_certificate_guts(), raw_parser(), rj_load(), scan_file(), SyncRepQueueInsert(), SyncRepUpdateSyncStandbysDefined(), SyncRepWaitForLSN(), SyncRepWakeQueue(), and tarOpen().

◆ only_filenode

char* only_filenode = NULL
static

Definition at line 41 of file pg_checksums.c.

Referenced by main(), and scan_directory().

◆ progname

const char* progname
static

Definition at line 65 of file pg_checksums.c.

Referenced by main(), and usage().

◆ showprogress

bool showprogress = false
static

Definition at line 44 of file pg_checksums.c.

Referenced by main(), progress_report(), and scan_file().

◆ skip

const struct exclude_list_item skip[]
static
Initial value:
= {
{"pg_control", false},
{"pg_filenode.map", false},
{"pg_internal.init", true},
{"PG_VERSION", false},
{NULL, false}
}

Definition at line 114 of file pg_checksums.c.

Referenced by array_replace_internal(), DefineVirtualRelation(), dependencies_clauselist_selectivity(), heap_hot_search_buffer(), initTrie(), and verify_heapam().

◆ total_size

int64 total_size = 0

Definition at line 70 of file pg_checksums.c.

Referenced by main(), make_new_segment(), and progress_report().

◆ verbose

bool verbose = false
static

Definition at line 43 of file pg_checksums.c.

Referenced by main(), and scan_file().