*
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.204.2.1 2008/04/16 23:59:51 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.204.2.2 2008/04/18 06:48:50 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
    pgstat_drop_database(db_id);
 
    /*
-    * Tell bgwriter to forget any pending fsync requests for files in the
-    * database; else it'll fail at next checkpoint.
+    * Tell bgwriter to forget any pending fsync and unlink requests for files
+    * in the database; else the fsyncs will fail at next checkpoint, or worse,
+    * it will delete files that belong to a newly created database with the
+    * same OID.
     */
    ForgetDatabaseFsyncRequests(db_id);
 
    /*
-    * On Windows, force a checkpoint so that the bgwriter doesn't hold any
-    * open files, which would cause rmdir() to fail.
+    * Force a checkpoint to make sure the bgwriter has received the message
+    * sent by ForgetDatabaseFsyncRequests. On Windows, this also ensures that
+    * the bgwriter doesn't hold any open files, which would cause rmdir() to
+    * fail.
     */
-#ifdef WIN32
    RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
-#endif
 
    /*
     * Remove all tablespace subdirs belonging to the database.
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.135 2008/01/01 19:45:52 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.135.2.1 2008/04/18 06:48:50 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
        if (unlink(path) < 0)
        {
            /*
-            * ENOENT shouldn't happen either, but it doesn't really matter
-            * because we would've deleted it now anyway.
+            * There's a race condition, when the database is dropped at the
+            * same time that we process the pending unlink requests. If the
+            * DROP DATABASE deletes the file before we do, we will get ENOENT
+            * here. rmtree() also has to ignore ENOENT errors, to deal with
+            * the possibility that we delete the file first.
             */
            if (errno != ENOENT)
                ereport(WARNING,
        /* Remove any pending requests for the entire database */
        HASH_SEQ_STATUS hstat;
        PendingOperationEntry *entry;
+       ListCell   *cell, 
+                  *prev,
+                  *next;
 
+       /* Remove fsync requests */
        hash_seq_init(&hstat, pendingOpsTable);
        while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
        {
                entry->canceled = true;
            }
        }
+   
+       /* Remove unlink requests */
+       prev = NULL;
+       for (cell = list_head(pendingUnlinks); cell; cell = next)
+       {
+           PendingUnlinkEntry *entry = (PendingUnlinkEntry *) lfirst(cell);
+
+           next = lnext(cell);
+           if (entry->rnode.dbNode == rnode.dbNode) 
+           {
+               pendingUnlinks = list_delete_cell(pendingUnlinks, cell, prev);
+               pfree(entry);
+           }
+           else
+               prev = cell;
+       }
    }
    else if (segno == UNLINK_RELATION_REQUEST)
    {
 }
 
 /*
- * ForgetRelationFsyncRequests -- ensure any fsyncs for a rel are forgotten
+ * ForgetRelationFsyncRequests -- forget any fsyncs for a rel
  */
 void
 ForgetRelationFsyncRequests(RelFileNode rnode)
 }
 
 /*
- * ForgetDatabaseFsyncRequests -- ensure any fsyncs for a DB are forgotten
+ * ForgetDatabaseFsyncRequests -- forget any fsyncs and unlinks for a DB
  */
 void
 ForgetDatabaseFsyncRequests(Oid dbid)
 
  * Win32 (NT, Win2k, XP).  replace() doesn't work on Win95/98/Me.
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/port/dirmod.c,v 1.51.2.2 2008/04/11 23:59:49 tgl Exp $
+ *   $PostgreSQL: pgsql/src/port/dirmod.c,v 1.51.2.3 2008/04/18 06:48:50 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
    {
        snprintf(filepath, MAXPGPATH, "%s/%s", path, *filename);
 
+       /*
+        * It's ok if the file is not there anymore; we were just about to
+        * delete it anyway.
+        *
+        * This is not an academic possibility. One scenario where this
+        * happens is when bgwriter has a pending unlink request for a file
+        * in a database that's being dropped. In dropdb(), we call
+        * ForgetDatabaseFsyncRequests() to flush out any such pending unlink
+        * requests, but because that's asynchronous, it's not guaranteed
+        * that the bgwriter receives the message in time.
+        */
        if (lstat(filepath, &statbuf) != 0)
-           goto report_and_fail;
+       {
+           if (errno != ENOENT)
+               goto report_and_fail;
+           else
+               continue;
+       }
 
        if (S_ISDIR(statbuf.st_mode))
        {
        else
        {
            if (unlink(filepath) != 0)
-               goto report_and_fail;
+           {
+               if (errno != ENOENT)
+                   goto report_and_fail;
+           }
        }
    }