Hi,

> +/*
> + * rename_safe -- rename of a file, making it on-disk persistent
> + *
> + * This routine ensures that a rename file persists in case of a crash by 
> using
> + * fsync on the old and new files before and after performing the rename so 
> as
> + * this categorizes as an all-or-nothing operation.
> + */
> +int
> +rename_safe(const char *oldfile, const char *newfile)
> +{
> +     struct stat     filestats;
> +
> +     /*
> +      * First fsync the old entry and new entry, it this one exists, to 
> ensure
> +      * that they are properly persistent on disk. Calling this routine with
> +      * an existing new target file is fine, rename() will first remove it
> +      * before performing its operation.
> +      */
> +     fsync_fname(oldfile, false);
> +     if (stat(newfile, &filestats) == 0)
> +             fsync_fname(newfile, false);

I don't think we want any stat()s here. I'd much, much rather check open
for ENOENT.


> +/*
> + * link_safe -- make a file hard link, making it on-disk persistent
> + *
> + * This routine ensures that a hard link created on a file persists on system
> + * in case of a crash by using fsync where on the link generated as well as 
> on
> + * its parent directory.
> + */
> +int
> +link_safe(const char *oldfile, const char *newfile)
> +{

If we go for a new abstraction here, I'd rather make it
'replace_file_safe' or something, and move the link/rename code #ifdef
into it.


> +     if (link(oldfile, newfile) < 0)
> +             return -1;
> +
> +     /*
> +      * Make the link persistent in case of an OS crash, the new entry
> +      * generated as well as its parent directory need to be flushed.
> +      */
> +     fsync_fname(newfile, false);
> +
> +     /*
> +      * Same for parent directory. This routine is never called to rename
> +      * files across directories, but if this proves to become the case,
> +      * flushing the parent directory if the old file would be necessary.
> +      */
> +     fsync_parent_path(newfile);
> +     return 0;

I think it's a seriously bad idea to encode that knowledge in such a
general sounding routine.  We could however argue that this is about
safely replacing the *target* file; not about safely removing the old
file.


Currently I'm inclined to apply this to master soon. But I think we
might want to wait a while with backpatching.  The recent fsync upgrade
disaster kinda makes me a bit careful...


Greetings,

Andres Freund


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to