Re: Patch to improve reliability of postgresql on linux nfs

Florian G. Pflug <fgp@phlo.org>

From: Florian Pflug <fgp@phlo.org>
To: Florian Pflug <fgp@phlo.org>
Cc: George Barnett <gbarnett@atlassian.com>, Bernd Helmle <mailings@oopsware.de>, Tom Lane <tgl@sss.pgh.pa.us>, PostgreSQL-development Hackers <pgsql-hackers@postgresql.org>
Date: 2011-09-13T11:30:34Z
Lists: pgsql-hackers
On Sep13, 2011, at 13:07 , Florian Pflug wrote:
> Here's my suggested implementation for pg_write_nointr. pg_read_nointr should be similar
> (but obviously without the ENOSPC handling)
> 
> <wrong pg_write_nointr implementation snipped>

Sorry for the self-reply. I realized only after hitting send that I
got the ENOSPC handling wrong again - we probably ought to check for
ENOSPC as well as ret == 0. Also, it seems preferable to return the
number of bytes actually written instead of -1 if we hit an error during
retry.

With this version, any return value other than <amount> signals an
error, the number of actually written bytes is reported even in the
case of an error (to the best of pg_write_nointr's knowledge), and
errno always indicates the kind of error.

int pg_write_nointr(int fd, const void *bytes, Size amount)
{
 int written = 0;

 while (amount > 0)
 {
   int ret;

   ret = write(fd, bytes, amount);

   if ((ret < 0) && (errno == EINTR))
   {
     /* interrupted by signal before first byte was written. Retry */

     /* XXX: Is it safe to call CHECK_FOR_INTERRUPTS here? */
     CHECK_FOR_INTERRUPTS();

     continue;
   }
   else if (ret < 1)
   {
     /* error occurred. Abort */

     if (ret == 0)
       /* out of disk space */
       errno = ENOSPC;

     if (written == 0)
       return -1;
     else
       return written;
   }

   /* made progress */
   written += ret;
   amount -= ret;
   bytes = (const char *) bytes + ret;
   
   /* XXX: Is it safe to call CHECK_FOR_INTERRUPTS here? */
   CHECK_FOR_INTERRUPTS();
 }
}

best regards,
Florian Pflug