zircon/system/ulib/fs/journal/test/journal_test.cc
// Tests that writing "block N" to metadata before "block N" to data will revoke the
// block before data is written to the underlying device.
Tests that writing "block N" to metadata before "block N" to data will revoke the
block before data is written to the underlying device.
Tests that writing " block N " to metadata before " block N " to data will revoke the block before data is written to the underlying device .
TEST_F(JournalTest, WriteSameBlockMetadataThenDataRevokesBlock) {
  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 = 10,
              .length = 3,
          },
      },
  };
  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_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        uint64_t sequence_number = 1;
        verifier.VerifyInfoBlockWrite(sequence_number, requests);
        registry()->VerifyReplay({}, sequence_number);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        verifier.VerifyDataWrite(operations[1], requests);
        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 , WriteSameBlockMetadataThenDataRevokesBlock ) { 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 = 10 , . length = 3 , } , } , } ; 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_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { uint64_t sequence_number = 1 ; verifier . VerifyInfoBlockWrite ( sequence_number , requests ) ; registry ( ) -> VerifyReplay ( { } , sequence_number ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { verifier . VerifyDataWrite ( operations [ 1 ] , requests ) ; 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 N" to data will revoke the
block before data is written to the underlying device.
Tests that writing " block N " to metadata before " block N " to data will revoke the block before data is written to the underlying device .
// This info block is written before a data operation to intentionally avoid // replaying the metadata operation on reboot.