zircon/system/ulib/fs/journal/test/journal_test.cc
// Tests that when metadata operations fail, subsequent operations also fail to avoid
// leaving the device in an inconsistent state.
//
// Tests a failure which occurs when writing metadata to the final on-disk location (non-journal).
Tests that when metadata operations fail, subsequent operations also fail to avoid
leaving the device in an inconsistent state.

Tests a failure which occurs when writing metadata to the final on-disk location (non-journal).
Tests that when metadata operations fail subsequent operations also fail to avoid leaving the device in an inconsistent state . Tests a failure which occurs when writing metadata to the final on - disk location ( non - journal ) .
TEST_F(JournalTest, MetadataWriteFailureFailsSubsequentRequests) {
  storage::VmoBuffer metadata = registry()->InitializeBuffer(3);
  const std::vector<storage::UnbufferedOperation> operations = {
      {
          zx::unowned_vmo(metadata.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 20,
              .length = 1,
          },
      },
      {
          zx::unowned_vmo(metadata.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 2,
              .dev_offset = 1234,
              .length = 1,
          },
      },
  };
  constexpr uint64_t kJournalStartBlock = 55;
  JournalRequestVerifier verifier(registry()->info(), registry()->journal(),
                                  registry()->writeback(), kJournalStartBlock);
  MockTransactionHandler::TransactionCallback callbacks[] = {
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyJournalWrite(operations[0], requests);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyMetadataWrite(operations[0], requests);
        verifier.ExtendJournalOffset(operations[0].op.length + kEntryMetadataBlocks);
        return ZX_ERR_IO;
      },
  };
  std::atomic<bool> first_operation_failed = false;
  std::atomic<bool> second_operation_failed = false;
  MockTransactionHandler handler(registry(), callbacks, std::size(callbacks));
  {
    Journal journal(&handler, take_info(), take_journal_buffer(), take_data_buffer(),
                    kJournalStartBlock, Journal::Options());
    auto promise0 =
        journal.WriteMetadata({operations[0]}).then([&](fit::result<void, zx_status_t>& result) {
          EXPECT_STATUS(ZX_ERR_IO, result.error());
          first_operation_failed = true;
        });
    auto promise1 =
        journal.WriteMetadata({operations[1]}).then([&](fit::result<void, zx_status_t>& result) {
          EXPECT_STATUS(ZX_ERR_IO_REFUSED, result.error());
          second_operation_failed = true;
        });
    journal.schedule_task(std::move(promise0));
    journal.schedule_task(std::move(promise1));
  }
  EXPECT_TRUE(first_operation_failed);
  EXPECT_TRUE(second_operation_failed);
}
TEST_F ( JournalTest , MetadataWriteFailureFailsSubsequentRequests ) { storage :: VmoBuffer metadata = registry ( ) -> InitializeBuffer ( 3 ) ; const std :: vector < storage :: UnbufferedOperation > operations = { { zx :: unowned_vmo ( metadata . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 20 , . length = 1 , } , } , { zx :: unowned_vmo ( metadata . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 2 , . dev_offset = 1234 , . length = 1 , } , } , } ; constexpr uint64_t kJournalStartBlock = 55 ; JournalRequestVerifier verifier ( registry ( ) -> info ( ) , registry ( ) -> journal ( ) , registry ( ) -> writeback ( ) , kJournalStartBlock ) ; MockTransactionHandler :: TransactionCallback callbacks [ ] = { [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyJournalWrite ( operations [ 0 ] , requests ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyMetadataWrite ( operations [ 0 ] , requests ) ; verifier . ExtendJournalOffset ( operations [ 0 ] . op . length + kEntryMetadataBlocks ) ; return ZX_ERR_IO ; } , } ; std :: atomic < bool > first_operation_failed = false ; std :: atomic < bool > second_operation_failed = false ; MockTransactionHandler handler ( registry ( ) , callbacks , std :: size ( callbacks ) ) ; { Journal journal ( & handler , take_info ( ) , take_journal_buffer ( ) , take_data_buffer ( ) , kJournalStartBlock , Journal :: Options ( ) ) ; auto promise0 = journal . WriteMetadata ( { operations [ 0 ] } ) . then ( [ & ] ( fit :: result < void , zx_status_t > & result ) { EXPECT_STATUS ( ZX_ERR_IO , result . error ( ) ) ; first_operation_failed = true ; } ) ; auto promise1 = journal . WriteMetadata ( { operations [ 1 ] } ) . then ( [ & ] ( fit :: result < void , zx_status_t > & result ) { EXPECT_STATUS ( ZX_ERR_IO_REFUSED , result . error ( ) ) ; second_operation_failed = true ; } ) ; journal . schedule_task ( std :: move ( promise0 ) ) ; journal . schedule_task ( std :: move ( promise1 ) ) ; } EXPECT_TRUE ( first_operation_failed ) ; EXPECT_TRUE ( second_operation_failed ) ; }
Tests that when metadata operations fail, subsequent operations also fail to avoid
leaving the device in an inconsistent state.
Tests that when metadata operations fail subsequent operations also fail to avoid leaving the device in an inconsistent state .
// Failure triggered by our MockTransactionHandler implementation. // Failure triggered by the journal itself.