]> granicus.if.org Git - postgresql/commitdiff
Add pg_ls_tmpdir function
authorMichael Paquier <michael@paquier.xyz>
Fri, 5 Oct 2018 00:21:48 +0000 (09:21 +0900)
committerMichael Paquier <michael@paquier.xyz>
Fri, 5 Oct 2018 00:21:48 +0000 (09:21 +0900)
This lists the contents of a temporary directory associated to a given
tablespace, useful to get information about on-disk consumption caused
by temporary files used by a session query.  By default, pg_default is
scanned, and a tablespace can be specified as argument.

This function is intended to be used by monitoring tools, and, unlike
pg_ls_dir(), access to them can be granted to non-superusers so that
those monitoring tools can observe the principle of least privilege.
Access is also given by default to members of pg_monitor.

Author: Nathan Bossart
Reviewed-by: Laurenz Albe
Discussion: https://postgr.es/m/92F458A2-6459-44B8-A7F2-2ADD3225046A@amazon.com

doc/src/sgml/func.sgml
src/backend/catalog/system_views.sql
src/backend/utils/adt/genfile.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.dat

index 9a7f6836581dbdf0e8f05bb42dc715a3056619f7..f984d069e1f539d1f0869a7d5d0aebff61f56a84 100644 (file)
@@ -20355,6 +20355,20 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
         role and may be granted to other non-superuser roles.
        </entry>
       </row>
+      <row>
+       <entry>
+        <literal><function>pg_ls_tmpdir(<optional><parameter>tablespace</parameter> <type>oid</type></optional>)</function></literal>
+       </entry>
+       <entry><type>setof record</type></entry>
+       <entry>
+        List the name, size, and last modification time of files in the
+        temporary directory for <parameter>tablespace</parameter>.  If
+        <parameter>tablespace</parameter> is not provided, the
+        <literal>pg_default</literal> tablespace is used.  Access is granted
+        to members of the <literal>pg_monitor</literal> role and may be
+        granted to other non-superuser roles.
+       </entry>
+      </row>
       <row>
        <entry>
         <literal><function>pg_read_file(<parameter>filename</parameter> <type>text</type> [, <parameter>offset</parameter> <type>bigint</type>, <parameter>length</parameter> <type>bigint</type> [, <parameter>missing_ok</parameter> <type>boolean</type>] ])</function></literal>
@@ -20428,6 +20442,19 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
     <command>GRANT</command>.
    </para>
 
+   <indexterm>
+    <primary>pg_ls_tmpdir</primary>
+   </indexterm>
+   <para>
+    <function>pg_ls_tmpdir</function> returns the name, size, and last modified
+    time (mtime) of each file in the temporary file directory for the specified
+    <parameter>tablespace</parameter>.  If <parameter>tablespace</parameter> is
+    not provided, the <literal>pg_default</literal> tablespace is used.  By
+    default only superusers and members of the <literal>pg_monitor</literal>
+    role can use this function.  Access may be granted to others using
+    <command>GRANT</command>.
+   </para>
+
    <indexterm>
     <primary>pg_read_file</primary>
    </indexterm>
index 7251552419962b901df0cb3bc3efec0bd2b638f9..020f28cbf66879fdbad24dde3c32c98d25745f6b 100644 (file)
@@ -1150,6 +1150,8 @@ REVOKE EXECUTE ON FUNCTION lo_export(oid, text) FROM public;
 
 REVOKE EXECUTE ON FUNCTION pg_ls_logdir() FROM public;
 REVOKE EXECUTE ON FUNCTION pg_ls_waldir() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir() FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir(oid) FROM public;
 
 REVOKE EXECUTE ON FUNCTION pg_read_file(text) FROM public;
 REVOKE EXECUTE ON FUNCTION pg_read_file(text,bigint,bigint) FROM public;
@@ -1170,6 +1172,8 @@ REVOKE EXECUTE ON FUNCTION pg_ls_dir(text,boolean,boolean) FROM public;
 --
 GRANT EXECUTE ON FUNCTION pg_ls_logdir() TO pg_monitor;
 GRANT EXECUTE ON FUNCTION pg_ls_waldir() TO pg_monitor;
+GRANT EXECUTE ON FUNCTION pg_ls_tmpdir() TO pg_monitor;
+GRANT EXECUTE ON FUNCTION pg_ls_tmpdir(oid) TO pg_monitor;
 
 GRANT pg_read_all_settings TO pg_monitor;
 GRANT pg_read_all_stats TO pg_monitor;
