diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 5023b4042617f0205ce2ec924248e9f6dc6147b9..13aca31a3e4f481e09b1bb5de20618e278cfa3e0 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.35 2000/05/31 00:28:26 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.36 2000/10/18 05:50:15 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -67,8 +67,9 @@ long	   *PrivateRefCount;	/* also used in freelist.c */
 bits8	   *BufferLocks;		/* flag bits showing locks I have set */
 BufferTag  *BufferTagLastDirtied;		/* tag buffer had when last
 										 * dirtied by me */
-BufferBlindId *BufferBlindLastDirtied;	/* and its BlindId too */
-bool	   *BufferDirtiedByMe;	/* T if buf has been dirtied in cur xact */
+BufferBlindId  *BufferBlindLastDirtied;
+LockRelId	   *BufferRelidLastDirtied;
+bool		   *BufferDirtiedByMe;	/* T if buf has been dirtied in cur xact */
 
 
 /*
@@ -251,6 +252,7 @@ InitBufferPool(IPCKey key)
 	BufferLocks = (bits8 *) calloc(NBuffers, sizeof(bits8));
 	BufferTagLastDirtied = (BufferTag *) calloc(NBuffers, sizeof(BufferTag));
 	BufferBlindLastDirtied = (BufferBlindId *) calloc(NBuffers, sizeof(BufferBlindId));
+	BufferRelidLastDirtied = (LockRelId *) calloc(NBuffers, sizeof(LockRelId));
 	BufferDirtiedByMe = (bool *) calloc(NBuffers, sizeof(bool));
 }
 
diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c
index 8139337e3522f48574b8d83468dd26cae3d1f40f..d48d321e8f8a2c9c5099d1468faf6cf18a510b98 100644
--- a/src/backend/storage/buffer/buf_table.c
+++ b/src/backend/storage/buffer/buf_table.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.17 2000/05/19 03:22:28 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.18 2000/10/18 05:50:15 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -125,8 +125,8 @@ BufTableDelete(BufferDesc *buf)
 	 * sequential searches through the buffer table won't think the
 	 * buffer is still valid for its old page.
 	 */
