=== Applying patches on top of PostgreSQL commit ID 5142f0093e648d1a32fdcc7c835d17fa103e1239 === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Mon Apr 20 00:40:24 UTC 2026 On branch cf/6555 nothing to commit, working tree clean === using 'git am' to apply patch ./v20260328-0001-pg_buffercache_pages-modernization-and-opt.patch === Applying: pg_buffercache_pages() modernization and optimization Using index info to reconstruct a base tree... M contrib/pg_buffercache/pg_buffercache_pages.c Falling back to patching base and 3-way merge... Auto-merging contrib/pg_buffercache/pg_buffercache_pages.c CONFLICT (content): Merge conflict in contrib/pg_buffercache/pg_buffercache_pages.c error: Failed to merge in the changes. hint: Use 'git am --show-current-patch=diff' to see the failed patch Patch failed at 0001 pg_buffercache_pages() modernization and optimization When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". === using patch(1) to apply patch ./v20260328-0001-pg_buffercache_pages-modernization-and-opt.patch === patching file contrib/pg_buffercache/pg_buffercache_pages.c Hunk #1 FAILED at 37. Hunk #2 FAILED at 117. Hunk #3 FAILED at 262. 3 out of 3 hunks FAILED -- saving rejects to file contrib/pg_buffercache/pg_buffercache_pages.c.rej Removing contrib/pg_buffercache/pg_buffercache_pages.c.rej === using 'git apply' to apply patch ./v20260328-0001-pg_buffercache_pages-modernization-and-opt.patch === Applied patch to 'contrib/pg_buffercache/pg_buffercache_pages.c' with conflicts. U contrib/pg_buffercache/pg_buffercache_pages.c diff --cc contrib/pg_buffercache/pg_buffercache_pages.c index 1ec2cf0e6f4,fae531573cb..00000000000 --- a/contrib/pg_buffercache/pg_buffercache_pages.c +++ b/contrib/pg_buffercache/pg_buffercache_pages.c @@@ -86,6 -86,8 +86,11 @@@ pg_buffercache_pages(PG_FUNCTION_ARGS { ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; TupleDesc expected_tupledesc; ++<<<<<<< ours ++======= + Datum values[NUM_BUFFERCACHE_PAGES_ELEM]; + bool nulls[NUM_BUFFERCACHE_PAGES_ELEM]; ++>>>>>>> theirs int i; /* @@@ -98,69 -100,68 +103,134 @@@ */ if (get_call_result_type(fcinfo, NULL, &expected_tupledesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); ++<<<<<<< ours + + if (expected_tupledesc->natts < NUM_BUFFERCACHE_PAGES_MIN_ELEM || + expected_tupledesc->natts > NUM_BUFFERCACHE_PAGES_ELEM) + elog(ERROR, "incorrect number of output arguments"); + + InitMaterializedSRF(fcinfo, 0); + + /* + * Scan through all the buffers, adding one row for each of the buffers to + * the tuplestore. + * + * We don't hold the partition locks, so we don't get a consistent + * snapshot across all buffers, but we do grab the buffer header locks, so + * the information of each buffer is self-consistent. + */ + for (i = 0; i < NBuffers; i++) + { + BufferDesc *bufHdr; + uint64 buf_state; + uint32 bufferid; + RelFileNumber relfilenumber; + Oid reltablespace; + Oid reldatabase; + ForkNumber forknum; + BlockNumber blocknum; + bool isvalid; + bool isdirty; + uint16 usagecount; + int32 pinning_backends; + Datum values[NUM_BUFFERCACHE_PAGES_ELEM]; + bool nulls[NUM_BUFFERCACHE_PAGES_ELEM]; + + CHECK_FOR_INTERRUPTS(); + + bufHdr = GetBufferDescriptor(i); + /* Lock each buffer header before inspecting. */ + buf_state = LockBufHdr(bufHdr); + + bufferid = BufferDescriptorGetBuffer(bufHdr); + relfilenumber = BufTagGetRelNumber(&bufHdr->tag); + reltablespace = bufHdr->tag.spcOid; + reldatabase = bufHdr->tag.dbOid; + forknum = BufTagGetForkNum(&bufHdr->tag); + blocknum = bufHdr->tag.blockNum; + usagecount = BUF_STATE_GET_USAGECOUNT(buf_state); + pinning_backends = BUF_STATE_GET_REFCOUNT(buf_state); + + if (buf_state & BM_DIRTY) + isdirty = true; + else + isdirty = false; + + /* Note if the buffer is valid, and has storage created */ + if ((buf_state & BM_VALID) && (buf_state & BM_TAG_VALID)) + isvalid = true; + else + isvalid = false; + + UnlockBufHdr(bufHdr); + + /* Build the tuple and add it to tuplestore */ + values[0] = Int32GetDatum(bufferid); + nulls[0] = false; ++======= + + if (expected_tupledesc->natts < NUM_BUFFERCACHE_PAGES_MIN_ELEM || + expected_tupledesc->natts > NUM_BUFFERCACHE_PAGES_ELEM) + elog(ERROR, "incorrect number of output arguments"); + + InitMaterializedSRF(fcinfo, 0); + + /* + * Scan through all the buffers, adding one row for each of the buffers to + * the tuplestore. + * + * We don't hold the partition locks, so we don't get a consistent + * snapshot across all buffers, but we do grab the buffer header locks, so + * the information of each buffer is self-consistent. + */ + for (i = 0; i < NBuffers; i++) + { + BufferDesc *bufHdr; + uint64 buf_state; + uint32 bufferid; + RelFileNumber relfilenumber; + Oid reltablespace; + Oid reldatabase; + ForkNumber forknum; + BlockNumber blocknum; + bool isvalid; + bool isdirty; + uint16 usagecount; + int32 pinning_backends; + + CHECK_FOR_INTERRUPTS(); + + bufHdr = GetBufferDescriptor(i); + /* Lock each buffer header before inspecting. */ + buf_state = LockBufHdr(bufHdr); + + bufferid = BufferDescriptorGetBuffer(bufHdr); + relfilenumber = BufTagGetRelNumber(&bufHdr->tag); + reltablespace = bufHdr->tag.spcOid; + reldatabase = bufHdr->tag.dbOid; + forknum = BufTagGetForkNum(&bufHdr->tag); + blocknum = bufHdr->tag.blockNum; + usagecount = BUF_STATE_GET_USAGECOUNT(buf_state); + pinning_backends = BUF_STATE_GET_REFCOUNT(buf_state); + + if (buf_state & BM_DIRTY) + isdirty = true; + else + isdirty = false; + + /* Note if the buffer is valid, and has storage created */ + if ((buf_state & BM_VALID) && (buf_state & BM_TAG_VALID)) + isvalid = true; + else + isvalid = false; + + UnlockBufHdr(bufHdr); + + /* Build the tuple and add it to tuplestore */ + memset(nulls, 0, sizeof(nulls)); + + values[0] = Int32GetDatum(bufferid); ++>>>>>>> theirs /* * Set all fields except the bufferid to null if the buffer is unused @@@ -181,22 -183,15 +252,34 @@@ else { values[1] = ObjectIdGetDatum(relfilenumber); ++<<<<<<< ours + nulls[1] = false; + values[2] = ObjectIdGetDatum(reltablespace); + nulls[2] = false; + values[3] = ObjectIdGetDatum(reldatabase); + nulls[3] = false; + values[4] = Int16GetDatum(forknum); + nulls[4] = false; + values[5] = Int64GetDatum((int64) blocknum); + nulls[5] = false; + values[6] = BoolGetDatum(isdirty); + nulls[6] = false; + values[7] = UInt16GetDatum(usagecount); + nulls[7] = false; + /* unused for v1.0 callers, but the array is always long enough */ + values[8] = Int32GetDatum(pinning_backends); + nulls[8] = false; ++======= + values[2] = ObjectIdGetDatum(reltablespace); + values[3] = ObjectIdGetDatum(reldatabase); + values[4] = Int16GetDatum(forknum); + values[5] = Int64GetDatum((int64) blocknum); + values[6] = BoolGetDatum(isdirty); + values[7] = UInt16GetDatum(usagecount); + /* unused for v1.0 callers, but the array is always long enough */ + if (expected_tupledesc->natts == NUM_BUFFERCACHE_PAGES_ELEM) + values[8] = Int32GetDatum(pinning_backends); ++>>>>>>> theirs } tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);