diff options
Diffstat (limited to 'src/backend/utils/adt/pagefuncs.c')
-rw-r--r-- | src/backend/utils/adt/pagefuncs.c | 229 |
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; -} |