zircon/system/ulib/fs/journal/test/journal_test.cc
// Tests that writing "block N" to metadata before "block M" to data will not revoke the
// block before data is written to the underlying device (For N != M).
Tests that writing "block N" to metadata before "block M" to data will not revoke the
block before data is written to the underlying device (For N != M).
Tests that writing " block N " to metadata before " block M " to data will not revoke the block before data is written to the underlying device ( For N ! = M ) .
TEST_F(JournalTest, WriteDifferentBlockMetadataThenDataDoesNotRevoke) {
  storage::VmoBuffer metadata = registry()->InitializeBuffer(kJournalLength);
  storage::VmoBuffer buffer = registry()->InitializeBuffer(5);
  const std::vector<storage::UnbufferedOperation> operations = {
      {
          zx::unowned_vmo(metadata.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 10,
              .length = 3,
          },
      },
      {
          zx::unowned_vmo(buffer.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 20,
              .length = 3,
          },
      },
  };
  constexpr uint64_t kJournalStartBlock = 55;
  JournalRequestVerifier verifier(registry()->info(), registry()->journal(),
                                  registry()->writeback(), kJournalStartBlock);
  uint64_t sequence_number = 0;
  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_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        registry()->VerifyReplay({operations[0]}, ++sequence_number);
        verifier.VerifyDataWrite(operations[1], requests);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyInfoBlockWrite(sequence_number, requests);
        registry()->VerifyReplay({}, sequence_number);
        return ZX_OK;
      },
  };
  MockTransactionHandler handler(registry(), callbacks, std::size(callbacks));
  {
    Journal journal(&handler, take_info(), take_journal_buffer(), take_data_buffer(),
                    kJournalStartBlock, Journal::Options());
    auto promise =
        journal.WriteMetadata({operations[0]}).and_then(journal.WriteData({operations[1]}));
    journal.schedule_task(std::move(promise));
  }
}
TEST_F ( JournalTest , WriteDifferentBlockMetadataThenDataDoesNotRevoke ) { storage :: VmoBuffer metadata = registry ( ) -> InitializeBuffer ( kJournalLength ) ; storage :: VmoBuffer buffer = registry ( ) -> InitializeBuffer ( 5 ) ; const std :: vector < storage :: UnbufferedOperation > operations = { { zx :: unowned_vmo ( metadata . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 10 , . length = 3 , } , } , { zx :: unowned_vmo ( buffer . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 20 , . length = 3 , } , } , } ; constexpr uint64_t kJournalStartBlock = 55 ; JournalRequestVerifier verifier ( registry ( ) -> info ( ) , registry ( ) -> journal ( ) , registry ( ) -> writeback ( ) , kJournalStartBlock ) ; uint64_t sequence_number = 0 ; 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_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { registry ( ) -> VerifyReplay ( { operations [ 0 ] } , ++ sequence_number ) ; verifier . VerifyDataWrite ( operations [ 1 ] , requests ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyInfoBlockWrite ( sequence_number , requests ) ; registry ( ) -> VerifyReplay ( { } , sequence_number ) ; return ZX_OK ; } , } ; MockTransactionHandler handler ( registry ( ) , callbacks , std :: size ( callbacks ) ) ; { Journal journal ( & handler , take_info ( ) , take_journal_buffer ( ) , take_data_buffer ( ) , kJournalStartBlock , Journal :: Options ( ) ) ; auto promise = journal . WriteMetadata ( { operations [ 0 ] } ) . and_then ( journal . WriteData ( { operations [ 1 ] } ) ) ; journal . schedule_task ( std :: move ( promise ) ) ; } }
Tests that writing "block N" to metadata before "block M" to data will not revoke the
block before data is written to the underlying device (For N != M).
Tests that writing " block N " to metadata before " block M " to data will not revoke the block before data is written to the underlying device ( For N ! = M ) .
// Since the metadata and data regions do not overlap, we're fine letting the // metadata operation replay: it won't overwrite our data operation.