* ProcessSyncRequests() -- Process queued fsync requests. */
| 303 | * ProcessSyncRequests() -- Process queued fsync requests. |
| 304 | */ |
| 305 | void |
| 306 | ProcessSyncRequests(void) |
| 307 | { |
| 308 | static bool sync_in_progress = false; |
| 309 | |
| 310 | HASH_SEQ_STATUS hstat; |
| 311 | PendingFsyncEntry *entry; |
| 312 | int absorb_counter; |
| 313 | |
| 314 | /* Statistics on sync times */ |
| 315 | int processed = 0; |
| 316 | instr_time sync_start, |
| 317 | sync_end, |
| 318 | sync_diff; |
| 319 | uint64 elapsed; |
| 320 | uint64 longest = 0; |
| 321 | uint64 total_elapsed = 0; |
| 322 | |
| 323 | /* |
| 324 | * This is only called during checkpoints, and checkpoints should only |
| 325 | * occur in processes that have created a pendingOps. |
| 326 | */ |
| 327 | if (!pendingOps) |
| 328 | elog(ERROR, "cannot sync without a pendingOps table"); |
| 329 | |
| 330 | /* |
| 331 | * If we are in the checkpointer, the sync had better include all fsync |
| 332 | * requests that were queued by backends up to this point. The tightest |
| 333 | * race condition that could occur is that a buffer that must be written |
| 334 | * and fsync'd for the checkpoint could have been dumped by a backend just |
| 335 | * before it was visited by BufferSync(). We know the backend will have |
| 336 | * queued an fsync request before clearing the buffer's dirtybit, so we |
| 337 | * are safe as long as we do an Absorb after completing BufferSync(). |
| 338 | */ |
| 339 | AbsorbSyncRequests(); |
| 340 | |
| 341 | /* |
| 342 | * To avoid excess fsync'ing (in the worst case, maybe a never-terminating |
| 343 | * checkpoint), we want to ignore fsync requests that are entered into the |
| 344 | * hashtable after this point --- they should be processed next time, |
| 345 | * instead. We use sync_cycle_ctr to tell old entries apart from new |
| 346 | * ones: new ones will have cycle_ctr equal to the incremented value of |
| 347 | * sync_cycle_ctr. |
| 348 | * |
| 349 | * In normal circumstances, all entries present in the table at this point |
| 350 | * will have cycle_ctr exactly equal to the current (about to be old) |
| 351 | * value of sync_cycle_ctr. However, if we fail partway through the |
| 352 | * fsync'ing loop, then older values of cycle_ctr might remain when we |
| 353 | * come back here to try again. Repeated checkpoint failures would |
| 354 | * eventually wrap the counter around to the point where an old entry |
| 355 | * might appear new, causing us to skip it, possibly allowing a checkpoint |
| 356 | * to succeed that should not have. To forestall wraparound, any time the |
| 357 | * previous ProcessSyncRequests() failed to complete, run through the |
| 358 | * table and forcibly set cycle_ctr = sync_cycle_ctr. |
| 359 | * |
| 360 | * Think not to merge this loop with the main loop, as the problem is |
| 361 | * exactly that that loop may fail before having visited all the entries. |
| 362 | * From a performance point of view it doesn't matter anyway, as this path |
no test coverage detected