unrecoverable-crash-during-unlink.patch

text/x-patch

Filename: unrecoverable-crash-during-unlink.patch
Type: text/x-patch
Part: 0
Message: Re: Lots of FSM-related fragility in transaction commit

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/backend/access/transam/twophase.c 0 0
src/backend/access/transam/xact.c 0 0
src/backend/catalog/storage.c 0 0
src/backend/storage/smgr/md.c 0 0
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index d2fecb1ecb9171fc2c6dd2887d846c8a16779bb0..c5a2541807e148c29c790b0fe12a52c0389f4626 100644
*** a/src/backend/access/transam/twophase.c
--- b/src/backend/access/transam/twophase.c
*************** FinishPreparedTransaction(const char *gi
*** 1366,1373 ****
  
  		for (fork = 0; fork <= MAX_FORKNUM; fork++)
  		{
! 			if (smgrexists(srel, fork))
! 				smgrdounlink(srel, fork, false);
  		}
  		smgrclose(srel);
  	}
--- 1366,1372 ----
  
  		for (fork = 0; fork <= MAX_FORKNUM; fork++)
  		{
! 			smgrdounlink(srel, fork, false);
  		}
  		smgrclose(srel);
  	}
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index c383011b5f6538fa2b90fa5f7778da7ff59fa679..4177a6c5cf95d5e1a1b49b9f11c17098b2158529 100644
*** a/src/backend/access/transam/xact.c
--- b/src/backend/access/transam/xact.c
*************** xact_redo_commit_internal(TransactionId 
*** 4595,4605 ****
  
  		for (fork = 0; fork <= MAX_FORKNUM; fork++)
  		{
! 			if (smgrexists(srel, fork))
! 			{
! 				XLogDropRelation(xnodes[i], fork);
! 				smgrdounlink(srel, fork, true);
! 			}
  		}
  		smgrclose(srel);
  	}
--- 4595,4602 ----
  
  		for (fork = 0; fork <= MAX_FORKNUM; fork++)
  		{
! 			XLogDropRelation(xnodes[i], fork);
! 			smgrdounlink(srel, fork, true);
  		}
  		smgrclose(srel);
  	}
*************** xact_redo_abort(xl_xact_abort *xlrec, Tr
*** 4738,4748 ****
  
  		for (fork = 0; fork <= MAX_FORKNUM; fork++)
  		{
! 			if (smgrexists(srel, fork))
! 			{
! 				XLogDropRelation(xlrec->xnodes[i], fork);
! 				smgrdounlink(srel, fork, true);
! 			}
  		}
  		smgrclose(srel);
  	}
--- 4735,4742 ----
  
  		for (fork = 0; fork <= MAX_FORKNUM; fork++)
  		{
! 			XLogDropRelation(xlrec->xnodes[i], fork);
! 			smgrdounlink(srel, fork, true);
  		}
  		smgrclose(srel);
  	}
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index fff933d403e7ca5e7b551b987e1684cd6a6e98a7..450e292f4013f9be5418f482654cd33c14c6d344 100644
*** a/src/backend/catalog/storage.c
--- b/src/backend/catalog/storage.c
*************** smgrDoPendingDeletes(bool isCommit)
*** 361,368 ****
  				srel = smgropen(pending->relnode, pending->backend);
  				for (i = 0; i <= MAX_FORKNUM; i++)
  				{
! 					if (smgrexists(srel, i))
! 						smgrdounlink(srel, i, false);
  				}
  				smgrclose(srel);
  			}
--- 361,367 ----
  				srel = smgropen(pending->relnode, pending->backend);
  				for (i = 0; i <= MAX_FORKNUM; i++)
  				{
! 					smgrdounlink(srel, i, false);
  				}
  				smgrclose(srel);
  			}
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index a761369d39c2f7aa4c71131d79ef6a0edc61b4ea..7150a00407e3b28dae1cca2e6063251f2c5b681c 100644
*** a/src/backend/storage/smgr/md.c
--- b/src/backend/storage/smgr/md.c
*************** mdcreate(SMgrRelation reln, ForkNumber f
*** 323,329 ****
   * number until it's safe, because relfilenode assignment skips over any
   * existing file.
   *
!  * If isRedo is true, it's okay for the relation to be already gone.
   * Also, we should remove the file immediately instead of queuing a request
   * for later, since during redo there's no possibility of creating a
   * conflicting relation.
--- 323,335 ----
   * number until it's safe, because relfilenode assignment skips over any
   * existing file.
   *
!  * All the above applies only to the relation's main fork; other forks can
!  * just be removed immediately, since they are not needed to prevent the
!  * relfilenode number from being recycled.  Also, we do not carefully
!  * track whether other forks have been created or not, but just attempt to
!  * unlink them unconditionally; so we should never complain about ENOENT.
!  *
!  * If isRedo is true, it's unsurprising for the relation to be already gone.
   * Also, we should remove the file immediately instead of queuing a request
   * for later, since during redo there's no possibility of creating a
   * conflicting relation.
*************** mdunlink(RelFileNodeBackend rnode, ForkN
*** 351,363 ****
  	if (isRedo || forkNum != MAIN_FORKNUM)
  	{
  		ret = unlink(path);
! 		if (ret < 0)
! 		{
! 			if (!isRedo || errno != ENOENT)
! 				ereport(WARNING,
! 						(errcode_for_file_access(),
! 						 errmsg("could not remove file \"%s\": %m", path)));
! 		}
  	}
  	else
  	{
--- 357,366 ----
  	if (isRedo || forkNum != MAIN_FORKNUM)
  	{
  		ret = unlink(path);
! 		if (ret < 0 && errno != ENOENT)
! 			ereport(WARNING,
! 					(errcode_for_file_access(),
! 					 errmsg("could not remove file \"%s\": %m", path)));
  	}
  	else
  	{