1 // Copyright 2017 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 <inttypes.h>
6
7 #include <utility>
8
9 #include "fvm-host/format.h"
10
BlobfsFormat(fbl::unique_fd fd,const char * type)11 BlobfsFormat::BlobfsFormat(fbl::unique_fd fd, const char* type)
12 : Format(), fd_(std::move(fd)) {
13 if (!strcmp(type, kBlobTypeName)) {
14 memcpy(type_, kBlobType, sizeof(kBlobType));
15 } else if (!strcmp(type, kDefaultTypeName)) {
16 memcpy(type_, kDefaultType, sizeof(kDefaultType));
17 } else {
18 fprintf(stderr, "Unrecognized type for blobfs: %s\n", type);
19 exit(-1);
20 }
21
22 if (blobfs::readblk(fd_.get(), 0, reinterpret_cast<void*>(blk_)) < 0) {
23 fprintf(stderr, "blobfs: could not read info block\n");
24 exit(-1);
25 }
26
27 if (blobfs::GetBlockCount(fd_.get(), &blocks_) != ZX_OK) {
28 fprintf(stderr, "blobfs: cannot find end of underlying device\n");
29 exit(-1);
30 } else if (blobfs::CheckSuperblock(&info_, blocks_) != ZX_OK) {
31 fprintf(stderr, "blobfs: Info check failed\n");
32 exit(-1);
33 }
34 }
35
36 BlobfsFormat::~BlobfsFormat() = default;
37
MakeFvmReady(size_t slice_size,uint32_t vpart_index)38 zx_status_t BlobfsFormat::MakeFvmReady(size_t slice_size, uint32_t vpart_index) {
39 memcpy(&fvm_blk_, &blk_, BlockSize());
40 xprintf("fvm_info has data block count %" PRIu64 "\n", fvm_info_.data_block_count);
41 fvm_info_.slice_size = slice_size;
42
43 if (fvm_info_.slice_size % BlockSize()) {
44 fprintf(stderr, "MakeFvmReady: Slice size not multiple of minfs block\n");
45 return ZX_ERR_INVALID_ARGS;
46 }
47
48 fvm_info_.abm_slices = BlocksToSlices(BlockMapBlocks(info_));
49 fvm_info_.ino_slices = BlocksToSlices(NodeMapBlocks(info_));
50 fvm_info_.journal_slices = BlocksToSlices(JournalBlocks(info_));
51 fvm_info_.dat_slices = BlocksToSlices(DataBlocks(info_));
52 fvm_info_.vslice_count = 1 + fvm_info_.abm_slices + fvm_info_.ino_slices +
53 fvm_info_.dat_slices + fvm_info_.journal_slices;
54
55 xprintf("Blobfs: slice_size is %" PRIu64 "\n", fvm_info_.slice_size);
56 xprintf("Blobfs: abm_blocks: %" PRIu64 ", abm_slices: %u\n", BlockMapBlocks(info_),
57 fvm_info_.abm_slices);
58 xprintf("Blobfs: ino_blocks: %" PRIu64 ", ino_slices: %u\n", NodeMapBlocks(info_),
59 fvm_info_.ino_slices);
60 xprintf("Blobfs: jnl_blocks: %" PRIu64 ", jnl_slices: %u\n", JournalBlocks(info_),
61 fvm_info_.journal_slices);
62 xprintf("Blobfs: dat_blocks: %" PRIu64 ", dat_slices: %u\n", DataBlocks(info_),
63 fvm_info_.dat_slices);
64
65 fvm_info_.inode_count = static_cast<uint32_t>(fvm_info_.ino_slices * fvm_info_.slice_size /
66 blobfs::kBlobfsInodeSize);
67 fvm_info_.journal_block_count = SlicesToBlocks(fvm_info_.journal_slices);
68 fvm_info_.data_block_count = SlicesToBlocks(fvm_info_.dat_slices);
69 fvm_info_.flags |= blobfs::kBlobFlagFVM;
70
71 zx_status_t status;
72 if ((status = CheckSuperblock(&fvm_info_, blocks_)) != ZX_OK) {
73 fprintf(stderr, "Check info failed\n");
74 return status;
75 }
76
77 fvm_ready_ = true;
78 vpart_index_ = vpart_index;
79 return ZX_OK;
80 }
81
GetVsliceRange(unsigned extent_index,vslice_info_t * vslice_info) const82 zx_status_t BlobfsFormat::GetVsliceRange(unsigned extent_index, vslice_info_t* vslice_info) const {
83 CheckFvmReady();
84 switch (extent_index) {
85 case 0: {
86 vslice_info->vslice_start = 0;
87 vslice_info->slice_count = 1;
88 vslice_info->block_offset = 0;
89 vslice_info->block_count = 1;
90 vslice_info->zero_fill = true;
91 return ZX_OK;
92 }
93 case 1: {
94 vslice_info->vslice_start = blobfs::kFVMBlockMapStart;
95 vslice_info->slice_count = fvm_info_.abm_slices;
96 vslice_info->block_offset = BlockMapStartBlock(info_);
97 vslice_info->block_count = BlockMapBlocks(info_);
98 vslice_info->zero_fill = true;
99 return ZX_OK;
100 }
101 case 2: {
102 vslice_info->vslice_start = blobfs::kFVMNodeMapStart;
103 vslice_info->slice_count = fvm_info_.ino_slices;
104 vslice_info->block_offset = NodeMapStartBlock(info_);
105 vslice_info->block_count = NodeMapBlocks(info_);
106 vslice_info->zero_fill = true;
107 return ZX_OK;
108 }
109 case 3: {
110 vslice_info->vslice_start = blobfs::kFVMJournalStart;
111 vslice_info->slice_count = fvm_info_.journal_slices;
112 vslice_info->block_offset = JournalStartBlock(info_);
113 vslice_info->block_count = JournalBlocks(info_);
114 vslice_info->zero_fill = false;
115 return ZX_OK;
116 }
117 case 4: {
118 vslice_info->vslice_start = blobfs::kFVMDataStart;
119 vslice_info->slice_count = fvm_info_.dat_slices;
120 vslice_info->block_offset = DataStartBlock(info_);
121 vslice_info->block_count = DataBlocks(info_);
122 vslice_info->zero_fill = false;
123 return ZX_OK;
124 }
125 }
126
127 return ZX_ERR_OUT_OF_RANGE;
128 }
129
GetSliceCount(uint32_t * slices_out) const130 zx_status_t BlobfsFormat::GetSliceCount(uint32_t* slices_out) const {
131 CheckFvmReady();
132 *slices_out = 1 + fvm_info_.abm_slices + fvm_info_.ino_slices + fvm_info_.journal_slices
133 + fvm_info_.dat_slices;
134 return ZX_OK;
135 }
136
FillBlock(size_t block_offset)137 zx_status_t BlobfsFormat::FillBlock(size_t block_offset) {
138 CheckFvmReady();
139 // If we are reading the super block, make sure it is the fvm version and not the original
140 if (block_offset == 0) {
141 memcpy(datablk, fvm_blk_, BlockSize());
142 } else if (blobfs::readblk(fd_.get(), block_offset, datablk) != ZX_OK) {
143 fprintf(stderr, "blobfs: could not read block\n");
144 return ZX_ERR_INTERNAL;
145 }
146 return ZX_OK;
147 }
148
EmptyBlock()149 zx_status_t BlobfsFormat::EmptyBlock() {
150 CheckFvmReady();
151 memset(datablk, 0, BlockSize());
152 return ZX_OK;
153 }
154
Data()155 void* BlobfsFormat::Data() {
156 return datablk;
157 }
158
Name() const159 const char* BlobfsFormat::Name() const {
160 return kBlobfsName;
161 }
162
BlockSize() const163 uint32_t BlobfsFormat::BlockSize() const {
164 return blobfs::kBlobfsBlockSize;
165 }
166
BlocksPerSlice() const167 uint32_t BlobfsFormat::BlocksPerSlice() const {
168 CheckFvmReady();
169 return fvm_info_.slice_size / BlockSize();
170 }
171
BlocksToSlices(uint32_t block_count) const172 uint32_t BlobfsFormat::BlocksToSlices(uint32_t block_count) const {
173 return fvm::BlocksToSlices(fvm_info_.slice_size, BlockSize(), block_count);
174 }
175
SlicesToBlocks(uint32_t slice_count) const176 uint32_t BlobfsFormat::SlicesToBlocks(uint32_t slice_count) const {
177 return fvm::SlicesToBlocks(fvm_info_.slice_size, BlockSize(), slice_count);
178 }
179