zircon/system/ulib/fs/journal/test/journal_test.cc
// Writes operations where the in-memory and on-disk representation are not aligned.
// - In-memory buffer ahead of on-disk buffer, and
// - On-disk buffer ahead of in-memory buffer.
//
// Operation 0: [ _, _, _, H, 1, C, _, _, _, _ ] (In-memory)
// Operation 0: [ H, 1, C, _, _, _, _, _, _, _ ] (On-disk)
// Operation 1: [ H, 1, C, _, _, _, _, _, _, _ ] (In-memory)
// Operation 1: [ _, _, _, H, 1, C, _, _, _, _ ] (On-disk)
Writes operations where the in-memory and on-disk representation are not aligned.
In-memory buffer ahead of on-disk buffer, and
On-disk buffer ahead of in-memory buffer.


Writes operations where the in - memory and on - disk representation are not aligned . In - memory buffer ahead of on - disk buffer and On - disk buffer ahead of in - memory buffer .
TEST_F(JournalTest, MetadataOnDiskOrderNotMatchingInMemoryOrder) {
  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 = 1234,
              .length = 1,
          },
      },
      {
          zx::unowned_vmo(metadata.vmo().get()),
          {
              storage::OperationType::kWrite,
              .vmo_offset = 0,
              .dev_offset = 4567,
              .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) {
        EXPECT_EQ(1, requests.size());
        verifier.VerifyJournalWrite(operations[0], requests);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        EXPECT_EQ(1, requests.size());
        verifier.VerifyMetadataWrite(operations[0], requests);
        verifier.ExtendJournalOffset(operations[0].op.length + kEntryMetadataBlocks);
        return ZX_OK;
      },
      [&](const std::vector<storage::BufferedOperation>& requests) {
        EXPECT_EQ(1, 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());
   This means that in-memory, operations[1] wraps around the internal buffer.
  storage::BlockingRingBufferReservation reservation0, reservation1;
  uint64_t block_count1 = operations[1].op.length + kEntryMetadataBlocks;
  ASSERT_OK(journal_buffer->Reserve(block_count1, &reservation1));
  uint64_t block_count0 = operations[0].op.length + kEntryMetadataBlocks;
  ASSERT_OK(journal_buffer->Reserve(block_count0, &reservation0));
   Actually write operations[0] before operations[1].
  std::vector<storage::BufferedOperation> buffered_operations0;
  ASSERT_OK(
      reservation0.CopyRequests({operations[0]}, kJournalEntryHeaderBlocks, &buffered_operations0));
  auto result = writer.WriteMetadata(
      internal::JournalWorkItem(std::move(reservation0), std::move(buffered_operations0)));
  ASSERT_TRUE(result.is_ok());
  std::vector<storage::BufferedOperation> buffered_operations1;
  ASSERT_OK(
      reservation1.CopyRequests({operations[1]}, kJournalEntryHeaderBlocks, &buffered_operations1));
  result = writer.WriteMetadata(
      internal::JournalWorkItem(std::move(reservation1), std::move(buffered_operations1)));
  ASSERT_TRUE(result.is_ok());
}
TEST_F ( JournalTest , MetadataOnDiskOrderNotMatchingInMemoryOrder ) { 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 = 1234 , . length = 1 , } , } , { zx :: unowned_vmo ( metadata . vmo ( ) . get ( ) ) , { storage :: OperationType :: kWrite , . vmo_offset = 0 , . dev_offset = 4567 , . 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 ) { EXPECT_EQ ( 1 , requests . size ( ) ) ; verifier . VerifyJournalWrite ( operations [ 0 ] , requests ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { EXPECT_EQ ( 1 , requests . size ( ) ) ; verifier . VerifyMetadataWrite ( operations [ 0 ] , requests ) ; verifier . ExtendJournalOffset ( operations [ 0 ] . op . length + kEntryMetadataBlocks ) ; return ZX_OK ; } , [ & ] ( const std :: vector < storage :: BufferedOperation > & requests ) { EXPECT_EQ ( 1 , 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 reservation0 , reservation1 ; uint64_t block_count1 = operations [ 1 ] . op . length + kEntryMetadataBlocks ; ASSERT_OK ( journal_buffer -> Reserve ( block_count1 , & reservation1 ) ) ; uint64_t block_count0 = operations [ 0 ] . op . length + kEntryMetadataBlocks ; ASSERT_OK ( journal_buffer -> Reserve ( block_count0 , & reservation0 ) ) ; std :: vector < storage :: BufferedOperation > buffered_operations0 ; ASSERT_OK ( reservation0 . CopyRequests ( { operations [ 0 ] } , kJournalEntryHeaderBlocks , & buffered_operations0 ) ) ; auto result = writer . WriteMetadata ( internal :: JournalWorkItem ( std :: move ( reservation0 ) , std :: move ( buffered_operations0 ) ) ) ; ASSERT_TRUE ( result . is_ok ( ) ) ; std :: vector < storage :: BufferedOperation > buffered_operations1 ; ASSERT_OK ( reservation1 . CopyRequests ( { operations [ 1 ] } , kJournalEntryHeaderBlocks , & buffered_operations1 ) ) ; result = writer . WriteMetadata ( internal :: JournalWorkItem ( std :: move ( reservation1 ) , std :: move ( buffered_operations1 ) ) ) ; ASSERT_TRUE ( result . is_ok ( ) ) ; }
Writes operations where the in-memory and on-disk representation are not aligned.
Writes operations where the in - memory and on - disk representation are not aligned .
// Reserve operations[1] in memory before operations[0]. // // This means that in-memory, operations[1] wraps around the internal buffer. // Actually write operations[0] before operations[1].