Thread: EvictUnpinnedBuffer and buffer free list
Hi All, EvictUnpinnedBuffer() calls InvalidateVictimBuffer() followed by UnpinBuffer() before returning. None of those functions put the buffer back into the free list. Its freeNext remains set to FREENEXT_NOT_IN_LIST. I think then that buffer will never be used and lost forever. I know that that function is only meant for development or testing but even while testing something losing a buffer forever seems like a problem. The prologue of function InvalidateVictimBuffer() says "/* Helper routine for GetVictimBuffer() ". I believe that it's expected that the buffer will be allocated to some other page, and that's why it doesn't return the buffer to the free list. But in the case of EvictUnpinnedBuffer() we are not using that buffer for any page, so it must be returned to the free list. InvalidateBuffer() does that but its prologue mentions that it's supposed to be used when freeing buffers for relations and databases. I think there are two solutions 1. Use InvalidBuffer() instead of InvalidateVictimBuffer(). But I am not sure whether that's safe or what other safety measures we have to put in EvictUnpinnedBuffer() 2. Call StrategyFreeBuffer() after InvalidateVictimBuffer() Thoughts? -- Best Wishes, Ashutosh Bapat
31.01.2025 08:15, Ashutosh Bapat пишет: > Hi All, > EvictUnpinnedBuffer() calls InvalidateVictimBuffer() followed by > UnpinBuffer() before returning. None of those functions put the buffer > back into the free list. Its freeNext remains set to > FREENEXT_NOT_IN_LIST. I think then that buffer will never be used and > lost forever. I know that that function is only meant for development > or testing but even while testing something losing a buffer forever > seems like a problem. > > The prologue of function InvalidateVictimBuffer() says "/* Helper > routine for GetVictimBuffer() ". I believe that it's expected that the > buffer will be allocated to some other page, and that's why it doesn't > return the buffer to the free list. But in the case of > EvictUnpinnedBuffer() we are not using that buffer for any page, so it > must be returned to the free list. InvalidateBuffer() does that but > its prologue mentions that it's supposed to be used when freeing > buffers for relations and databases. > > I think there are two solutions > 1. Use InvalidBuffer() instead of InvalidateVictimBuffer(). But I am > not sure whether that's safe or what other safety measures we have to > put in EvictUnpinnedBuffer() > 2. Call StrategyFreeBuffer() after InvalidateVictimBuffer() > > Thoughts? Clock eviction algorithm visit every page (by StrategyGetBuffer), so it will eventually observe this buffer and use it for new page.
On Fri, Jan 31, 2025 at 2:19 PM Yura Sokolov <y.sokolov@postgrespro.ru> wrote: > > 31.01.2025 08:15, Ashutosh Bapat пишет: > > Hi All, > > EvictUnpinnedBuffer() calls InvalidateVictimBuffer() followed by > > UnpinBuffer() before returning. None of those functions put the buffer > > back into the free list. Its freeNext remains set to > > FREENEXT_NOT_IN_LIST. I think then that buffer will never be used and > > lost forever. I know that that function is only meant for development > > or testing but even while testing something losing a buffer forever > > seems like a problem. > > > > The prologue of function InvalidateVictimBuffer() says "/* Helper > > routine for GetVictimBuffer() ". I believe that it's expected that the > > buffer will be allocated to some other page, and that's why it doesn't > > return the buffer to the free list. But in the case of > > EvictUnpinnedBuffer() we are not using that buffer for any page, so it > > must be returned to the free list. InvalidateBuffer() does that but > > its prologue mentions that it's supposed to be used when freeing > > buffers for relations and databases. > > > > I think there are two solutions > > 1. Use InvalidBuffer() instead of InvalidateVictimBuffer(). But I am > > not sure whether that's safe or what other safety measures we have to > > put in EvictUnpinnedBuffer() > > 2. Call StrategyFreeBuffer() after InvalidateVictimBuffer() > > > > Thoughts? > > Clock eviction algorithm visit every page (by StrategyGetBuffer), so it > will eventually observe this buffer and use it for new page. > yes, that's correct. That does reduce the intensity of problem very much. However, a backend which would otherwise be able to get a buffer from freelist will be forced to evict some other useful buffer. This may show unexpected results even in testing/development experiments being carried out. -- Best Wishes, Ashutosh Bapat