Fix a race condition that caused pg_database_size() and pg_tablespace_size()
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Sun, 11 Mar 2007 05:22:00 +0000 (05:22 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Sun, 11 Mar 2007 05:22:00 +0000 (05:22 +0000)
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.

src/backend/utils/adt/dbsize.c

index 6df746c38eb0000f28ed5321568bdc4cb9917e03..e733260370ef4cc2e02de95bcb59fcb3fba2cdb5 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (c) 2002-2007, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.11 2007/02/27 23:48:07 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.12 2007/03/11 05:22:00 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);