index a97cbea24831ecc41ab1c91e4907eca88399c3ac..85bea8d5022096011c9ec44309950854f5abcdb1 100644 (file)
@@ -23,6 +23,7 @@
 #include "access/htup_details.h"
 #include "access/xlog_internal.h"
 #include "catalog/pg_authid.h"
+#include "catalog/pg_tablespace_d.h"
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "mb/pg_wchar.h"
@@ -31,6 +32,7 @@
 #include "storage/fd.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
+#include "utils/syscache.h"
 #include "utils/timestamp.h"
 
 typedef struct
@@ -520,7 +522,7 @@ pg_ls_dir_1arg(PG_FUNCTION_ARGS)
 
 /* Generic function to return a directory listing of files */
 static Datum
-pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
+pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
 {
        FuncCallContext *funcctx;
        struct dirent *de;
@@ -549,10 +551,18 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
                fctx->dirdesc = AllocateDir(fctx->location);
 
                if (!fctx->dirdesc)
-                       ereport(ERROR,
-                                       (errcode_for_file_access(),
-                                        errmsg("could not open directory \"%s\": %m",
-                                                       fctx->location)));
+               {
+                       if (missing_ok && errno == ENOENT)
+                       {
+                               MemoryContextSwitchTo(oldcontext);
+                               SRF_RETURN_DONE(funcctx);
+                       }
+                       else
+                               ereport(ERROR,
+                                               (errcode_for_file_access(),
+                                                errmsg("could not open directory \"%s\": %m",
+                                                               fctx->location)));
+               }
 
                funcctx->user_fctx = fctx;
                MemoryContextSwitchTo(oldcontext);
@@ -601,12 +611,50 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
 Datum
 pg_ls_logdir(PG_FUNCTION_ARGS)
 {
-       return pg_ls_dir_files(fcinfo, Log_directory);
+       return pg_ls_dir_files(fcinfo, Log_directory, false);
 }
 
 /* Function to return the list of files in the WAL directory */
 Datum
 pg_ls_waldir(PG_FUNCTION_ARGS)
 {
-       return pg_ls_dir_files(fcinfo, XLOGDIR);
+       return pg_ls_dir_files(fcinfo, XLOGDIR, false);
+}
+
+/*
+ * Generic function to return the list of files in pgsql_tmp
+ */
+static Datum
+pg_ls_tmpdir(FunctionCallInfo fcinfo, Oid tblspc)
+{
+       char            path[MAXPGPATH];
+
+       if (!SearchSysCacheExists1(TABLESPACEOID, ObjectIdGetDatum(tblspc)))
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("tablespace with OID %u does not exist",
+                                               tblspc)));
+
+       TempTablespacePath(path, tblspc);
+       return pg_ls_dir_files(fcinfo, path, true);
+}
+
+/*
+ * Function to return the list of temporary files in the pg_default tablespace's
+ * pgsql_tmp directory
+ */
+Datum
+pg_ls_tmpdir_noargs(PG_FUNCTION_ARGS)
+{
+       return pg_ls_tmpdir(fcinfo, DEFAULTTABLESPACE_OID);
+}
+
+/*
+ * Function to return the list of temporary files in the specified tablespace's
+ * pgsql_tmp directory
+ */
+Datum
+pg_ls_tmpdir_1arg(PG_FUNCTION_ARGS)
+{
+       return pg_ls_tmpdir(fcinfo, PG_GETARG_OID(0));
 }
index 02a9866f321c5c7da4bb6ba5d461c2c177b7f628..89e2b609165730fbab57e6293fd2379ea4c24e23 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201809301
+#define CATALOG_VERSION_NO     201810051
 
 #endif
index 8e4145f42b44cbebf175d737691167be93496830..8579822bcd250e5fd2ea1e533e9be61edf3f19f8 100644 (file)
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
   proargnames => '{name,size,modification}', prosrc => 'pg_ls_waldir' },
+{ oid => '5029', descr => 'list files in the pgsql_tmp directory',
+  proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
+  provolatile => 'v', prorettype => 'record', proargtypes => '',
+  proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
+  proargnames => '{name,size,modification}', prosrc => 'pg_ls_tmpdir_noargs' },
+{ oid => '5030', descr => 'list files in the pgsql_tmp directory',
+  proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
+  provolatile => 'v', prorettype => 'record', proargtypes => 'oid',
+  proallargtypes => '{oid,text,int8,timestamptz}', proargmodes => '{i,o,o,o}',
+  proargnames => '{tablespace,name,size,modification}', prosrc => 'pg_ls_tmpdir_1arg' },
 
 # hash partitioning constraint function
 { oid => '5028', descr => 'hash partition CHECK constraint',