-	buf->tag.relId.relId = InvalidOid;
-	buf->tag.relId.dbId = InvalidOid;
+	buf->tag.rnode.relNode = InvalidOid;
+	buf->tag.rnode.tblNode = InvalidOid;
 
 	return TRUE;
 }
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index d5badefd084ebfb1be8a7ca458cc3dbdee4a4f8c..41ee78e547c018e263cde96dcf17dd3b4304e23f 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.86 2000/10/16 14:52:09 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.87 2000/10/18 05:50:15 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -116,13 +116,10 @@ RelationGetBufferWithBuffer(Relation relation,
 	{
 		if (!BufferIsLocal(buffer))
 		{
-			LockRelId  *lrelId = &relation->rd_lockInfo.lockRelId;
-
 			bufHdr = &BufferDescriptors[buffer - 1];
 			SpinAcquire(BufMgrLock);
 			if (bufHdr->tag.blockNum == blockNumber &&
-				bufHdr->tag.relId.relId == lrelId->relId &&
-				bufHdr->tag.relId.dbId == lrelId->dbId)
+				RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node))
 			{
 				SpinRelease(BufMgrLock);
 				return buffer;
@@ -132,8 +129,8 @@ RelationGetBufferWithBuffer(Relation relation,
 		else
 		{
 			bufHdr = &LocalBufferDescriptors[-buffer - 1];
-			if (bufHdr->tag.relId.relId == RelationGetRelid(relation) &&
-				bufHdr->tag.blockNum == blockNumber)
+			if (bufHdr->tag.blockNum == blockNumber &&
+				RelFileNodeEquals(bufHdr->tag.rnode, relation->rd_node))
 				return buffer;
 		}
 	}
@@ -614,9 +611,7 @@ BufferAlloc(Relation reln,
 	/* record the database name and relation name for this buffer */
 	strcpy(buf->blind.dbname, DatabaseName);
 	strcpy(buf->blind.relname, RelationGetPhysicalRelationName(reln));
-#ifndef OLD_FILE_NAMING
-	buf->blind.rnode = reln->rd_node;
-#endif
+	buf->relId = reln->rd_lockInfo.lockRelId;
 
 	INIT_BUFFERTAG(&(buf->tag), reln, blockNum);
 	if (!BufTableInsert(buf))
@@ -703,59 +698,6 @@ refcount = %ld, file: %s, line: %d\n",
 
 #endif
 
-/*
- * DirtyBufferCopy() -- For a given dbid/relid/blockno, if the buffer is
- *						in the cache and is dirty, mark it clean and copy
- *						it to the requested location.  This is a logical
- *						write, and has been installed to support the cache
- *						management code for write-once storage managers.
- *
- *	DirtyBufferCopy() -- Copy a given dirty buffer to the requested
- *						 destination.
- *
- *		We treat this as a write.  If the requested buffer is in the pool
- *		and is dirty, we copy it to the location requested and mark it
- *		clean.	This routine supports the Sony jukebox storage manager,
- *		which agrees to take responsibility for the data once we mark
- *		it clean.
- *
- *	NOTE: used by sony jukebox code in postgres 4.2   - ay 2/95
- */
-#ifdef NOT_USED
-void
-DirtyBufferCopy(Oid dbid, Oid relid, BlockNumber blkno, char *dest)
-{
-	BufferDesc *buf;
-	BufferTag	btag;
-
-	btag.relId.relId = relid;
-	btag.relId.dbId = dbid;
-	btag.blockNum = blkno;
-
-	SpinAcquire(BufMgrLock);
-	buf = BufTableLookup(&btag);
-
-	if (buf == (BufferDesc *) NULL
-		|| !(buf->flags & BM_DIRTY)
-		|| !(buf->flags & BM_VALID))
-	{
-		SpinRelease(BufMgrLock);
-		return;
-	}
-
-	/*
-	 * hate to do this holding the lock, but release and reacquire is
-	 * slower
-	 */
-	memmove(dest, (char *) MAKE_PTR(buf->data), BLCKSZ);
-
-	buf->flags &= ~BM_DIRTY;
-
-	SpinRelease(BufMgrLock);
-}
-
-#endif
-
 /*
  * FlushBuffer -- like WriteBuffer, but force the page to disk.
  *
@@ -783,10 +725,10 @@ FlushBuffer(Buffer buffer, bool release)
 
 	bufHdr = &BufferDescriptors[buffer - 1];
 
-	bufdb = bufHdr->tag.relId.dbId;
+	bufdb = bufHdr->relId.dbId;
 
 	Assert(bufdb == MyDatabaseId || bufdb == (Oid) NULL);
-	bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
+	bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
 
 	Assert(bufrel != (Relation) NULL);
 
@@ -954,8 +896,7 @@ SetBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
 	 */
 	if (BufferDirtiedByMe[buffer - 1])
 	{
-		if (bufHdr->tag.relId.dbId == tagLastDirtied->relId.dbId &&
-			bufHdr->tag.relId.relId == tagLastDirtied->relId.relId &&
+		if (RelFileNodeEquals(bufHdr->tag.rnode, tagLastDirtied->rnode) &&
 			bufHdr->tag.blockNum == tagLastDirtied->blockNum)
 			return;				/* Same tag already dirtied, so no work */
 
@@ -963,25 +904,17 @@ SetBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
 		SpinRelease(BufMgrLock);
 #endif	 /* OPTIMIZE_SINGLE */
 
-		reln = RelationIdCacheGetRelation(tagLastDirtied->relId.relId);
+		reln = RelationIdCacheGetRelation(BufferRelidLastDirtied[buffer - 1].relId);
 
 		if (reln == (Relation) NULL)
 		{
-#ifdef OLD_FILE_NAMING
-			status = smgrblindmarkdirty(DEFAULT_SMGR,
-							BufferBlindLastDirtied[buffer - 1].dbname,
-							BufferBlindLastDirtied[buffer - 1].relname,
-							tagLastDirtied->relId.dbId,
-							tagLastDirtied->relId.relId,
-							tagLastDirtied->blockNum);
-#else
 			status = smgrblindmarkdirty(DEFAULT_SMGR,
-							BufferBlindLastDirtied[buffer - 1].rnode,
+							tagLastDirtied->rnode,
 							tagLastDirtied->blockNum);
-#endif
 		}
 		else
 		{
+			Assert(RelFileNodeEquals(tagLastDirtied->rnode, reln->rd_node));
 			status = smgrmarkdirty(DEFAULT_SMGR, reln,
 								   tagLastDirtied->blockNum);
 
@@ -1005,6 +938,7 @@ SetBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
 	}
 
 	*tagLastDirtied = bufHdr->tag;
+	BufferRelidLastDirtied[buffer - 1] = bufHdr->relId;
 	BufferBlindLastDirtied[buffer - 1] = bufHdr->blind;
 	BufferDirtiedByMe[buffer - 1] = true;
 }
@@ -1028,10 +962,9 @@ ClearBufferDirtiedByMe(Buffer buffer, BufferDesc *bufHdr)
 	 * the data we just wrote.	This is unlikely, but possible if some
 	 * other backend replaced the buffer contents since we set our flag.
 	 */
-		if (bufHdr->tag.relId.dbId == tagLastDirtied->relId.dbId &&
-				bufHdr->tag.relId.relId == tagLastDirtied->relId.relId &&
-				bufHdr->tag.blockNum == tagLastDirtied->blockNum)
-			BufferDirtiedByMe[buffer - 1] = false;
+	if (RelFileNodeEquals(bufHdr->tag.rnode, tagLastDirtied->rnode) &&
+			bufHdr->tag.blockNum == tagLastDirtied->blockNum)
+		BufferDirtiedByMe[buffer - 1] = false;
 }
 
 /*
@@ -1074,15 +1007,10 @@ BufferSync()
 		didwrite = false;
 		if ((bufHdr->flags & BM_VALID) && (bufHdr->flags & BM_DIRTY))
 		{
-			Oid			bufdb;
-			Oid			bufrel;
-
-			bufdb = bufHdr->tag.relId.dbId;
-			bufrel = bufHdr->tag.relId.relId;
-			if (bufdb == BufferTagLastDirtied[i].relId.dbId &&
-				bufrel == BufferTagLastDirtied[i].relId.relId &&
+			if (RelFileNodeEquals(bufHdr->tag.rnode, BufferTagLastDirtied[i].rnode) &&
 				bufHdr->tag.blockNum == BufferTagLastDirtied[i].blockNum)
 			{
+				Oid		bufrel = bufHdr->relId.relId;
 
 				/*
 				 * Try to find relation for buf.  This could fail, if the
@@ -1147,24 +1075,16 @@ BufferSync()
 					 */
 					if (reln == (Relation) NULL)
 					{
-#ifdef OLD_FILE_NAMING
-						status = smgrblindwrt(DEFAULT_SMGR,
-											bufHdr->blind.dbname,
-											bufHdr->blind.relname,
-											bufdb, bufrel,
-											bufHdr->tag.blockNum,
-											(char *) MAKE_PTR(bufHdr->data),
-											true);	/* must fsync */
-#else
 						status = smgrblindwrt(DEFAULT_SMGR,
-											bufHdr->blind.rnode,
+											bufHdr->tag.rnode,
 											bufHdr->tag.blockNum,
 											(char *) MAKE_PTR(bufHdr->data),
 											true);	/* must fsync */
-#endif
 					}
 					else
 					{
+						Assert(RelFileNodeEquals(reln->rd_node,
+									BufferTagLastDirtied[i].rnode));
 						status = smgrwrite(DEFAULT_SMGR, reln,
 										   bufHdr->tag.blockNum,
 										(char *) MAKE_PTR(bufHdr->data));
@@ -1218,24 +1138,17 @@ BufferSync()
 			SpinRelease(BufMgrLock);
 #endif	 /* OPTIMIZE_SINGLE */
 
-			reln = RelationIdCacheGetRelation(BufferTagLastDirtied[i].relId.relId);
+			reln = RelationIdCacheGetRelation(BufferRelidLastDirtied[i].relId);
 			if (reln == (Relation) NULL)
 			{
-#ifdef OLD_FILE_NAMING
-				status = smgrblindmarkdirty(DEFAULT_SMGR,
-									BufferBlindLastDirtied[i].dbname,
-									BufferBlindLastDirtied[i].relname,
-									BufferTagLastDirtied[i].relId.dbId,
-									BufferTagLastDirtied[i].relId.relId,
-									BufferTagLastDirtied[i].blockNum);
-#else
 				status = smgrblindmarkdirty(DEFAULT_SMGR,
-									BufferBlindLastDirtied[i].rnode,
+									BufferTagLastDirtied[i].rnode,
 									BufferTagLastDirtied[i].blockNum);
-#endif
 			}
 			else
 			{
+				Assert(RelFileNodeEquals(reln->rd_node,
+							BufferTagLastDirtied[i].rnode));
 				status = smgrmarkdirty(DEFAULT_SMGR, reln,
 									   BufferTagLastDirtied[i].blockNum);
 
@@ -1492,46 +1405,6 @@ BufferGetBlockNumber(Buffer buffer)
 		return BufferDescriptors[buffer - 1].tag.blockNum;
 }
 
-#ifdef NOT_USED
-/*
- * BufferGetRelation
- *		Returns the relation desciptor associated with a buffer.
- *
- * Note:
- *		Assumes buffer is valid.
- */
-Relation
-BufferGetRelation(Buffer buffer)
-{
-	Relation	relation;
-	Oid			relid;
-
-	Assert(BufferIsValid(buffer));
-	Assert(!BufferIsLocal(buffer));		/* not supported for local buffers */
-
-	/* XXX should be a critical section */
-	relid = BufferDescriptors[buffer - 1].tag.relId.relId;
-	relation = RelationIdGetRelation(relid);
-	Assert(relation);
-
-	/* drop relcache refcnt incremented by RelationIdGetRelation */
-	RelationDecrementReferenceCount(relation);
-
-	if (RelationHasReferenceCountZero(relation))
-	{
-
-		/*
-		 * XXX why??
-		 */
-
-		RelationIncrementReferenceCount(relation);
-	}
-
-	return relation;
-}
-
-#endif
-
 /*
  * BufferReplace
  *
@@ -1554,8 +1427,8 @@ BufferReplace(BufferDesc *bufHdr)
 	 * first try to find the reldesc in the cache, if no luck, don't
 	 * bother to build the reldesc from scratch, just do a blind write.
 	 */
-	bufdb = bufHdr->tag.relId.dbId;
-	bufrel = bufHdr->tag.relId.relId;
+	bufdb = bufHdr->relId.dbId;
+	bufrel = bufHdr->relId.relId;
 
 	if (bufdb == MyDatabaseId || bufdb == (Oid) NULL)
 		reln = RelationIdCacheGetRelation(bufrel);
@@ -1576,23 +1449,16 @@ BufferReplace(BufferDesc *bufHdr)
 
 	if (reln != (Relation) NULL)
 	{
+		Assert(RelFileNodeEquals(bufHdr->tag.rnode, reln->rd_node));
 		status = smgrwrite(DEFAULT_SMGR, reln, bufHdr->tag.blockNum,
 						   (char *) MAKE_PTR(bufHdr->data));
 	}
 	else
 	{
-#ifdef OLD_FILE_NAMING
-		status = smgrblindwrt(DEFAULT_SMGR, bufHdr->blind.dbname,
-							  bufHdr->blind.relname, bufdb, bufrel,
+		status = smgrblindwrt(DEFAULT_SMGR, bufHdr->tag.rnode,
 							  bufHdr->tag.blockNum,
 							  (char *) MAKE_PTR(bufHdr->data),
 							  false);	/* no fsync */
-#else
-		status = smgrblindwrt(DEFAULT_SMGR, bufHdr->blind.rnode,
-							  bufHdr->tag.blockNum,
-							  (char *) MAKE_PTR(bufHdr->data),
-							  false);	/* no fsync */
-#endif
 	}
 
 	LockBuffer(BufferDescriptorGetBuffer(bufHdr), BUFFER_LOCK_UNLOCK);
@@ -1654,18 +1520,22 @@ ReleaseRelationBuffers(Relation rel)
 {
 	Oid			relid = RelationGetRelid(rel);
 	int			i;
-	BufferDesc *buf;
+	BufferDesc *bufHdr;
 
 	if (rel->rd_myxactonly)
 	{
 		for (i = 0; i < NLocBuffer; i++)
 		{
-			buf = &LocalBufferDescriptors[i];
-			if (buf->tag.relId.relId == relid)
+			bufHdr = &LocalBufferDescriptors[i];
+			if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
 			{
-				buf->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
+				bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
 				LocalRefCount[i] = 0;
-				buf->tag.relId.relId = InvalidOid;
+				bufHdr->tag.rnode.relNode = InvalidOid;
+			}
+			else
+			{
+				Assert(bufHdr->relId.relId != relid);
 			}
 		}
 		return;
@@ -1674,11 +1544,9 @@ ReleaseRelationBuffers(Relation rel)
 	SpinAcquire(BufMgrLock);
 	for (i = 1; i <= NBuffers; i++)
 	{
-		buf = &BufferDescriptors[i - 1];
+		bufHdr = &BufferDescriptors[i - 1];
 recheck:
-		if (buf->tag.relId.relId == relid &&
-			(buf->tag.relId.dbId == MyDatabaseId ||
-			 buf->tag.relId.dbId == (Oid) NULL))
+		if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
 		{
 
 			/*
@@ -1686,9 +1554,9 @@ recheck:
 			 * don't want to delete the relation out from under someone
 			 * who's just trying to flush the buffer!
 			 */
-			if (buf->flags & BM_IO_IN_PROGRESS)
+			if (bufHdr->flags & BM_IO_IN_PROGRESS)
 			{
-				WaitIO(buf, BufMgrLock);
+				WaitIO(bufHdr, BufMgrLock);
 
 				/*
 				 * By now, the buffer very possibly belongs to some other
@@ -1697,8 +1565,8 @@ recheck:
 				goto recheck;
 			}
 			/* Now we can do what we came for */
-			buf->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
-			ClearBufferDirtiedByMe(i, buf);
+			bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
+			BufferDirtiedByMe[i - 1] = false;
 
 			/*
 			 * Release any refcount we may have.
@@ -1707,11 +1575,11 @@ recheck:
 			 * probably wrong.	I added the Assert to find out --- tgl
 			 * 11/99.
 			 */
-			if (!(buf->flags & BM_FREE))
+			if (!(bufHdr->flags & BM_FREE))
 			{
 				/* Assert checks that buffer will actually get freed! */
 				Assert(PrivateRefCount[i - 1] == 1 &&
-					   buf->refcount == 1);
+					   bufHdr->refcount == 1);
 				/* ReleaseBuffer expects we do not hold the lock at entry */
 				SpinRelease(BufMgrLock);
 				ReleaseBuffer(i);
@@ -1720,9 +1588,19 @@ recheck:
 			/*
 			 * And mark the buffer as no longer occupied by this rel.
 			 */
-			BufTableDelete(buf);
+			BufTableDelete(bufHdr);
+		}
+		else
+		{
+			Assert(bufHdr->relId.relId != relid ||
+			(bufHdr->relId.dbId != MyDatabaseId &&
+			 bufHdr->relId.dbId != InvalidOid));
+			if (RelFileNodeEquals(rel->rd_node, 
+					BufferTagLastDirtied[i - 1].rnode))
+				BufferDirtiedByMe[i - 1] = false;
 		}
 	}
+
 	SpinRelease(BufMgrLock);
 }
 
@@ -1741,14 +1619,19 @@ void
 DropBuffers(Oid dbid)
 {
 	int			i;
-	BufferDesc *buf;
+	BufferDesc *bufHdr;
 
 	SpinAcquire(BufMgrLock);
 	for (i = 1; i <= NBuffers; i++)
 	{
-		buf = &BufferDescriptors[i - 1];
+		bufHdr = &BufferDescriptors[i - 1];
 recheck:
-		if (buf->tag.relId.dbId == dbid)
+		/*
+		 * We know that currently database OID is tblNode but
+		 * this probably will be changed in future and this
+		 * func will be used to drop tablespace buffers.
+		 */
+		if (bufHdr->tag.rnode.tblNode == dbid)
 		{
 
 			/*
@@ -1756,9 +1639,9 @@ recheck:
 			 * don't want to delete the database out from under someone
 			 * who's just trying to flush the buffer!
 			 */
-			if (buf->flags & BM_IO_IN_PROGRESS)
+			if (bufHdr->flags & BM_IO_IN_PROGRESS)
 			{
-				WaitIO(buf, BufMgrLock);
+				WaitIO(bufHdr, BufMgrLock);
 
 				/*
 				 * By now, the buffer very possibly belongs to some other
@@ -1767,18 +1650,24 @@ recheck:
 				goto recheck;
 			}
 			/* Now we can do what we came for */
-			buf->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
-			ClearBufferDirtiedByMe(i, buf);
+			bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
+			BufferDirtiedByMe[i - 1] = false;
 
 			/*
 			 * The thing should be free, if caller has checked that no
 			 * backends are running in that database.
 			 */
-			Assert(buf->flags & BM_FREE);
+			Assert(bufHdr->flags & BM_FREE);
 			/*
 			 * And mark the buffer as no longer occupied by this page.
 			 */
-			BufTableDelete(buf);
+			BufTableDelete(bufHdr);
+		}
+		else
+		{
+			Assert(bufHdr->relId.dbId != dbid);
+			if (BufferTagLastDirtied[i - 1].rnode.tblNode == dbid)
+				BufferDirtiedByMe[i - 1] = false;
 		}
 	}
 	SpinRelease(BufMgrLock);
@@ -1917,22 +1806,22 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
 {
 	Oid			relid = RelationGetRelid(rel);
 	int			i;
-	BufferDesc *buf;
+	BufferDesc *bufHdr;
 
 	if (rel->rd_myxactonly)
 	{
 		for (i = 0; i < NLocBuffer; i++)
 		{
-			buf = &LocalBufferDescriptors[i];
-			if (buf->tag.relId.relId == relid)
+			bufHdr = &LocalBufferDescriptors[i];
+			if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
 			{
-				if (buf->flags & BM_DIRTY)
+				if (bufHdr->flags & BM_DIRTY)
 				{
 					if (FlushBuffer(-i - 1, false) != STATUS_OK)
 					{
 						elog(NOTICE, "FlushRelationBuffers(%s (local), %u): block %u is dirty, could not flush it",
 							 RelationGetRelationName(rel), firstDelBlock,
-							 buf->tag.blockNum);
+							 bufHdr->tag.blockNum);
 						return -1;
 					}
 				}
@@ -1940,14 +1829,18 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
 				{
 					elog(NOTICE, "FlushRelationBuffers(%s (local), %u): block %u is referenced (%ld)",
 						 RelationGetRelationName(rel), firstDelBlock,
-						 buf->tag.blockNum, LocalRefCount[i]);
+						 bufHdr->tag.blockNum, LocalRefCount[i]);
 					return -2;
 				}
-				if (buf->tag.blockNum >= firstDelBlock)
+				if (bufHdr->tag.blockNum >= firstDelBlock)
 				{
-					buf->tag.relId.relId = InvalidOid;
+					bufHdr->tag.rnode.relNode = InvalidOid;
 				}
 			}
+			else
+			{
+				Assert(bufHdr->relId.relId != relid);
+			}
 		}
 		return 0;
 	}
@@ -1955,22 +1848,20 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
 	SpinAcquire(BufMgrLock);
 	for (i = 0; i < NBuffers; i++)
 	{
-		buf = &BufferDescriptors[i];
+		bufHdr = &BufferDescriptors[i];
 recheck:
-		if (buf->tag.relId.relId == relid &&
-			(buf->tag.relId.dbId == MyDatabaseId ||
-			 buf->tag.relId.dbId == (Oid) NULL))
+		if (RelFileNodeEquals(bufHdr->tag.rnode, rel->rd_node))
 		{
-			if (buf->flags & BM_DIRTY)
+			if (bufHdr->flags & BM_DIRTY)
 			{
-				PinBuffer(buf);
+				PinBuffer(bufHdr);
 				SpinRelease(BufMgrLock);
 				if (FlushBuffer(i + 1, true) != STATUS_OK)
 				{
 					elog(NOTICE, "FlushRelationBuffers(%s, %u): block %u is dirty (private %ld, global %d), could not flush it",
 						 RelationGetRelationName(rel), firstDelBlock,
-						 buf->tag.blockNum,
-						 PrivateRefCount[i], buf->refcount);
+						 bufHdr->tag.blockNum,
+						 PrivateRefCount[i], bufHdr->refcount);
 					return -1;
 				}
 				SpinAcquire(BufMgrLock);
@@ -1981,20 +1872,26 @@ recheck:
 				 */
 				goto recheck;
 			}
-			if (!(buf->flags & BM_FREE))
+			if (!(bufHdr->flags & BM_FREE))
 			{
 				SpinRelease(BufMgrLock);
 				elog(NOTICE, "FlushRelationBuffers(%s, %u): block %u is referenced (private %ld, global %d)",
 					 RelationGetRelationName(rel), firstDelBlock,
-					 buf->tag.blockNum,
-					 PrivateRefCount[i], buf->refcount);
+					 bufHdr->tag.blockNum,
+					 PrivateRefCount[i], bufHdr->refcount);
 				return -2;
 			}
-			if (buf->tag.blockNum >= firstDelBlock)
+			if (bufHdr->tag.blockNum >= firstDelBlock)
 			{
-				BufTableDelete(buf);
+				BufTableDelete(bufHdr);
 			}
 		}
+		else
+		{
+			Assert(bufHdr->relId.relId != relid ||
+				(bufHdr->relId.dbId != MyDatabaseId &&
+				bufHdr->relId.dbId != InvalidOid));
+		}
 	}
 	SpinRelease(BufMgrLock);
 	return 0;
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 91eff97f26482649de63578b35394ce71cc1b373..3cb8f572b896bbf4352c0d007f91fcd434d4e347 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.30 2000/04/12 17:15:34 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.31 2000/10/18 05:50:15 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,7 +60,8 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 	/* a low tech search for now -- not optimized for scans */
 	for (i = 0; i < NLocBuffer; i++)
 	{
-		if (LocalBufferDescriptors[i].tag.relId.relId == RelationGetRelid(reln) &&
+		if (LocalBufferDescriptors[i].tag.rnode.relNode == 
+			reln->rd_node.relNode &&
 			LocalBufferDescriptors[i].tag.blockNum == blockNum)
 		{
 
@@ -102,7 +103,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 	 */
 	if (bufHdr->flags & BM_DIRTY)
 	{
-		Relation	bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
+		Relation	bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
 
 		Assert(bufrel != NULL);
 
@@ -120,9 +121,13 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 
 	/*
 	 * it's all ours now.
+	 *
+	 * We need not in tblNode currently but will in future I think,
+	 * when we'll give up rel->rd_fd to fmgr cache.
 	 */
-	bufHdr->tag.relId.relId = RelationGetRelid(reln);
+	bufHdr->tag.rnode = reln->rd_node;
 	bufHdr->tag.blockNum = blockNum;
+	bufHdr->relId = reln->rd_lockInfo.lockRelId;
 	bufHdr->flags &= ~BM_DIRTY;
 
 	/*
@@ -187,7 +192,7 @@ FlushLocalBuffer(Buffer buffer, bool release)
 	bufid = -(buffer + 1);
 	bufHdr = &LocalBufferDescriptors[bufid];
 	bufHdr->flags &= ~BM_DIRTY;
-	bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
+	bufrel = RelationIdCacheGetRelation(bufHdr->relId.relId);
 
 	Assert(bufrel != NULL);
 	smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
@@ -263,7 +268,7 @@ LocalBufferSync(void)
 #ifdef LBDEBUG
 			fprintf(stderr, "LB SYNC %d\n", -i - 1);
 #endif
-			bufrel = RelationIdCacheGetRelation(buf->tag.relId.relId);
+			bufrel = RelationIdCacheGetRelation(buf->relId.relId);
 
 			Assert(bufrel != NULL);
 
@@ -274,7 +279,7 @@ LocalBufferSync(void)
 			/* drop relcache refcount from RelationIdCacheGetRelation */
 			RelationDecrementReferenceCount(bufrel);
 
-			buf->tag.relId.relId = InvalidOid;
+			buf->relId.relId = InvalidOid;
 			buf->flags &= ~BM_DIRTY;
 		}
 	}
@@ -292,7 +297,7 @@ ResetLocalBufferPool(void)
 	{
 		BufferDesc *buf = &LocalBufferDescriptors[i];
 
-		buf->tag.relId.relId = InvalidOid;
+		buf->tag.rnode.relNode = InvalidOid;
 		buf->flags &= ~BM_DIRTY;
 		buf->buf_id = -i - 2;
 	}
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 4f4a516afdfe9aca17b8d9853847cf65a576202b..12bf6604da198a504a23d96fd0871a46b3388599 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: buf_internals.h,v 1.38 2000/10/16 14:52:28 vadim Exp $
+ * $Id: buf_internals.h,v 1.39 2000/10/18 05:50:16 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,27 +44,27 @@ typedef long **BufferBlock;
 
 typedef struct buftag
 {
-	LockRelId	relId;
+	RelFileNode	rnode;
 	BlockNumber blockNum;		/* blknum relative to begin of reln */
 } BufferTag;
 
 #define CLEAR_BUFFERTAG(a) \
 ( \
-	(a)->relId.dbId = InvalidOid, \
-	(a)->relId.relId = InvalidOid, \
+	(a)->rnode.tblNode = InvalidOid, \
+	(a)->rnode.relNode = InvalidOid, \
 	(a)->blockNum = InvalidBlockNumber \
 )
 
 #define INIT_BUFFERTAG(a,xx_reln,xx_blockNum) \
 ( \
 	(a)->blockNum = (xx_blockNum), \
-	(a)->relId = (xx_reln)->rd_lockInfo.lockRelId \
+	(a)->rnode = (xx_reln)->rd_node \
 )
 
-#ifdef OLD_FILE_NAMING
-/* If we have to write a buffer "blind" (without a relcache entry),
- * the BufferTag is not enough information.  BufferBlindId carries the
- * additional information needed.
+/*
+ * We don't need in this data any more but it allows more user
+ * friendly error messages. Feel free to get rid of it
+ * (and change a lot of places -:))
  */
 typedef struct bufblindid
 {
@@ -72,17 +72,6 @@ typedef struct bufblindid
 	char		relname[NAMEDATALEN];	/* name of reln */
 }			BufferBlindId;
 
-#else
-
-typedef struct bufblindid
-{
-	char		dbname[NAMEDATALEN];	/* name of db in which buf belongs */
-	char		relname[NAMEDATALEN];	/* name of reln */
-	RelFileNode	rnode;
-} BufferBlindId;
-
-#endif
-
 #define BAD_BUFFER_ID(bid) ((bid) < 1 || (bid) > NBuffers)
 #define INVALID_DESCRIPTOR (-3)
 
@@ -120,7 +109,22 @@ typedef struct sbufdesc
 	bool		ri_lock;		/* read-intent lock */
 	bool		w_lock;			/* context exclusively locked */
 
-	BufferBlindId blind;		/* extra info to support blind write */
+	/* 
+	 * This is logical information about relation.
+	 * IT MUST CORRESPOND TO BUFFER TAG!
+	 * If you're going to play with relation file node (ie change relation
+	 * file) then you have to exclusively lock relation, create new one
+	 * (with new relID), make data transformation, flush from pool buffers
+	 * of both files (old and new), flush old relation from cache,
+	 * update relfilenode in pg_class, flush new relation version from
+	 * cache, open it - now you can use relation with new file.
+	 *
+	 * Why we keep relId here? To re-use file descriptors. On rollback
+	 * WAL uses dummy relId - bad (more blind writes - open/close calls),
+	 * but allowable. Obviously we should have another cache in file manager.
+	 */
+	LockRelId	relId;
+	BufferBlindId blind;		/* was used to support blind write */
 } BufferDesc;
 
 /*
@@ -187,6 +191,7 @@ extern long *PrivateRefCount;
 extern bits8 *BufferLocks;
 extern BufferTag *BufferTagLastDirtied;
 extern BufferBlindId *BufferBlindLastDirtied;
+extern LockRelId *BufferRelidLastDirtied;
 extern bool *BufferDirtiedByMe;
 extern SPINLOCK BufMgrLock;
 
diff --git a/src/include/storage/relfilenode.h b/src/include/storage/relfilenode.h
index de4d1e1beea1ee13b97ec3ba4537cacc0a450159..ee6e2c2280504b89017cd12d114eb5937a332636 100644
--- a/src/include/storage/relfilenode.h
+++ b/src/include/storage/relfilenode.h
@@ -15,4 +15,8 @@ typedef struct RelFileNode
 	Oid					relNode;		/* relation */
 } RelFileNode;
 
+#define	RelFileNodeEquals(node1, node2)	\
+	((node1).relNode == (node2).relNode && \
+	(node2).tblNode == (node2).tblNode)
+
 #endif	/* RELFILENODE_H */