aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/pagefuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/pagefuncs.c')
-rw-r--r--src/backend/utils/adt/pagefuncs.c229
1 files changed, 0 insertions, 229 deletions
diff --git a/src/backend/utils/adt/pagefuncs.c b/src/backend/utils/adt/pagefuncs.c
deleted file mode 100644
index 368ada515cf..00000000000
--- a/src/backend/utils/adt/pagefuncs.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * pagefuncs.c
- * Functions for features related to relation pages.
- *
- * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/backend/utils/adt/pagefuncs.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-#include "access/relation.h"
-#include "funcapi.h"
-#include "miscadmin.h"
-#include "storage/bufmgr.h"
-#include "storage/lmgr.h"
-#include "storage/smgr.h"
-#include "utils/builtins.h"
-#include "utils/syscache.h"
-
-static void check_one_relation(TupleDesc tupdesc, Tuplestorestate *tupstore,
- Oid relid, ForkNumber single_forknum);
-static void check_relation_fork(TupleDesc tupdesc, Tuplestorestate *tupstore,
- Relation relation, ForkNumber forknum);
-
-/*
- * callback arguments for check_pages_error_callback()
- */
-typedef struct CheckPagesErrorInfo
-{
- char *path;
- BlockNumber blkno;
-} CheckPagesErrorInfo;
-
-/*
- * Error callback specific to check_relation_fork().
- */
-static void
-check_pages_error_callback(void *arg)
-{
- CheckPagesErrorInfo *errinfo = (CheckPagesErrorInfo *) arg;
-
- errcontext("while checking page %u of path %s",
- errinfo->blkno, errinfo->path);
-}
-
-/*
- * pg_relation_check_pages
- *
- * Check the state of all the pages for one or more fork types in the given
- * relation.
- */
-Datum
-pg_relation_check_pages(PG_FUNCTION_ARGS)
-{
- Oid relid;
- ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
- ForkNumber forknum;
-
- /* Switch into long-lived context to construct returned data structures */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
-
- /* handle arguments */
- if (PG_ARGISNULL(0))
- {
- /* Just leave if nothing is defined */
- PG_RETURN_VOID();
- }
-
- /* By default all the forks of a relation are checked */
- if (PG_ARGISNULL(1))
- forknum = InvalidForkNumber;
- else
- {
- const char *forkname = TextDatumGetCString(PG_GETARG_TEXT_PP(1));
-
- forknum = forkname_to_number(forkname);
- }
-
- relid = PG_GETARG_OID(0);
-
- check_one_relation(tupdesc, tupstore, relid, forknum);
- tuplestore_donestoring(tupstore);
-
- return (Datum) 0;
-}
-
-/*
- * Perform the check on a single relation, possibly filtered with a single
- * fork. This function will check if the given relation exists or not, as
- * a relation could be dropped after checking for the list of relations and
- * before getting here, and we don't want to error out in this case.
- */
-static void
-check_one_relation(TupleDesc tupdesc, Tuplestorestate *tupstore,
- Oid relid, ForkNumber single_forknum)
-{
- Relation relation;
- ForkNumber forknum;
-
- /* Check if relation exists. leaving if there is no such relation */
- if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
- return;
-
- relation = relation_open(relid, AccessShareLock);
-
- /*
- * Sanity checks, returning no results if not supported. Temporary
- * relations and relations without storage are out of scope.
- */
- if (!RELKIND_HAS_STORAGE(relation->rd_rel->relkind) ||
- relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
- {
- relation_close(relation, AccessShareLock);
- return;
- }
-
- RelationOpenSmgr(relation);
-
- for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
- {
- if (single_forknum != InvalidForkNumber && single_forknum != forknum)
- continue;
-
- if (smgrexists(relation->rd_smgr, forknum))
- check_relation_fork(tupdesc, tupstore, relation, forknum);
- }
-
- relation_close(relation, AccessShareLock);
-}
-
-/*
- * For a given relation and fork, do the real work of iterating over all pages
- * and doing the check. Caller must hold an AccessShareLock lock on the given
- * relation.
- */
-static void
-check_relation_fork(TupleDesc tupdesc, Tuplestorestate *tupstore,
- Relation relation, ForkNumber forknum)
-{
- BlockNumber blkno,
- nblocks;
- SMgrRelation smgr = relation->rd_smgr;
- char *path;
- CheckPagesErrorInfo errinfo;
- ErrorContextCallback errcallback;
-
- /* Number of output arguments in the SRF */
-#define PG_CHECK_RELATION_COLS 2
-
- Assert(CheckRelationLockedByMe(relation, AccessShareLock, true));
-
- /*
- * We remember the number of blocks here. Since caller must hold a lock
- * on the relation, we know that it won't be truncated while we are
- * iterating over the blocks. Any block added after this function started
- * will not be checked.
- */
- nblocks = RelationGetNumberOfBlocksInFork(relation, forknum);
-
- path = relpathbackend(smgr->smgr_rnode.node,
- smgr->smgr_rnode.backend,
- forknum);
-
- /*
- * Error context to print some information about blocks and relations
- * impacted by corruptions.
- */
- errinfo.path = pstrdup(path);
- errinfo.blkno = 0;
- errcallback.callback = check_pages_error_callback;
- errcallback.arg = (void *) &errinfo;
- errcallback.previous = error_context_stack;
- error_context_stack = &errcallback;
-
- for (blkno = 0; blkno < nblocks; blkno++)
- {
- Datum values[PG_CHECK_RELATION_COLS];
- bool nulls[PG_CHECK_RELATION_COLS];
- int i = 0;
-
- /* Update block number for the error context */
- errinfo.blkno = blkno;
-
- CHECK_FOR_INTERRUPTS();
-
- /* Check the given buffer */
- if (CheckBuffer(smgr, forknum, blkno))
- continue;
-
- memset(values, 0, sizeof(values));
- memset(nulls, 0, sizeof(nulls));
-
- values[i++] = CStringGetTextDatum(path);
- values[i++] = Int64GetDatum((int64) blkno);
-
- Assert(i == PG_CHECK_RELATION_COLS);
-
- /* Save the corrupted blocks in the tuplestore. */
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
- }
-
- pfree(path);
-
- /* Pop the error context stack */
- error_context_stack = errcallback.previous;
-}