>
> > -----Original Message-----
> > From: Bruce Momjian [mailto:maillist@candle.pha.pa.us]
> > Sent: Tuesday, September 28, 1999 11:54 PM
> > To: Tom Lane
> > Cc: Hiroshi Inoue; pgsql-hackers
> > Subject: Re: [HACKERS] Recovery on incomplete write
> >
> >
> > > "Hiroshi Inoue" <Inoue@tpf.co.jp> writes:
> > > > I have wondered that md.c handles incomplete block(page)s
> > > > correctly.
> > > > Am I mistaken ?
> > >
> > > I think you are right, and there may be some other trouble
> spots in that
> > > file too.  I remember thinking that the code depended heavily on never
> > > having a partial block at the end of the file.
> > >
> > > But is it worth fixing?  The only way I can see for the file length
> > > to become funny is if we run out of disk space part way
> through writing
> > > a page, which seems unlikely...
> > >
> >
> > That is how he got started, the TODO item about running out of disk
> > space causing corrupted databases.  I think it needs a fix, if we can.
> >
>
> Maybe it isn't so difficult to fix.
> I would provide a patch.
>

Here is a patch.

1) mdnblocks() ignores a partial block at the end of relation files.
2) mdread() ignores a partial block of block number 0.
3) mdextend() adjusts its position to a multiple of BLCKSZ
    before writing.
4) mdextend() truncates extra bytes in case of incomplete write.

If there's no objection,I would commit this change to the current
tree.

Regards.

Hiroshi Inoue
Inoue@tpf.co.jp

*** storage/smgr/md.c.orig	Thu Sep 30 10:50:58 1999
--- storage/smgr/md.c	Tue Oct  5 13:30:55 1999
***************
*** 233,239 ****
  int
  mdextend(Relation reln, char *buffer)
  {
! 	long		pos;
  	int			nblocks;
  	MdfdVec    *v;

--- 233,239 ----
  int
  mdextend(Relation reln, char *buffer)
  {
! 	long		pos, nbytes;
  	int			nblocks;
  	MdfdVec    *v;

***************
*** 243,250 ****
  	if ((pos = FileSeek(v->mdfd_vfd, 0L, SEEK_END)) < 0)
  		return SM_FAIL;

! 	if (FileWrite(v->mdfd_vfd, buffer, BLCKSZ) != BLCKSZ)
  		return SM_FAIL;

  	/* remember that we did a write, so we can sync at xact commit */
  	v->mdfd_flags |= MDFD_DIRTY;
--- 243,264 ----
  	if ((pos = FileSeek(v->mdfd_vfd, 0L, SEEK_END)) < 0)
  		return SM_FAIL;

! 	if (pos % BLCKSZ != 0) /* the last block is incomplete */
! 	{
! 		pos = BLCKSZ * (long)(pos / BLCKSZ);
! 		if (FileSeek(v->mdfd_vfd, pos, SEEK_SET) < 0)
! 			return SM_FAIL;
! 	}
!
! 	if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ)
! 	{
! 		if (nbytes > 0)
! 		{
! 			FileTruncate(v->mdfd_vfd, pos);
! 			FileSeek(v->mdfd_vfd, pos, SEEK_SET);
! 		}
  		return SM_FAIL;
+ 	}

  	/* remember that we did a write, so we can sync at xact commit */
  	v->mdfd_flags |= MDFD_DIRTY;
***************
*** 432,437 ****
--- 446,453 ----
  	{
  		if (nbytes == 0)
  			MemSet(buffer, 0, BLCKSZ);
+ 		else if (blocknum == 0 && nbytes > 0 && mdnblocks(reln) == 0)
+ 			MemSet(buffer, 0, BLCKSZ);
  		else
  			status = SM_FAIL;
  	}
***************
*** 1067,1072 ****
  {
  	long		len;

! 	len = FileSeek(file, 0L, SEEK_END) - 1;
! 	return (BlockNumber) ((len < 0) ? 0 : 1 + len / blcksz);
  }
--- 1083,1088 ----
  {
  	long		len;

! 	len = FileSeek(file, 0L, SEEK_END);
! 	return (BlockNumber) (len / blcksz);
  }



Tue, 5 Oct 1999 18:25:48 +0900
"Hiroshi Inoue" <Inoue@tpf.co.jp>
RE: [HACKERS] Recovery on incomplete write