1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "format.h" 6 7 namespace minfs { 8 9 // TODO(ZX-2781): Break up transactions into chunks so that journal size 10 // is not dependent on block bitmap size. 11 12 // Calculates and returns the maximum number of block bitmap blocks, based on |info_|. 13 blk_t GetBlockBitmapBlocks(const Superblock& info); 14 15 // Calculates the required number of blocks into |num_req_blocks| for a write at the given |offset| 16 // and |length|. 17 zx_status_t GetRequiredBlockCount(size_t offset, size_t length, uint32_t* num_req_blocks); 18 19 // Calculates and tracks the number of Minfs metadata / data blocks that can be modified within one 20 // transaction, as well as the corresponding Journal sizes. 21 // Once we can grow the block bitmap, we will need to be able to recalculate these limits. 22 class TransactionLimits { 23 public: 24 TransactionLimits(const Superblock& info); 25 26 // Returns the maximum number of metadata blocks that we expect to be modified in the data 27 // section within one transaction. For data vnodes, based on a max write size of 64kb, this is 28 // currently expected to be 3 indirect blocks (would be 4 with the introduction of more doubly 29 // indirect blocks). For directories, with a max dirent size of 268b, this is expected to be 5 30 // blocks. GetMaximumMetaDataBlocks()31 blk_t GetMaximumMetaDataBlocks() const { return max_meta_data_blocks_; } 32 33 // Returns the maximum number of data blocks (including indirects) that we expect to be 34 // modified within one transaction. Based on a max write size of 64kb, this is currently 35 // expected to be 9 direct blocks + 3 indirect blocks = 11 total blocks. With the addition of 36 // more doubly indirect blocks, this would increase to 4 indirect blocks for a total of 12 37 // blocks. GetMaximumDataBlocks()38 blk_t GetMaximumDataBlocks() const { return max_data_blocks_; } 39 40 // Returns the maximum number of data blocks that can be included in a journal entry, 41 // i.e. the total number of blocks that can be held in a WriteTxn enqueued to the journal. GetMaximumEntryDataBlocks()42 blk_t GetMaximumEntryDataBlocks() const { return max_entry_data_blocks_; } 43 44 // Returns the total number of blocks required for the maximum size journal entry. GetMaximumEntryBlocks()45 blk_t GetMaximumEntryBlocks() const { return max_entry_blocks_; } 46 47 // Returns the minimum number of blocks required to create a journal guaranteed large enough to 48 // hold at least a single journal entry of maximum size. GetMinimumJournalBlocks()49 blk_t GetMinimumJournalBlocks() const { return min_journal_blocks_; } 50 51 // Returns the ideal number of blocks to allocate to the journal section, provided enough space 52 // is available. GetRecommendedJournalBlocks()53 blk_t GetRecommendedJournalBlocks() const { return rec_journal_blocks_; } 54 55 // Maximum number of superblock blocks that can be modified within one transaction. 56 // Since there is only 1 superblock, there can be only 1 block updated on each transaction. 57 static constexpr blk_t kMaxSuperblockBlocks = 1; 58 59 // TODO(planders): Enforce all of the following limits. 60 // (Perhaps by tracking modified counts within the Transaction). 61 // Maximum number of inode bitmap blocks that can be modified within one transaction. 62 // A maximum of 1 inode can be created or deleted during a single transaction. 63 static constexpr blk_t kMaxInodeBitmapBlocks = 1; 64 65 // Maximum number of inode table blocks that can be modified within one transaction. 66 // No more than 2 inodes will be modified during a single transaction. 67 // (In the case of Create, the parent directory and the child inode will be modified.) 68 static constexpr blk_t kMaxInodeTableBlocks = 2; 69 70 // The largest amount of data that Write() should able to process at once. This is currently 71 // constrainted by external factors to (1 << 13), but with the switch to FIDL we expect 72 // incoming requests to be NO MORE than (1 << 16). Even so, we should update Write() to handle 73 // cases beyond this. 74 // TODO(planders): Internally break up large write requests so they fit within this constraint. 75 static constexpr size_t kMaxWriteBytes = (1 << 16); 76 77 // Number of metadata blocks required for the whole journal - 1 Superblock. 78 static constexpr blk_t kJournalMetadataBlocks = 1; 79 80 // Default number of blocks which should be allocated to the journal, if the minimum 81 // requirement does not exceed it. 82 static constexpr blk_t kDefaultJournalBlocks = 256; 83 84 private: 85 // Calculates the maximum number of data and metadata blocks that can be updated during a 86 // single transaction. 87 void CalculateDataBlocks(); 88 89 // Calculates the maximum journal entry size and the minimum size required for the journal. 90 void CalculateJournalBlocks(blk_t block_bitmap_blocks); 91 92 blk_t max_meta_data_blocks_; 93 blk_t max_data_blocks_; 94 blk_t max_entry_data_blocks_; 95 blk_t max_entry_blocks_; 96 blk_t min_journal_blocks_; 97 blk_t rec_journal_blocks_; 98 }; 99 100 } // namespace minfs