postgres.git / summary / log / commit / refs

commit    2c3ebfd1ad3523987ec6f268df020a5e1431572e
Author:   Andres Freund <andres@anarazel.de>
Date:     Fri Nov 14 17:21:30 2014 +0000
First released in: 9.5.0, 9.1.15, 9.2.10, 9.3.6, 9.4.0

    Sync unlogged relations to disk after they have been reset.
    
    Unlogged relations are only reset when performing a unclean
    restart. That means they have to be synced to disk during clean
    shutdowns. During normal processing that's achieved by registering a
    buffer's file to be fsynced at the next checkpoint when flushed. But
    ResetUnloggedRelations() doesn't go through the buffer manager, so
    nothing will force reset relations to disk before the next shutdown
    checkpoint.
    
    So just make ResetUnloggedRelations() fsync the newly created main
    forks to disk.
    
    Discussion: 20140912112246.GA4984@alap3.anarazel.de
    
    Backpatch to 9.1 where unlogged tables were introduced.
    
    Abhijit Menon-Sen and Andres Freund


src/backend/storage/file/reinit.c | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/backend/storage/file/reinit.c b/src/backend/storage/file/reinit.c index d62d5848a7a..31c18f1c788 100644 --- a/src/backend/storage/file/reinit.c +++ b/src/backend/storage/file/reinit.c @@ -339,6 +339,53 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op) } FreeDir(dbspace_dir); + + /* + * copy_file() above has already called pg_flush_data() on the + * files it created. Now we need to fsync those files, because + * a checkpoint won't do it for us while we're in recovery. We + * do this in a separate pass to allow the kernel to perform + * all the flushes (especially the metadata ones) at once. + */ + dbspace_dir = AllocateDir(dbspacedirname); + if (dbspace_dir == NULL) + { + /* we just saw this directory, so it really ought to be there */ + elog(LOG, + "could not open dbspace directory \"%s\": %m", + dbspacedirname); + return; + } + + while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL) + { + ForkNumber forkNum; + int oidchars; + char oidbuf[OIDCHARS + 1]; + char mainpath[MAXPGPATH]; + + /* Skip anything that doesn't look like a relation data file. */ + if (!parse_filename_for_nontemp_relation(de->d_name, &oidchars, + &forkNum)) + continue; + + /* Also skip it unless this is the init fork. */ + if (forkNum != INIT_FORKNUM) + continue; + + /* Construct main fork pathname. */ + memcpy(oidbuf, de->d_name, oidchars); + oidbuf[oidchars] = '\0'; + snprintf(mainpath, sizeof(mainpath), "%s/%s%s", + dbspacedirname, oidbuf, de->d_name + oidchars + 1 + + strlen(forkNames[INIT_FORKNUM])); + + fsync_fname(mainpath, false); + } + + FreeDir(dbspace_dir); + + fsync_fname((char *) dbspacedirname, true); } } [parent: 672b43e68b41]