Skip to content

Commit

Permalink
Rewrite the FSM. Instead of relying on a fixed-size shared memory seg…
Browse files Browse the repository at this point in the history
…ment, the

free space information is stored in a dedicated FSM relation fork, with each
relation (except for hash indexes; they don't use FSM).

This eliminates the max_fsm_relations and max_fsm_pages GUC options; remove any
trace of them from the backend, initdb, and documentation.

Rewrite contrib/pg_freespacemap to match the new FSM implementation. Also
introduce a new variant of the get_raw_page(regclass, int4, int4) function in
contrib/pageinspect that let's you to return pages from any relation fork, and
a new fsm_page_contents() function to inspect the new FSM pages.
  • Loading branch information
hlinnaka committed Sep 30, 2008
1 parent 2dbc0ca commit 15c121b
Show file tree
Hide file tree
Showing 53 changed files with 1,755 additions and 2,631 deletions.
4 changes: 2 additions & 2 deletions contrib/pageinspect/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
#
# pageinspect Makefile
#
# $PostgreSQL: pgsql/contrib/pageinspect/Makefile,v 1.3 2007/11/10 23:59:51 momjian Exp $
# $PostgreSQL: pgsql/contrib/pageinspect/Makefile,v 1.4 2008/09/30 10:52:09 heikki Exp $
#
#-------------------------------------------------------------------------

MODULE_big = pageinspect
OBJS = rawpage.o heapfuncs.o btreefuncs.o
OBJS = rawpage.o heapfuncs.o btreefuncs.o fsmfuncs.o
DATA_built = pageinspect.sql
DATA = uninstall_pageinspect.sql

Expand Down
61 changes: 61 additions & 0 deletions contrib/pageinspect/fsmfuncs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*-------------------------------------------------------------------------
*
* fsmfuncs.c
* Functions to investigate FSM pages
*
* These functions are restricted to superusers for the fear of introducing
* security holes if the input checking isn't as water-tight as it should.
* You'd need to be superuser to obtain a raw page image anyway, so
* there's hardly any use case for using these without superuser-rights
* anyway.
*
* Copyright (c) 2007-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/contrib/pageinspect/fsmfuncs.c,v 1.1 2008/09/30 10:52:09 heikki Exp $
*
*-------------------------------------------------------------------------
*/

#include "postgres.h"
#include "lib/stringinfo.h"
#include "storage/fsm_internals.h"
#include "utils/builtins.h"
#include "miscadmin.h"
#include "funcapi.h"

Datum fsm_page_contents(PG_FUNCTION_ARGS);

/*
* Dumps the contents of a FSM page.
*/
PG_FUNCTION_INFO_V1(fsm_page_contents);

Datum
fsm_page_contents(PG_FUNCTION_ARGS)
{
bytea *raw_page = PG_GETARG_BYTEA_P(0);
int raw_page_size;
StringInfoData sinfo;
FSMPage fsmpage;
int i;

if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to use raw page functions"))));

raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
fsmpage = (FSMPage) PageGetContents(VARDATA(raw_page));

initStringInfo(&sinfo);

for(i=0; i < NodesPerPage; i++)
{
if (fsmpage->fp_nodes[i] != 0)
appendStringInfo(&sinfo, "%d: %d\n", i, fsmpage->fp_nodes[i]);
}
appendStringInfo(&sinfo, "fp_next_slot: %d\n", fsmpage->fp_next_slot);

PG_RETURN_TEXT_P(cstring_to_text(sinfo.data));
}
17 changes: 15 additions & 2 deletions contrib/pageinspect/pageinspect.sql.in
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
/* $PostgreSQL: pgsql/contrib/pageinspect/pageinspect.sql.in,v 1.4 2007/11/13 04:24:28 momjian Exp $ */
/* $PostgreSQL: pgsql/contrib/pageinspect/pageinspect.sql.in,v 1.5 2008/09/30 10:52:09 heikki Exp $ */

-- Adjust this setting to control where the objects get created.
SET search_path = public;

--
-- get_raw_page()
--
CREATE OR REPLACE FUNCTION get_raw_page(text, int4)
CREATE OR REPLACE FUNCTION get_raw_page(text, int4, int4)
RETURNS bytea
AS 'MODULE_PATHNAME', 'get_raw_page'
LANGUAGE C STRICT;

CREATE OR REPLACE FUNCTION get_raw_page(text, int4)
RETURNS bytea
AS $$ SELECT get_raw_page($1, 0, $2); $$
LANGUAGE SQL STRICT;

--
-- page_header()
--
Expand Down Expand Up @@ -92,3 +97,11 @@ CREATE OR REPLACE FUNCTION bt_page_items(IN relname text, IN blkno int4,
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'bt_page_items'
LANGUAGE C STRICT;

--
-- fsm_page_contents()
--
CREATE OR REPLACE FUNCTION fsm_page_contents(IN page bytea)
RETURNS text
AS 'MODULE_PATHNAME', 'fsm_page_contents'
LANGUAGE C STRICT;
12 changes: 9 additions & 3 deletions contrib/pageinspect/rawpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright (c) 2007-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.6 2008/05/12 00:00:43 alvherre Exp $
* $PostgreSQL: pgsql/contrib/pageinspect/rawpage.c,v 1.7 2008/09/30 10:52:09 heikki Exp $
*
*-------------------------------------------------------------------------
*/
Expand Down Expand Up @@ -41,7 +41,8 @@ Datum
get_raw_page(PG_FUNCTION_ARGS)
{
text *relname = PG_GETARG_TEXT_P(0);
uint32 blkno = PG_GETARG_UINT32(1);
uint32 forknum = PG_GETARG_UINT32(1);
uint32 blkno = PG_GETARG_UINT32(2);

Relation rel;
RangeVar *relrv;
Expand All @@ -54,6 +55,11 @@ get_raw_page(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to use raw functions"))));

if (forknum > MAX_FORKNUM)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid fork number")));

relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
rel = relation_openrv(relrv, AccessShareLock);

Expand All @@ -80,7 +86,7 @@ get_raw_page(PG_FUNCTION_ARGS)

/* Take a verbatim copy of the page */

buf = ReadBuffer(rel, blkno);
buf = ReadBufferWithFork(rel, forknum, blkno);
LockBuffer(buf, BUFFER_LOCK_SHARE);

memcpy(raw_page_data, BufferGetPage(buf), BLCKSZ);
Expand Down
48 changes: 15 additions & 33 deletions contrib/pg_freespacemap/pg_freespacemap.sql.in
Original file line number Diff line number Diff line change
@@ -1,44 +1,26 @@
/* $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.sql.in,v 1.8 2007/11/13 04:24:28 momjian Exp $ */
/* $PostgreSQL: pgsql/contrib/pg_freespacemap/pg_freespacemap.sql.in,v 1.9 2008/09/30 10:52:09 heikki Exp $ */

-- Adjust this setting to control where the objects get created.
SET search_path = public;


-- Register the functions.
CREATE OR REPLACE FUNCTION pg_freespacemap_pages()
RETURNS SETOF RECORD
AS 'MODULE_PATHNAME', 'pg_freespacemap_pages'
-- Register the C function.
CREATE OR REPLACE FUNCTION pg_freespace(regclass, int4)
RETURNS int2
AS 'MODULE_PATHNAME', 'pg_freespace'
LANGUAGE C;

CREATE OR REPLACE FUNCTION pg_freespacemap_relations()
-- pg_freespace shows the recorded space avail at each block in a relation
CREATE OR REPLACE FUNCTION
pg_freespace(rel regclass, blkno OUT int4, avail OUT int2)
RETURNS SETOF RECORD
AS 'MODULE_PATHNAME', 'pg_freespacemap_relations'
LANGUAGE C;
AS $$
SELECT blkno::int4, pg_freespace($1, blkno::int4) AS avail
FROM generate_series(0, pg_relation_size($1) / current_setting('block_size')::bigint - 1) AS blkno;
$$
LANGUAGE SQL;


-- Create views for convenient access.
CREATE VIEW pg_freespacemap_pages AS
SELECT P.* FROM pg_freespacemap_pages() AS P
(reltablespace oid,
reldatabase oid,
relfilenode oid,
relblocknumber bigint,
bytes integer);

CREATE VIEW pg_freespacemap_relations AS
SELECT P.* FROM pg_freespacemap_relations() AS P
(reltablespace oid,
reldatabase oid,
relfilenode oid,
avgrequest integer,
interestingpages integer,
storedpages integer,
nextpage integer);


-- Don't want these to be available to public.
REVOKE ALL ON FUNCTION pg_freespacemap_pages() FROM PUBLIC;
REVOKE ALL ON pg_freespacemap_pages FROM PUBLIC;

REVOKE ALL ON FUNCTION pg_freespacemap_relations() FROM PUBLIC;
REVOKE ALL ON pg_freespacemap_relations FROM PUBLIC;
REVOKE ALL ON FUNCTION pg_freespace(regclass, int4) FROM PUBLIC;
REVOKE ALL ON FUNCTION pg_freespace(regclass) FROM PUBLIC;
4 changes: 2 additions & 2 deletions doc/src/sgml/acronyms.sgml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/acronyms.sgml,v 1.5 2008/03/18 16:05:07 mha Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/acronyms.sgml,v 1.6 2008/09/30 10:52:09 heikki Exp $ -->

<appendix id="acronyms">
<title>Acronyms</title>
Expand Down Expand Up @@ -216,7 +216,7 @@
<term><acronym>FSM</acronym></term>
<listitem>
<para>
<link linkend="runtime-config-resource-fsm">Free Space Map</link>
<link linkend="storage-fsm">Free Space Map</link>
</para>
</listitem>
</varlistentry>
Expand Down
76 changes: 1 addition & 75 deletions doc/src/sgml/config.sgml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.190 2008/08/25 19:03:37 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.191 2008/09/30 10:52:09 heikki Exp $ -->

<chapter Id="runtime-config">
<title>Server Configuration</title>
Expand Down Expand Up @@ -896,80 +896,6 @@ SET ENABLE_SEQSCAN TO OFF;
</varlistentry>

</variablelist>
</sect2>
<sect2 id="runtime-config-resource-fsm">
<title>Free Space Map</title>

<indexterm>
<primary>free space map</primary>
</indexterm>

<para>
These parameters control the size of the shared <firstterm>free space
map</> (<acronym>FSM</>), which tracks the locations of unused space in the database.
An undersized free space map can cause the database to consume
increasing amounts of disk space over time, because free space that
is not in the map cannot be re-used; instead <productname>PostgreSQL</>
will request more disk space from the operating system when it needs
to store new data.
The last few lines displayed by a database-wide <command>VACUUM VERBOSE</>
command can help in determining if the current settings are adequate.
A <literal>NOTICE</> message is also printed during such an operation
if the current settings are too low.
</para>

<para>
Increasing these parameters might cause <productname>PostgreSQL</>
to request more <systemitem class="osname">System V</> shared
memory than your operating system's default configuration
allows. See <xref linkend="sysvipc"> for information on how to
adjust those parameters, if necessary.
</para>

<variablelist>
<varlistentry id="guc-max-fsm-pages" xreflabel="max_fsm_pages">
<term><varname>max_fsm_pages</varname> (<type>integer</type>)</term>
<indexterm>
<primary><varname>max_fsm_pages</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Sets the maximum number of disk pages for which free space will
be tracked in the shared free-space map. Six bytes of shared memory
are consumed for each page slot. This setting must be at least
16 * <varname>max_fsm_relations</varname>. The default is chosen
by <application>initdb</> depending on the amount of available memory,
and can range from 20k to 200k pages.
This parameter can only be set at server start.
</para>
</listitem>
</varlistentry>

<varlistentry id="guc-max-fsm-relations" xreflabel="max_fsm_relations">
<term><varname>max_fsm_relations</varname> (<type>integer</type>)</term>
<indexterm>
<primary><varname>max_fsm_relations</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Sets the maximum number of relations (tables and indexes) for which
free space will be tracked in the shared free-space map. Roughly
seventy bytes of shared memory are consumed for each slot.
The default is one thousand relations.
This parameter can only be set at server start.
</para>
</listitem>
</varlistentry>

</variablelist>

<note>
<para>
See the <xref linkend="sql-vacuum" endterm="sql-vacuum-title">
command for information on setting this parameter.
</para>
</note>

</sect2>

<sect2 id="runtime-config-resource-kernel">
Expand Down

0 comments on commit 15c121b

Please sign in to comment.