zircon/system/ulib/fs/journal/test/journal_test.cc
// Tests that the in-memory writeback buffer for metadata and the on-disk buffer for
// metadata can both wraparound at different offsets.
//
// Operation 0: [ H, 1, 2, 3, 4, C, _, _, _, _ ]
// Operation _: [ _, _, _, _, _, _, X, X, X, _ ] (In-memory, reserved then released)
//            : Info block written by wraparound
// Operation 1: [ 1, 2, 3, 4, C, _, _, _, _, H ] (In-memory)
// Operation 1: [ 4, C, _, _, _, _, H, 1, 2, 3 ] (On-disk)
Tests that the in-memory writeback buffer for metadata and the on-disk buffer for
metadata can both wraparound at different offsets.


Tests that the in - memory writeback buffer for metadata and the on - disk buffer for metadata can both wraparound at different offsets .
TEST_F(JournalTest, MetadataOnDiskAndInMemoryWraparoundAtDifferentOffsets) {
  storage::VmoBuffer metadata = registry()->InitializeBuffer(kJournalLength);
  const std::vector<storage::UnbufferedOperation> operations = {
      {
          zx::unowned_vmo(metadata.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 20,
              .length = 4,
          },
      },
      {
          zx::unowned_vmo(metadata.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 1234,
              .length = 4,
          },
      },
  };
  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);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        EXPECT_EQ(3, requests.size());
        verifier.VerifyJournalWrite(operations[1], requests);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        EXPECT_EQ(1, requests.size());
        verifier.VerifyMetadataWrite(operations[1], requests);
        verifier.ExtendJournalOffset(operations[1].op.length + kEntryMetadataBlocks);
        return ZX_OK;
      },
  };
  MockTransactionHandler handler(registry(), callbacks, std::size(callbacks));
  std::unique_ptr<storage::BlockingRingBuffer> journal_buffer = take_journal_buffer();
  internal::JournalWriter writer(&handler, take_info(), kJournalStartBlock,
                                 journal_buffer->capacity());
  storage::BlockingRingBufferReservation reservation;
  std::vector<storage::BufferedOperation> buffered_operations;
  uint64_t block_count = operations[0].op.length + kEntryMetadataBlocks;
  ASSERT_OK(journal_buffer->Reserve(block_count, &reservation));
  ASSERT_OK(
      reservation.CopyRequests({operations[0]}, kJournalEntryHeaderBlocks, &buffered_operations));
  auto result = writer.WriteMetadata(
      internal::JournalWorkItem(std::move(reservation), std::move(buffered_operations)));
  ASSERT_TRUE(result.is_ok());
  storage::BlockingRingBufferReservation reservation_unused;
  ASSERT_OK(journal_buffer->Reserve(3, &reservation_unused));
  block_count = operations[1].op.length + kEntryMetadataBlocks;
  ASSERT_OK(journal_buffer->Reserve(block_count, &reservation));
  ASSERT_OK(
      reservation.CopyRequests({operations[1]}, kJournalEntryHeaderBlocks, &buffered_operations));
  result = writer.WriteMetadata(
      internal::JournalWorkItem(std::move(reservation), std::move(buffered_operations)));
  ASSERT_TRUE(result.is_ok());
}
TEST_F ( JournalTest , MetadataOnDiskAndInMemoryWraparoundAtDifferentOffsets ) { storage :: VmoBuffer metadata = registry ( ) -> InitializeBuffer ( kJournalLength ) ; const std :: vector < storage :: UnbufferedOperation > operations = { { zx :: unowned_vmo ( metadata . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 20 , . length = 4 , } , } , { zx :: unowned_vmo ( metadata . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 1234 , . length = 4 , } , } , } ; 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 ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { EXPECT_EQ ( 3 , requests . size ( ) ) ; verifier . VerifyJournalWrite ( operations [ 1 ] , requests ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { EXPECT_EQ ( 1 , requests . size ( ) ) ; verifier . VerifyMetadataWrite ( operations [ 1 ] , requests ) ; verifier . ExtendJournalOffset ( operations [ 1 ] . op . length + kEntryMetadataBlocks ) ; return ZX_OK ; } , } ; MockTransactionHandler handler ( registry ( ) , callbacks , std :: size ( callbacks ) ) ; std :: unique_ptr < storage :: BlockingRingBuffer > journal_buffer = take_journal_buffer ( ) ; internal :: JournalWriter writer ( & handler , take_info ( ) , kJournalStartBlock , journal_buffer -> capacity ( ) ) ; storage :: BlockingRingBufferReservation reservation ; std :: vector < storage :: BufferedOperation > buffered_operations ; uint64_t block_count = operations [ 0 ] . op . length + kEntryMetadataBlocks ; ASSERT_OK ( journal_buffer -> Reserve ( block_count , & reservation ) ) ; ASSERT_OK ( reservation . CopyRequests ( { operations [ 0 ] } , kJournalEntryHeaderBlocks , & buffered_operations ) ) ; auto result = writer . WriteMetadata ( internal :: JournalWorkItem ( std :: move ( reservation ) , std :: move ( buffered_operations ) ) ) ; ASSERT_TRUE ( result . is_ok ( ) ) ; storage :: BlockingRingBufferReservation reservation_unused ; ASSERT_OK ( journal_buffer -> Reserve ( 3 , & reservation_unused ) ) ; block_count = operations [ 1 ] . op . length + kEntryMetadataBlocks ; ASSERT_OK ( journal_buffer -> Reserve ( block_count , & reservation ) ) ; ASSERT_OK ( reservation . CopyRequests ( { operations [ 1 ] } , kJournalEntryHeaderBlocks , & buffered_operations ) ) ; result = writer . WriteMetadata ( internal :: JournalWorkItem ( std :: move ( reservation ) , std :: move ( buffered_operations ) ) ) ; ASSERT_TRUE ( result . is_ok ( ) ) ; }
Tests that the in-memory writeback buffer for metadata and the on-disk buffer for
metadata can both wraparound at different offsets.
Tests that the in - memory writeback buffer for metadata and the on - disk buffer for metadata can both wraparound at different offsets .
// "H", then "1, 2, 3", then "4, C". // "1, 2, 3, 4" are contiguous in the in-memory buffer. // Issue the first operation, so the next operation will wrap around.