7
7
*
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.2 1996/07/23 05:44:10 scrappy Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.2.2.1 1996/09/19 19:47:31 scrappy Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -280,7 +280,7 @@ ReadBufferWithBufferLock(Relation reln,
280
280
* the buffer can tell that the contents are invalid.
281
281
*/
282
282
bufHdr -> flags |= BM_IO_ERROR ;
283
-
283
+ bufHdr -> flags &= ~ BM_IO_IN_PROGRESS ;
284
284
} else {
285
285
/* IO Succeeded. clear the flags, finish buffer update */
286
286
@@ -297,6 +297,9 @@ ReadBufferWithBufferLock(Relation reln,
297
297
298
298
SpinRelease (BufMgrLock );
299
299
300
+ if (status == SM_FAIL )
301
+ return (InvalidBuffer );
302
+
300
303
return (BufferDescriptorGetBuffer (bufHdr ));
301
304
}
302
305
@@ -387,6 +390,14 @@ BufferAlloc(Relation reln,
387
390
/* GetFreeBuffer will abort if it can't find a free buffer */
388
391
buf = GetFreeBuffer ();
389
392
393
+ /*
394
+ * But it can return buf == NULL if we are in aborting
395
+ * transaction now and so elog(WARN,...) in GetFreeBuffer
396
+ * will not abort again.
397
+ */
398
+ if ( buf == NULL )
399
+ return (NULL );
400
+
390
401
/*
391
402
* There should be exactly one pin on the buffer after
392
403
* it is allocated -- ours. If it had a pin it wouldn't
@@ -399,6 +410,7 @@ BufferAlloc(Relation reln,
399
410
PrivateRefCount [BufferDescriptorGetBuffer (buf ) - 1 ] = 1 ;
400
411
401
412
if (buf -> flags & BM_DIRTY ) {
413
+ bool smok ;
402
414
/*
403
415
* Set BM_IO_IN_PROGRESS to keep anyone from doing anything
404
416
* with the contents of the buffer while we write it out.
@@ -428,11 +440,38 @@ BufferAlloc(Relation reln,
428
440
* you on machines that don't have spinlocks. If you don't
429
441
* operate with much concurrency, well...
430
442
*/
431
- (void ) BufferReplace (buf , true);
432
- BufferFlushCount ++ ;
443
+ smok = BufferReplace (buf , true);
433
444
#ifndef OPTIMIZE_SINGLE
434
445
SpinAcquire (BufMgrLock );
435
446
#endif /* OPTIMIZE_SINGLE */
447
+
448
+ if ( smok == FALSE )
449
+ {
450
+ elog (NOTICE , "BufferAlloc: cannot write block %u for %s/%s" ,
451
+ buf -> tag .blockNum , buf -> sb_dbname , buf -> sb_relname );
452
+ inProgress = FALSE;
453
+ buf -> flags |= BM_IO_ERROR ;
454
+ buf -> flags &= ~BM_IO_IN_PROGRESS ;
455
+ #ifdef HAS_TEST_AND_SET
456
+ S_UNLOCK (& (buf -> io_in_progress_lock ));
457
+ #else /* !HAS_TEST_AND_SET */
458
+ if (buf -> refcount > 1 )
459
+ SignalIO (buf );
460
+ #endif /* !HAS_TEST_AND_SET */
461
+ PrivateRefCount [BufferDescriptorGetBuffer (buf ) - 1 ] = 0 ;
462
+ buf -> refcount -- ;
463
+ if ( buf -> refcount == 0 )
464
+ {
465
+ AddBufferToFreelist (buf );
466
+ buf -> flags |= BM_FREE ;
467
+ }
468
+ buf = (BufferDesc * ) NULL ;
469
+ }
470
+ else
471
+ {
472
+ BufferFlushCount ++ ;
473
+ buf -> flags &= ~BM_DIRTY ;
474
+ }
436
475
437
476
/*
438
477
* Somebody could have pinned the buffer while we were
@@ -445,7 +484,7 @@ BufferAlloc(Relation reln,
445
484
* no reason to think that we have an immediate disaster on
446
485
* our hands.
447
486
*/
448
- if (buf -> refcount > 1 ) {
487
+ if (buf && buf -> refcount > 1 ) {
449
488
inProgress = FALSE;
450
489
buf -> flags &= ~BM_IO_IN_PROGRESS ;
451
490
#ifdef HAS_TEST_AND_SET
@@ -473,18 +512,6 @@ BufferAlloc(Relation reln,
473
512
* to do. We'll just handle this as if it were found in
474
513
* the buffer pool in the first place.
475
514
*/
476
-
477
- PinBuffer (buf2 );
478
- inProgress = (buf2 -> flags & BM_IO_IN_PROGRESS );
479
-
480
- * foundPtr = TRUE;
481
- if (inProgress ) {
482
- WaitIO (buf2 , BufMgrLock );
483
- if (buf2 -> flags & BM_IO_ERROR ) {
484
- * foundPtr = FALSE;
485
- }
486
- }
487
-
488
515
if ( buf != NULL )
489
516
{
490
517
#ifdef HAS_TEST_AND_SET
@@ -499,9 +526,19 @@ BufferAlloc(Relation reln,
499
526
PrivateRefCount [BufferDescriptorGetBuffer (buf ) - 1 ] = 0 ;
500
527
AddBufferToFreelist (buf );
501
528
buf -> flags |= BM_FREE ;
502
- buf -> flags &= ~BM_DIRTY ;
503
529
buf -> flags &= ~BM_IO_IN_PROGRESS ;
504
530
}
531
+
532
+ PinBuffer (buf2 );
533
+ inProgress = (buf2 -> flags & BM_IO_IN_PROGRESS );
534
+
535
+ * foundPtr = TRUE;
536
+ if (inProgress ) {
537
+ WaitIO (buf2 , BufMgrLock );
538
+ if (buf2 -> flags & BM_IO_ERROR ) {
539
+ * foundPtr = FALSE;
540
+ }
541
+ }
505
542
506
543
SpinRelease (BufMgrLock );
507
544
@@ -532,13 +569,6 @@ BufferAlloc(Relation reln,
532
569
533
570
}
534
571
535
- if (buf -> flags & BM_DIRTY ) {
536
- /* must clear flag first because of wierd race
537
- * condition described below.
538
- */
539
- buf -> flags &= ~BM_DIRTY ;
540
- }
541
-
542
572
/* record the database name and relation name for this buffer */
543
573
strcpy (buf -> sb_relname , reln -> rd_rel -> relname .data );
544
574
strcpy (buf -> sb_dbname , GetDatabaseName ());
@@ -813,6 +843,30 @@ BufferSync()
813
843
if (bufdb == MyDatabaseId || bufdb == (Oid ) 0 ) {
814
844
reln = RelationIdCacheGetRelation (bufrel );
815
845
846
+ /*
847
+ * We have to pin buffer to keep anyone from stealing it
848
+ * from the buffer pool while we are flushing it or
849
+ * waiting in WaitIO. It's bad for GetFreeBuffer in
850
+ * BufferAlloc, but there is no other way to prevent
851
+ * writing into disk block data from some other buffer,
852
+ * getting smgr status of some other block and
853
+ * clearing BM_DIRTY of ... - VAdim 09/16/96
854
+ */
855
+ PinBuffer (bufHdr );
856
+ if (bufHdr -> flags & BM_IO_IN_PROGRESS )
857
+ {
858
+ WaitIO (bufHdr , BufMgrLock );
859
+ UnpinBuffer (bufHdr );
860
+ if (bufHdr -> flags & BM_IO_ERROR )
861
+ {
862
+ elog (WARN , "cannot write %u for %s" ,
863
+ bufHdr -> tag .blockNum , bufHdr -> sb_relname );
864
+ }
865
+ if (reln != (Relation )NULL )
866
+ RelationDecrementReferenceCount (reln );
867
+ continue ;
868
+ }
869
+
816
870
/*
817
871
* If we didn't have the reldesc in our local cache, flush this
818
872
* page out using the 'blind write' storage manager routine. If
@@ -836,8 +890,10 @@ BufferSync()
836
890
SpinAcquire (BufMgrLock );
837
891
#endif /* OPTIMIZE_SINGLE */
838
892
893
+ UnpinBuffer (bufHdr );
839
894
if (status == SM_FAIL ) {
840
- elog (WARN , "cannot write %d for %16s" ,
895
+ bufHdr -> flags |= BM_IO_ERROR ;
896
+ elog (WARN , "cannot write %u for %s" ,
841
897
bufHdr -> tag .blockNum , bufHdr -> sb_relname );
842
898
}
843
899
0 commit comments