|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.210 2006/09/17 22:16:22 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.211 2006/09/25 22:01:10 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -175,9 +175,26 @@ ReadBuffer(Relation reln, BlockNumber blockNum)
|
175 | 175 | /*
|
176 | 176 | * We get here only in the corner case where we are trying to extend
|
177 | 177 | * the relation but we found a pre-existing buffer marked BM_VALID.
|
178 |
| - * (This can happen because mdread doesn't complain about reads |
179 |
| - * beyond EOF --- which is arguably bogus, but changing it seems |
180 |
| - * tricky.) We *must* do smgrextend before succeeding, else the |
| 178 | + * This can happen because mdread doesn't complain about reads beyond |
| 179 | + * EOF --- which is arguably bogus, but changing it seems tricky --- |
| 180 | + * and so a previous attempt to read a block just beyond EOF could |
| 181 | + * have left a "valid" zero-filled buffer. Unfortunately, we have |
| 182 | + * also seen this case occurring because of buggy Linux kernels that |
| 183 | + * sometimes return an lseek(SEEK_END) result that doesn't account for |
| 184 | + * a recent write. In that situation, the pre-existing buffer would |
| 185 | + * contain valid data that we don't want to overwrite. Since the |
| 186 | + * legitimate cases should always have left a zero-filled buffer, |
| 187 | + * complain if not PageIsNew. |
| 188 | + */ |
| 189 | + bufBlock = isLocalBuf ? LocalBufHdrGetBlock(bufHdr) : BufHdrGetBlock(bufHdr); |
| 190 | + if (!PageIsNew((PageHeader) bufBlock)) |
| 191 | + ereport(ERROR, |
| 192 | + (errmsg("unexpected data beyond EOF in block %u of relation \"%s\"", |
| 193 | + blockNum, RelationGetRelationName(reln)), |
| 194 | + errhint("This has been seen to occur with buggy kernels; consider updating your system."))); |
| 195 | + |
| 196 | + /* |
| 197 | + * We *must* do smgrextend before succeeding, else the |
181 | 198 | * page will not be reserved by the kernel, and the next P_NEW call
|
182 | 199 | * will decide to return the same page. Clear the BM_VALID bit,
|
183 | 200 | * do the StartBufferIO call that BufferAlloc didn't, and proceed.
|
|
0 commit comments