Fix a race condition that caused pg_database_size() and pg_tablespace_size()

to fail if an object was removed between calls to ReadDir() and stat().
Per discussion in pgsql-hackers.

http://archives.postgresql.org/pgsql-hackers/2007-03/msg00671.php

Bug report and patch by Michael Fuhr.
This commit is contained in:
Alvaro Herrera 2007-03-11 06:44:11 +00:00
parent 5ea7b175f6
commit 8a7b38617a

View File

@ -5,7 +5,7 @@
* Copyright (c) 2002-2006, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.9 2006/11/06 03:06:41 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.9.2.1 2007/03/11 06:44:11 alvherre Exp $
*
*/
@ -52,10 +52,14 @@ db_dir_size(const char *path)
snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name);
if (stat(filename, &fst) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat file \"%s\": %m", filename)));
{
if (errno == ENOENT)
continue;
else
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat file \"%s\": %m", filename)));
}
dirsize += fst.st_size;
}
@ -174,9 +178,14 @@ calculate_tablespace_size(Oid tblspcOid)
snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name);
if (stat(pathname, &fst) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat file \"%s\": %m", pathname)));
{
if (errno == ENOENT)
continue;
else
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat file \"%s\": %m", pathname)));
}
if (fst.st_mode & S_IFDIR)
totalsize += db_dir_size(pathname);