diff --git a/zircon/system/ulib/blobfs/blobfs.cpp b/zircon/system/ulib/blobfs/blobfs.cpp index b0bce191845328c0e24ff67b85966fff904348ec..7d2c99119e81ab5dbad7898be14d94f0869996ce 100644 --- a/zircon/system/ulib/blobfs/blobfs.cpp +++ b/zircon/system/ulib/blobfs/blobfs.cpp @@ -253,19 +253,20 @@ void Blobfs::WriteBitmap(WritebackWork* wb, uint64_t nblocks, uint64_t start_blo fbl::round_up(start_block + nblocks, kBlobfsBlockBits) / kBlobfsBlockBits; // Write back the block allocation bitmap - wb->Enqueue(allocator_->GetBlockMapVmo(), bbm_start_block, - BlockMapStartBlock(info_) + bbm_start_block, bbm_end_block - bbm_start_block); + wb->Transaction().Enqueue(allocator_->GetBlockMapVmo(), bbm_start_block, + BlockMapStartBlock(info_) + bbm_start_block, bbm_end_block - + bbm_start_block); } void Blobfs::WriteNode(WritebackWork* wb, uint32_t map_index) { TRACE_DURATION("blobfs", "Blobfs::WriteNode", "map_index", map_index); uint64_t b = (map_index * sizeof(Inode)) / kBlobfsBlockSize; - wb->Enqueue(allocator_->GetNodeMapVmo(), b, NodeMapStartBlock(info_) + b, 1); + wb->Transaction().Enqueue(allocator_->GetNodeMapVmo(), b, NodeMapStartBlock(info_) + b, 1); } void Blobfs::WriteInfo(WritebackWork* wb) { memcpy(info_mapping_.start(), &info_, sizeof(info_)); - wb->Enqueue(info_mapping_.vmo(), 0, 0, 1); + wb->Transaction().Enqueue(info_mapping_.vmo(), 0, 0, 1); } zx_status_t Blobfs::CreateFsId() { @@ -401,8 +402,8 @@ zx_status_t Blobfs::AddInodes(fzl::ResizeableVmoMapper* node_map) { } WriteInfo(wb.get()); - wb.get()->Enqueue(node_map->vmo(), inoblks_old, NodeMapStartBlock(info_) + inoblks_old, - inoblks - inoblks_old); + wb->Transaction().Enqueue(node_map->vmo(), inoblks_old, NodeMapStartBlock(info_) + inoblks_old, + inoblks - inoblks_old); return EnqueueWork(std::move(wb), EnqueueType::kJournal); } @@ -461,7 +462,8 @@ zx_status_t Blobfs::AddBlocks(size_t nblocks, RawBitmap* block_map) { uint64_t vmo_offset = abmblks_old; uint64_t dev_offset = BlockMapStartBlock(info_) + abmblks_old; uint64_t length = abmblks - abmblks_old; - wb.get()->Enqueue(block_map->StorageUnsafe()->GetVmo(), vmo_offset, dev_offset, length); + wb->Transaction().Enqueue(block_map->StorageUnsafe()->GetVmo(), vmo_offset, dev_offset, + length); } info_.vslice_count += length; diff --git a/zircon/system/ulib/blobfs/include/blobfs/write-txn.h b/zircon/system/ulib/blobfs/include/blobfs/write-txn.h index de59a10925ff830af50a43ed227bcec7657ebd9a..b205835234d0adbc29fcb6827d888ff230547136 100644 --- a/zircon/system/ulib/blobfs/include/blobfs/write-txn.h +++ b/zircon/system/ulib/blobfs/include/blobfs/write-txn.h @@ -68,7 +68,6 @@ public: vmoid_ = VMOID_INVALID; } -protected: // Activates the transaction. zx_status_t Flush(); diff --git a/zircon/system/ulib/blobfs/include/blobfs/writeback-work.h b/zircon/system/ulib/blobfs/include/blobfs/writeback-work.h index 84dfba45dfb0e3e2caa8d86dd308456697c445a8..f09737a163893b35612e8d54cb0f8fc4706c7552 100644 --- a/zircon/system/ulib/blobfs/include/blobfs/writeback-work.h +++ b/zircon/system/ulib/blobfs/include/blobfs/writeback-work.h @@ -19,8 +19,7 @@ namespace blobfs { // A wrapper around a WriteTxn with added support for callback invocation on completion. -class WritebackWork : public WriteTxn, - public fbl::SinglyLinkedListable<std::unique_ptr<WritebackWork>> { +class WritebackWork : public fbl::SinglyLinkedListable<std::unique_ptr<WritebackWork>> { public: using ReadyCallback = fbl::Function<bool()>; using SyncCallback = fs::Vnode::SyncCallback; @@ -55,7 +54,10 @@ public: // and resets the WritebackWork to its initial state. zx_status_t Complete(); + WriteTxn& Transaction() { return transaction_; } + private: + WriteTxn transaction_; // Optional callbacks. ReadyCallback ready_cb_; // Call to check whether work is ready to be processed. SyncCallback sync_cb_; // Call after work has been completely flushed. diff --git a/zircon/system/ulib/blobfs/journal-entry.cpp b/zircon/system/ulib/blobfs/journal-entry.cpp index fecb25d4d21dfbe7e13e2090ea028e7b14033e5f..04118bc7ed5500b1ef0cb873bb7a8042fba8e6a9 100644 --- a/zircon/system/ulib/blobfs/journal-entry.cpp +++ b/zircon/system/ulib/blobfs/journal-entry.cpp @@ -21,15 +21,15 @@ JournalEntry::JournalEntry(JournalBase* journal, EntryStatus status, size_t head return; } - size_t work_blocks = work_->BlkCount(); + size_t work_blocks = work_->Transaction().BlkCount(); // Ensure the work is valid. ZX_DEBUG_ASSERT(work_blocks > 0); - ZX_DEBUG_ASSERT(work_->IsBuffered()); + ZX_DEBUG_ASSERT(work_->Transaction().IsBuffered()); ZX_DEBUG_ASSERT(work_blocks <= kMaxEntryDataBlocks); // Copy all target blocks from the WritebackWork to the entry's header block. - for (size_t i = 0; i < work_->Requests().size(); i++) { - WriteRequest& request = work_->Requests()[i]; + for (size_t i = 0; i < work_->Transaction().Requests().size(); i++) { + WriteRequest& request = work_->Transaction().Requests()[i]; for (size_t j = request.dev_offset; j < request.dev_offset + request.length; j++) { header_block_.target_blocks[block_count_++] = j; } diff --git a/zircon/system/ulib/blobfs/journal.cpp b/zircon/system/ulib/blobfs/journal.cpp index 764ff5c12218ca2b89354a6c7589090e3c4b4dfb..468e08b21b91030e42f9cb1c6d7fa9c1fba45f8e 100644 --- a/zircon/system/ulib/blobfs/journal.cpp +++ b/zircon/system/ulib/blobfs/journal.cpp @@ -209,10 +209,10 @@ zx_status_t Journal::InitWriteback() { zx_status_t Journal::Enqueue(fbl::unique_ptr<WritebackWork> work) { // Verify that the work exists and has not already been prepared for writeback. ZX_DEBUG_ASSERT(work != nullptr); - ZX_DEBUG_ASSERT(!work->IsBuffered()); + ZX_DEBUG_ASSERT(!work->Transaction().IsBuffered()); // Block count will be the number of blocks in the transaction + header + commit. - size_t blocks = work->BlkCount(); + size_t blocks = work->Transaction().BlkCount(); // By default set the header/commit indices to the buffer capacity, // since this will be an invalid index value. size_t header_index = entries_->capacity(); @@ -249,7 +249,7 @@ zx_status_t Journal::Enqueue(fbl::unique_ptr<WritebackWork> work) { // header and commit blocks asynchronously, since this will involve calculating the // checksum. // TODO(planders): Release the lock while transaction is being copied. - entries_->CopyTransaction(work.get()); + entries_->CopyTransaction(&work->Transaction()); // Assign commit_index immediately after copying to the buffer. // Increase length_ accordingly. @@ -313,7 +313,7 @@ fbl::unique_ptr<JournalEntry> Journal::CreateEntry(uint64_t header_index, uint64 fbl::unique_ptr<WritebackWork> work) { EntryStatus status = EntryStatus::kInit; - if (work->BlkCount() == 0) { + if (work->Transaction().BlkCount() == 0) { // If the work has no transactions, this is a sync work - we can return early. // Right now we make the assumption that if a WritebackWork has any transactions, it cannot // have a corresponding sync callback. We may need to revisit this later. @@ -408,8 +408,10 @@ void Journal::PrepareDelete(JournalEntry* entry, WritebackWork* work) { memset(entries_->MutableData(commit_index), 0, kBlobfsBlockSize); // Enqueue transactions for the header/commit blocks. - entries_->AddTransaction(header_index, start_block_ + 1 + header_index, 1, work); - entries_->AddTransaction(commit_index, start_block_ + 1 + commit_index, 1, work); + entries_->AddTransaction(header_index, start_block_ + 1 + header_index, 1, + &work->Transaction()); + entries_->AddTransaction(commit_index, start_block_ + 1 + commit_index, 1, + &work->Transaction()); } fbl::unique_ptr<WritebackWork> Journal::CreateWork() { @@ -420,7 +422,7 @@ fbl::unique_ptr<WritebackWork> Journal::CreateWork() { } zx_status_t Journal::EnqueueEntryWork(fbl::unique_ptr<WritebackWork> work) { - entries_->ValidateTransaction(work.get()); + entries_->ValidateTransaction(&work->Transaction()); return transaction_manager_->EnqueueWork(std::move(work), EnqueueType::kData); } @@ -486,7 +488,7 @@ zx_status_t Journal::ReplayEntry(size_t header_index, size_t remaining_length, // Enqueue one block at a time, since they may not end up being contiguous on disk. for (unsigned i = 0; i < header->num_blocks; i++) { size_t vmo_block = (header_index + i + 1) % entries_->capacity(); - entries_->AddTransaction(vmo_block, header->target_blocks[i], 1, work.get()); + entries_->AddTransaction(vmo_block, header->target_blocks[i], 1, &work->Transaction()); } // Replay (and therefore mount) will fail if we cannot enqueue the replay work. Since the @@ -510,7 +512,7 @@ zx_status_t Journal::CommitReplay() { memset(entries_->MutableData(0), 0, kBlobfsBlockSize); fbl::unique_ptr<WritebackWork> work = CreateWork(); - entries_->AddTransaction(0, start_block_ + 1, 1, work.get()); + entries_->AddTransaction(0, start_block_ + 1, 1, &work->Transaction()); zx_status_t status; if ((status = EnqueueEntryWork(std::move(work))) != ZX_OK) { @@ -566,8 +568,8 @@ zx_status_t Journal::WriteInfo(uint64_t start, uint64_t length) { uint8_t* info_ptr = reinterpret_cast<uint8_t*>(info); info->checksum = crc32(0, info_ptr, sizeof(JournalInfo)); - info_->AddTransaction(0, start_block_, 1, work.get()); - info_->ValidateTransaction(work.get()); + info_->AddTransaction(0, start_block_, 1, &work->Transaction()); + info_->ValidateTransaction(&work->Transaction()); return transaction_manager_->EnqueueWork(std::move(work), EnqueueType::kData); } @@ -606,12 +608,12 @@ void Journal::AddEntryTransaction(size_t start, size_t length, WritebackWork* wo // Enqueue the first part of the transaction. size_t disk_start = start_block_ + 1; - entries_->AddTransaction(start, disk_start + start, first_length, work); + entries_->AddTransaction(start, disk_start + start, first_length, &work->Transaction()); // If we wrapped around to the front of the journal, // enqueue a second transaction with the remaining data + commit block. if (first_length < length) { - entries_->AddTransaction(0, disk_start, length - first_length, work); + entries_->AddTransaction(0, disk_start, length - first_length, &work->Transaction()); } } diff --git a/zircon/system/ulib/blobfs/test/journal-test.cpp b/zircon/system/ulib/blobfs/test/journal-test.cpp index 4b6e82a8a36aa53a6588894a5ed4cf1b63e2f9a9..1e48682e226dbf5a03978276bbe0fb045368f23f 100644 --- a/zircon/system/ulib/blobfs/test/journal-test.cpp +++ b/zircon/system/ulib/blobfs/test/journal-test.cpp @@ -38,8 +38,8 @@ public: zx::vmo vmo; ZX_ASSERT(zx::vmo::create(PAGE_SIZE, 0, &vmo) == ZX_OK); - work->Enqueue(vmo, 0, 0, block_count); - work->SetBuffer(2); + work->Transaction().Enqueue(vmo, 0, 0, block_count); + work->Transaction().SetBuffer(2); return work; } diff --git a/zircon/system/ulib/blobfs/writeback-queue.cpp b/zircon/system/ulib/blobfs/writeback-queue.cpp index 574d0e96cbf2850743205531a0eecefcf5e50cf3..28b1ee008030fbd9ebfd219ff4b2e68bba66b524 100644 --- a/zircon/system/ulib/blobfs/writeback-queue.cpp +++ b/zircon/system/ulib/blobfs/writeback-queue.cpp @@ -83,18 +83,18 @@ zx_status_t WritebackQueue::Enqueue(fbl::unique_ptr<WritebackWork> work) { // enqueued and ultimately processed by the WritebackThread. This will help us avoid // potential race conditions if the work callback must acquire a lock. status = ZX_ERR_BAD_STATE; - } else if (!work->IsBuffered()) { + } else if (!work->Transaction().IsBuffered()) { ZX_DEBUG_ASSERT(state_ == WritebackState::kRunning); // Only copy blocks to the buffer if they have not already been copied to another buffer. - EnsureSpaceLocked(work->BlkCount()); + EnsureSpaceLocked(work->Transaction().BlkCount()); // It is possible that the queue entered a read only state // while we were waiting to ensure space, so check again now. if (IsReadOnly()) { status = ZX_ERR_BAD_STATE; } else { - buffer_->CopyTransaction(work.get()); + buffer_->CopyTransaction(&work->Transaction()); } } @@ -143,8 +143,8 @@ int WritebackQueue::WritebackThread(void* arg) { auto work = b->work_queue_.pop(); TRACE_DURATION("blobfs", "WritebackQueue::WritebackThread", "work ptr", work.get()); - bool our_buffer = b->buffer_->VerifyTransaction(work.get()); - size_t blk_count = work->BlkCount(); + bool our_buffer = b->buffer_->VerifyTransaction(&work->Transaction()); + size_t blk_count = work->Transaction().BlkCount(); // Stay unlocked while processing a unit of work. b->lock_.Release(); @@ -155,7 +155,7 @@ int WritebackQueue::WritebackThread(void* arg) { } else { // If we should complete the work, make sure it has been buffered. // (This is not necessary if we are currently in an error state). - ZX_DEBUG_ASSERT(work->IsBuffered()); + ZX_DEBUG_ASSERT(work->Transaction().IsBuffered()); zx_status_t status; if ((status = work->Complete()) != ZX_OK) { FS_TRACE_ERROR("Work failed with status %d - " diff --git a/zircon/system/ulib/blobfs/writeback-work.cpp b/zircon/system/ulib/blobfs/writeback-work.cpp index f2365d2e015eaf051178378f442832b558c3194c..f0fc6378986f482245fb0cff50ed11ed5d1efe21 100644 --- a/zircon/system/ulib/blobfs/writeback-work.cpp +++ b/zircon/system/ulib/blobfs/writeback-work.cpp @@ -9,7 +9,7 @@ namespace blobfs { void WritebackWork::MarkCompleted(zx_status_t status) { - WriteTxn::Reset(); + transaction_.Reset(); if (sync_cb_) { sync_cb_(status); } @@ -51,12 +51,12 @@ void WritebackWork::SetSyncCallback(SyncCallback callback) { // Returns the number of blocks of the writeback buffer that have been consumed zx_status_t WritebackWork::Complete() { - zx_status_t status = Flush(); + zx_status_t status = transaction_.Flush(); MarkCompleted(status); return status; } WritebackWork::WritebackWork(TransactionManager* transaction_manager) - : WriteTxn(transaction_manager), ready_cb_(nullptr), sync_cb_(nullptr) {} + : transaction_(transaction_manager), ready_cb_(nullptr), sync_cb_(nullptr) {} } // namespace blobfs diff --git a/zircon/system/ulib/blobfs/writeback.cpp b/zircon/system/ulib/blobfs/writeback.cpp index 8ef56c7e0f27e62e4ae53d38bc07363b83390ba9..a4929ed409d7ced5cf78f933933479d734bcd9e8 100644 --- a/zircon/system/ulib/blobfs/writeback.cpp +++ b/zircon/system/ulib/blobfs/writeback.cpp @@ -15,7 +15,7 @@ zx_status_t EnqueuePaginated(fbl::unique_ptr<WritebackWork>* work, const size_t kMaxChunkBlocks = (3 * transaction_manager->WritebackCapacity()) / 4; uint64_t delta_blocks = fbl::min(nblocks, kMaxChunkBlocks); while (nblocks > 0) { - if ((*work)->BlkCount() + delta_blocks > kMaxChunkBlocks) { + if ((*work)->Transaction().BlkCount() + delta_blocks > kMaxChunkBlocks) { // If enqueueing these blocks could push us past the writeback buffer capacity // when combined with all previous writes, break this transaction into a smaller // chunk first. @@ -31,7 +31,7 @@ zx_status_t EnqueuePaginated(fbl::unique_ptr<WritebackWork>* work, *work = std::move(tmp); } - (*work)->Enqueue(vmo, relative_block, absolute_block, delta_blocks); + (*work)->Transaction().Enqueue(vmo, relative_block, absolute_block, delta_blocks); relative_block += delta_blocks; absolute_block += delta_blocks; nblocks -= delta_blocks;