• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "liblp/builder.h"
18 
19 #include <string.h>
20 
21 #include <algorithm>
22 
23 #include <android-base/properties.h>
24 #include <android-base/unique_fd.h>
25 
26 #include "liblp/liblp.h"
27 #include "reader.h"
28 #include "utility.h"
29 
30 namespace android {
31 namespace fs_mgr {
32 
33 bool MetadataBuilder::sABOverrideSet;
34 bool MetadataBuilder::sABOverrideValue;
35 
36 static const std::string kDefaultGroup = "default";
37 
AddTo(LpMetadata * out) const38 bool LinearExtent::AddTo(LpMetadata* out) const {
39     if (device_index_ >= out->block_devices.size()) {
40         LERROR << "Extent references unknown block device.";
41         return false;
42     }
43     out->extents.emplace_back(
44             LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_LINEAR, physical_sector_, device_index_});
45     return true;
46 }
47 
AddTo(LpMetadata * out) const48 bool ZeroExtent::AddTo(LpMetadata* out) const {
49     out->extents.emplace_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_ZERO, 0, 0});
50     return true;
51 }
52 
Partition(const std::string & name,const std::string & group_name,uint32_t attributes)53 Partition::Partition(const std::string& name, const std::string& group_name, uint32_t attributes)
54     : name_(name), group_name_(group_name), attributes_(attributes), size_(0) {}
55 
AddExtent(std::unique_ptr<Extent> && extent)56 void Partition::AddExtent(std::unique_ptr<Extent>&& extent) {
57     size_ += extent->num_sectors() * LP_SECTOR_SIZE;
58 
59     if (LinearExtent* new_extent = extent->AsLinearExtent()) {
60         if (!extents_.empty() && extents_.back()->AsLinearExtent()) {
61             LinearExtent* prev_extent = extents_.back()->AsLinearExtent();
62             if (prev_extent->end_sector() == new_extent->physical_sector() &&
63                 prev_extent->device_index() == new_extent->device_index()) {
64                 // If the previous extent can be merged into this new one, do so
65                 // to avoid creating unnecessary extents.
66                 extent = std::make_unique<LinearExtent>(
67                         prev_extent->num_sectors() + new_extent->num_sectors(),
68                         prev_extent->device_index(), prev_extent->physical_sector());
69                 extents_.pop_back();
70             }
71         }
72     }
73     extents_.push_back(std::move(extent));
74 }
75 
RemoveExtents()76 void Partition::RemoveExtents() {
77     size_ = 0;
78     extents_.clear();
79 }
80 
ShrinkTo(uint64_t aligned_size)81 void Partition::ShrinkTo(uint64_t aligned_size) {
82     if (aligned_size == 0) {
83         RemoveExtents();
84         return;
85     }
86 
87     // Remove or shrink extents of any kind until the total partition size is
88     // equal to the requested size.
89     uint64_t sectors_to_remove = (size_ - aligned_size) / LP_SECTOR_SIZE;
90     while (sectors_to_remove) {
91         Extent* extent = extents_.back().get();
92         if (extent->num_sectors() > sectors_to_remove) {
93             size_ -= sectors_to_remove * LP_SECTOR_SIZE;
94             extent->set_num_sectors(extent->num_sectors() - sectors_to_remove);
95             break;
96         }
97         size_ -= (extent->num_sectors() * LP_SECTOR_SIZE);
98         sectors_to_remove -= extent->num_sectors();
99         extents_.pop_back();
100     }
101     DCHECK(size_ == aligned_size);
102 }
103 
BytesOnDisk() const104 uint64_t Partition::BytesOnDisk() const {
105     uint64_t sectors = 0;
106     for (const auto& extent : extents_) {
107         if (!extent->AsLinearExtent()) {
108             continue;
109         }
110         sectors += extent->num_sectors();
111     }
112     return sectors * LP_SECTOR_SIZE;
113 }
114 
New(const IPartitionOpener & opener,const std::string & super_partition,uint32_t slot_number)115 std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const IPartitionOpener& opener,
116                                                       const std::string& super_partition,
117                                                       uint32_t slot_number) {
118     std::unique_ptr<LpMetadata> metadata = ReadMetadata(opener, super_partition, slot_number);
119     if (!metadata) {
120         return nullptr;
121     }
122     return New(*metadata.get(), &opener);
123 }
124 
New(const std::string & super_partition,uint32_t slot_number)125 std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& super_partition,
126                                                       uint32_t slot_number) {
127     return New(PartitionOpener(), super_partition, slot_number);
128 }
129 
New(const std::vector<BlockDeviceInfo> & block_devices,const std::string & super_partition,uint32_t metadata_max_size,uint32_t metadata_slot_count)130 std::unique_ptr<MetadataBuilder> MetadataBuilder::New(
131         const std::vector<BlockDeviceInfo>& block_devices, const std::string& super_partition,
132         uint32_t metadata_max_size, uint32_t metadata_slot_count) {
133     std::unique_ptr<MetadataBuilder> builder(new MetadataBuilder());
134     if (!builder->Init(block_devices, super_partition, metadata_max_size, metadata_slot_count)) {
135         return nullptr;
136     }
137     return builder;
138 }
139 
New(const LpMetadata & metadata,const IPartitionOpener * opener)140 std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const LpMetadata& metadata,
141                                                       const IPartitionOpener* opener) {
142     std::unique_ptr<MetadataBuilder> builder(new MetadataBuilder());
143     if (!builder->Init(metadata)) {
144         return nullptr;
145     }
146     if (opener) {
147         for (size_t i = 0; i < builder->block_devices_.size(); i++) {
148             std::string partition_name = GetBlockDevicePartitionName(builder->block_devices_[i]);
149             BlockDeviceInfo device_info;
150             if (opener->GetInfo(partition_name, &device_info)) {
151                 builder->UpdateBlockDeviceInfo(i, device_info);
152             }
153         }
154     }
155     return builder;
156 }
157 
NewForUpdate(const IPartitionOpener & opener,const std::string & source_partition,uint32_t source_slot_number,uint32_t target_slot_number)158 std::unique_ptr<MetadataBuilder> MetadataBuilder::NewForUpdate(const IPartitionOpener& opener,
159                                                                const std::string& source_partition,
160                                                                uint32_t source_slot_number,
161                                                                uint32_t target_slot_number) {
162     auto metadata = ReadMetadata(opener, source_partition, source_slot_number);
163     if (!metadata) {
164         return nullptr;
165     }
166 
167     // On non-retrofit devices there is only one location for metadata: the
168     // super partition. update_engine will remove and resize partitions as
169     // needed. On the other hand, for retrofit devices, we'll need to
170     // translate block device and group names to update their slot suffixes.
171     auto super_device = GetMetadataSuperBlockDevice(*metadata.get());
172     if (GetBlockDevicePartitionName(*super_device) == "super") {
173         return New(*metadata.get(), &opener);
174     }
175 
176     // Clear partitions and extents, since they have no meaning on the target
177     // slot. We also clear groups since they are re-added during OTA.
178     metadata->partitions.clear();
179     metadata->extents.clear();
180     metadata->groups.clear();
181 
182     std::string source_slot_suffix = SlotSuffixForSlotNumber(source_slot_number);
183     std::string target_slot_suffix = SlotSuffixForSlotNumber(target_slot_number);
184 
185     // Translate block devices.
186     auto source_block_devices = std::move(metadata->block_devices);
187     for (const auto& source_block_device : source_block_devices) {
188         std::string partition_name = GetBlockDevicePartitionName(source_block_device);
189         std::string slot_suffix = GetPartitionSlotSuffix(partition_name);
190         if (slot_suffix.empty() || slot_suffix != source_slot_suffix) {
191             // This should never happen. It means that the source metadata
192             // refers to a target or unknown block device.
193             LERROR << "Invalid block device for slot " << source_slot_suffix << ": "
194                    << partition_name;
195             return nullptr;
196         }
197         std::string new_name =
198                 partition_name.substr(0, partition_name.size() - slot_suffix.size()) +
199                 target_slot_suffix;
200 
201         auto new_device = source_block_device;
202         if (!UpdateBlockDevicePartitionName(&new_device, new_name)) {
203             LERROR << "Partition name too long: " << new_name;
204             return nullptr;
205         }
206         metadata->block_devices.emplace_back(new_device);
207     }
208 
209     return New(*metadata.get(), &opener);
210 }
211 
OverrideABForTesting(bool ab_device)212 void MetadataBuilder::OverrideABForTesting(bool ab_device) {
213     sABOverrideSet = true;
214     sABOverrideValue = ab_device;
215 }
216 
MetadataBuilder()217 MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false), ignore_slot_suffixing_(false) {
218     memset(&geometry_, 0, sizeof(geometry_));
219     geometry_.magic = LP_METADATA_GEOMETRY_MAGIC;
220     geometry_.struct_size = sizeof(geometry_);
221 
222     memset(&header_, 0, sizeof(header_));
223     header_.magic = LP_METADATA_HEADER_MAGIC;
224     header_.major_version = LP_METADATA_MAJOR_VERSION;
225     header_.minor_version = LP_METADATA_MINOR_VERSION;
226     header_.header_size = sizeof(header_);
227     header_.partitions.entry_size = sizeof(LpMetadataPartition);
228     header_.extents.entry_size = sizeof(LpMetadataExtent);
229     header_.groups.entry_size = sizeof(LpMetadataPartitionGroup);
230     header_.block_devices.entry_size = sizeof(LpMetadataBlockDevice);
231 }
232 
Init(const LpMetadata & metadata)233 bool MetadataBuilder::Init(const LpMetadata& metadata) {
234     geometry_ = metadata.geometry;
235     block_devices_ = metadata.block_devices;
236 
237     for (const auto& group : metadata.groups) {
238         std::string group_name = GetPartitionGroupName(group);
239         if (!AddGroup(group_name, group.maximum_size)) {
240             return false;
241         }
242     }
243 
244     for (const auto& partition : metadata.partitions) {
245         std::string group_name = GetPartitionGroupName(metadata.groups[partition.group_index]);
246         Partition* builder =
247                 AddPartition(GetPartitionName(partition), group_name, partition.attributes);
248         if (!builder) {
249             return false;
250         }
251         ImportExtents(builder, metadata, partition);
252     }
253     return true;
254 }
255 
ImportExtents(Partition * dest,const LpMetadata & metadata,const LpMetadataPartition & source)256 void MetadataBuilder::ImportExtents(Partition* dest, const LpMetadata& metadata,
257                                     const LpMetadataPartition& source) {
258     for (size_t i = 0; i < source.num_extents; i++) {
259         const LpMetadataExtent& extent = metadata.extents[source.first_extent_index + i];
260         if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
261             auto copy = std::make_unique<LinearExtent>(extent.num_sectors, extent.target_source,
262                                                        extent.target_data);
263             dest->AddExtent(std::move(copy));
264         } else if (extent.target_type == LP_TARGET_TYPE_ZERO) {
265             auto copy = std::make_unique<ZeroExtent>(extent.num_sectors);
266             dest->AddExtent(std::move(copy));
267         }
268     }
269 }
270 
VerifyDeviceProperties(const BlockDeviceInfo & device_info)271 static bool VerifyDeviceProperties(const BlockDeviceInfo& device_info) {
272     if (device_info.logical_block_size == 0) {
273         LERROR << "Block device " << device_info.partition_name
274                << " logical block size must not be zero.";
275         return false;
276     }
277     if (device_info.logical_block_size % LP_SECTOR_SIZE != 0) {
278         LERROR << "Block device " << device_info.partition_name
279                << " logical block size must be a multiple of 512.";
280         return false;
281     }
282     if (device_info.size % device_info.logical_block_size != 0) {
283         LERROR << "Block device " << device_info.partition_name
284                << " size must be a multiple of its block size.";
285         return false;
286     }
287     if (device_info.alignment_offset % LP_SECTOR_SIZE != 0) {
288         LERROR << "Block device " << device_info.partition_name
289                << " alignment offset is not sector-aligned.";
290         return false;
291     }
292     if (device_info.alignment % LP_SECTOR_SIZE != 0) {
293         LERROR << "Block device " << device_info.partition_name
294                << " partition alignment is not sector-aligned.";
295         return false;
296     }
297     if (device_info.alignment_offset > device_info.alignment) {
298         LERROR << "Block device " << device_info.partition_name
299                << " partition alignment offset is greater than its alignment.";
300         return false;
301     }
302     return true;
303 }
304 
Init(const std::vector<BlockDeviceInfo> & block_devices,const std::string & super_partition,uint32_t metadata_max_size,uint32_t metadata_slot_count)305 bool MetadataBuilder::Init(const std::vector<BlockDeviceInfo>& block_devices,
306                            const std::string& super_partition, uint32_t metadata_max_size,
307                            uint32_t metadata_slot_count) {
308     if (metadata_max_size < sizeof(LpMetadataHeader)) {
309         LERROR << "Invalid metadata maximum size.";
310         return false;
311     }
312     if (metadata_slot_count == 0) {
313         LERROR << "Invalid metadata slot count.";
314         return false;
315     }
316     if (block_devices.empty()) {
317         LERROR << "No block devices were specified.";
318         return false;
319     }
320 
321     // Align the metadata size up to the nearest sector.
322     metadata_max_size = AlignTo(metadata_max_size, LP_SECTOR_SIZE);
323 
324     // Validate and build the block device list.
325     uint32_t logical_block_size = 0;
326     for (const auto& device_info : block_devices) {
327         if (!VerifyDeviceProperties(device_info)) {
328             return false;
329         }
330 
331         if (!logical_block_size) {
332             logical_block_size = device_info.logical_block_size;
333         }
334         if (logical_block_size != device_info.logical_block_size) {
335             LERROR << "All partitions must have the same logical block size.";
336             return false;
337         }
338 
339         LpMetadataBlockDevice out = {};
340         out.alignment = device_info.alignment;
341         out.alignment_offset = device_info.alignment_offset;
342         out.size = device_info.size;
343         if (device_info.partition_name.size() > sizeof(out.partition_name)) {
344             LERROR << "Partition name " << device_info.partition_name << " exceeds maximum length.";
345             return false;
346         }
347         strncpy(out.partition_name, device_info.partition_name.c_str(), sizeof(out.partition_name));
348 
349         // In the case of the super partition, this field will be adjusted
350         // later. For all partitions, the first 512 bytes are considered
351         // untouched to be compatible code that looks for an MBR. Thus we
352         // start counting free sectors at sector 1, not 0.
353         uint64_t free_area_start = LP_SECTOR_SIZE;
354         if (out.alignment || out.alignment_offset) {
355             free_area_start = AlignTo(free_area_start, out.alignment, out.alignment_offset);
356         } else {
357             free_area_start = AlignTo(free_area_start, logical_block_size);
358         }
359         out.first_logical_sector = free_area_start / LP_SECTOR_SIZE;
360 
361         // There must be one logical block of space available.
362         uint64_t minimum_size = out.first_logical_sector * LP_SECTOR_SIZE + logical_block_size;
363         if (device_info.size < minimum_size) {
364             LERROR << "Block device " << device_info.partition_name
365                    << " is too small to hold any logical partitions.";
366             return false;
367         }
368 
369         // The "root" of the super partition is always listed first.
370         if (device_info.partition_name == super_partition) {
371             block_devices_.emplace(block_devices_.begin(), out);
372         } else {
373             block_devices_.emplace_back(out);
374         }
375     }
376     if (GetBlockDevicePartitionName(block_devices_[0]) != super_partition) {
377         LERROR << "No super partition was specified.";
378         return false;
379     }
380 
381     LpMetadataBlockDevice& super = block_devices_[0];
382 
383     // We reserve a geometry block (4KB) plus space for each copy of the
384     // maximum size of a metadata blob. Then, we double that space since
385     // we store a backup copy of everything.
386     uint64_t total_reserved = GetTotalMetadataSize(metadata_max_size, metadata_slot_count);
387     if (super.size < total_reserved) {
388         LERROR << "Attempting to create metadata on a block device that is too small.";
389         return false;
390     }
391 
392     // Compute the first free sector, factoring in alignment.
393     uint64_t free_area_start = total_reserved;
394     if (super.alignment || super.alignment_offset) {
395         free_area_start = AlignTo(free_area_start, super.alignment, super.alignment_offset);
396     } else {
397         free_area_start = AlignTo(free_area_start, logical_block_size);
398     }
399     super.first_logical_sector = free_area_start / LP_SECTOR_SIZE;
400 
401     // There must be one logical block of free space remaining (enough for one partition).
402     uint64_t minimum_disk_size = (super.first_logical_sector * LP_SECTOR_SIZE) + logical_block_size;
403     if (super.size < minimum_disk_size) {
404         LERROR << "Device must be at least " << minimum_disk_size << " bytes, only has "
405                << super.size;
406         return false;
407     }
408 
409     geometry_.metadata_max_size = metadata_max_size;
410     geometry_.metadata_slot_count = metadata_slot_count;
411     geometry_.logical_block_size = logical_block_size;
412 
413     if (!AddGroup(kDefaultGroup, 0)) {
414         return false;
415     }
416     return true;
417 }
418 
AddGroup(const std::string & group_name,uint64_t maximum_size)419 bool MetadataBuilder::AddGroup(const std::string& group_name, uint64_t maximum_size) {
420     if (FindGroup(group_name)) {
421         LERROR << "Group already exists: " << group_name;
422         return false;
423     }
424     groups_.push_back(std::make_unique<PartitionGroup>(group_name, maximum_size));
425     return true;
426 }
427 
AddPartition(const std::string & name,uint32_t attributes)428 Partition* MetadataBuilder::AddPartition(const std::string& name, uint32_t attributes) {
429     return AddPartition(name, kDefaultGroup, attributes);
430 }
431 
AddPartition(const std::string & name,const std::string & group_name,uint32_t attributes)432 Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& group_name,
433                                          uint32_t attributes) {
434     if (name.empty()) {
435         LERROR << "Partition must have a non-empty name.";
436         return nullptr;
437     }
438     if (FindPartition(name)) {
439         LERROR << "Attempting to create duplication partition with name: " << name;
440         return nullptr;
441     }
442     if (!FindGroup(group_name)) {
443         LERROR << "Could not find partition group: " << group_name;
444         return nullptr;
445     }
446     if (IsABDevice() && !auto_slot_suffixing_ && name != "scratch" && !ignore_slot_suffixing_ &&
447         GetPartitionSlotSuffix(name).empty()) {
448         LERROR << "Unsuffixed partition not allowed on A/B device: " << name;
449         return nullptr;
450     }
451     partitions_.push_back(std::make_unique<Partition>(name, group_name, attributes));
452     return partitions_.back().get();
453 }
454 
FindPartition(const std::string & name)455 Partition* MetadataBuilder::FindPartition(const std::string& name) {
456     for (const auto& partition : partitions_) {
457         if (partition->name() == name) {
458             return partition.get();
459         }
460     }
461     return nullptr;
462 }
463 
FindGroup(const std::string & group_name)464 PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) {
465     for (const auto& group : groups_) {
466         if (group->name() == group_name) {
467             return group.get();
468         }
469     }
470     return nullptr;
471 }
472 
TotalSizeOfGroup(PartitionGroup * group) const473 uint64_t MetadataBuilder::TotalSizeOfGroup(PartitionGroup* group) const {
474     uint64_t total = 0;
475     for (const auto& partition : partitions_) {
476         if (partition->group_name() != group->name()) {
477             continue;
478         }
479         total += partition->BytesOnDisk();
480     }
481     return total;
482 }
483 
RemovePartition(const std::string & name)484 void MetadataBuilder::RemovePartition(const std::string& name) {
485     for (auto iter = partitions_.begin(); iter != partitions_.end(); iter++) {
486         if ((*iter)->name() == name) {
487             partitions_.erase(iter);
488             return;
489         }
490     }
491 }
492 
ExtentsToFreeList(const std::vector<Interval> & extents,std::vector<Interval> * free_regions) const493 void MetadataBuilder::ExtentsToFreeList(const std::vector<Interval>& extents,
494                                         std::vector<Interval>* free_regions) const {
495     // Convert the extent list into a list of gaps between the extents; i.e.,
496     // the list of ranges that are free on the disk.
497     for (size_t i = 1; i < extents.size(); i++) {
498         const Interval& previous = extents[i - 1];
499         const Interval& current = extents[i];
500         DCHECK(previous.device_index == current.device_index);
501 
502         uint64_t aligned = AlignSector(block_devices_[current.device_index], previous.end);
503         if (aligned >= current.start) {
504             // There is no gap between these two extents, try the next one.
505             // Note that we check with >= instead of >, since alignment may
506             // bump the ending sector past the beginning of the next extent.
507             continue;
508         }
509 
510         // The new interval represents the free space starting at the end of
511         // the previous interval, and ending at the start of the next interval.
512         free_regions->emplace_back(current.device_index, aligned, current.start);
513     }
514 }
515 
GetFreeRegions() const516 auto MetadataBuilder::GetFreeRegions() const -> std::vector<Interval> {
517     std::vector<Interval> free_regions;
518 
519     // Collect all extents in the partition table, per-device, then sort them
520     // by starting sector.
521     std::vector<std::vector<Interval>> device_extents(block_devices_.size());
522     for (const auto& partition : partitions_) {
523         for (const auto& extent : partition->extents()) {
524             LinearExtent* linear = extent->AsLinearExtent();
525             if (!linear) {
526                 continue;
527             }
528             CHECK(linear->device_index() < device_extents.size());
529             auto& extents = device_extents[linear->device_index()];
530             extents.emplace_back(linear->device_index(), linear->physical_sector(),
531                                  linear->physical_sector() + extent->num_sectors());
532         }
533     }
534 
535     // Add 0-length intervals for the first and last sectors. This will cause
536     // ExtentToFreeList() to treat the space in between as available.
537     for (size_t i = 0; i < device_extents.size(); i++) {
538         auto& extents = device_extents[i];
539         const auto& block_device = block_devices_[i];
540 
541         uint64_t first_sector = block_device.first_logical_sector;
542         uint64_t last_sector = block_device.size / LP_SECTOR_SIZE;
543         extents.emplace_back(i, first_sector, first_sector);
544         extents.emplace_back(i, last_sector, last_sector);
545 
546         std::sort(extents.begin(), extents.end());
547         ExtentsToFreeList(extents, &free_regions);
548     }
549     return free_regions;
550 }
551 
ValidatePartitionSizeChange(Partition * partition,uint64_t old_size,uint64_t new_size,bool force_check)552 bool MetadataBuilder::ValidatePartitionSizeChange(Partition* partition, uint64_t old_size,
553                                                   uint64_t new_size, bool force_check) {
554     PartitionGroup* group = FindGroup(partition->group_name());
555     CHECK(group);
556 
557     if (!force_check && new_size <= old_size) {
558         return true;
559     }
560 
561     // Figure out how much we need to allocate, and whether our group has
562     // enough space remaining.
563     uint64_t space_needed = new_size - old_size;
564     if (group->maximum_size() > 0) {
565         uint64_t group_size = TotalSizeOfGroup(group);
566         if (group_size >= group->maximum_size() ||
567             group->maximum_size() - group_size < space_needed) {
568             LERROR << "Partition " << partition->name() << " is part of group " << group->name()
569                    << " which does not have enough space free (" << space_needed << " requested, "
570                    << group_size << " used out of " << group->maximum_size() << ")";
571             return false;
572         }
573     }
574     return true;
575 }
576 
GrowPartition(Partition * partition,uint64_t aligned_size)577 bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) {
578     uint64_t space_needed = aligned_size - partition->size();
579     uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE;
580     DCHECK(sectors_needed * LP_SECTOR_SIZE == space_needed);
581 
582     std::vector<Interval> free_regions = GetFreeRegions();
583 
584     const uint64_t sectors_per_block = geometry_.logical_block_size / LP_SECTOR_SIZE;
585     CHECK_NE(sectors_per_block, 0);
586     CHECK(sectors_needed % sectors_per_block == 0);
587 
588     if (IsABDevice() && !IsRetrofitDevice() && GetPartitionSlotSuffix(partition->name()) == "_b") {
589         // Allocate "a" partitions top-down and "b" partitions bottom-up, to
590         // minimize fragmentation during OTA.
591         free_regions = PrioritizeSecondHalfOfSuper(free_regions);
592     }
593 
594     // Note we store new extents in a temporary vector, and only commit them
595     // if we are guaranteed enough free space.
596     std::vector<std::unique_ptr<LinearExtent>> new_extents;
597 
598     // If the last extent in the partition has a size < alignment, then the
599     // difference is unallocatable due to being misaligned. We peek for that
600     // case here to avoid wasting space.
601     if (auto extent = ExtendFinalExtent(partition, free_regions, sectors_needed)) {
602         sectors_needed -= extent->num_sectors();
603         new_extents.emplace_back(std::move(extent));
604     }
605 
606     for (auto& region : free_regions) {
607         // Note: this comes first, since we may enter the loop not needing any
608         // more sectors.
609         if (!sectors_needed) {
610             break;
611         }
612 
613         if (region.length() % sectors_per_block != 0) {
614             // This should never happen, because it would imply that we
615             // once allocated an extent that was not a multiple of the
616             // block size. That extent would be rejected by DM_TABLE_LOAD.
617             LERROR << "Region " << region.start << ".." << region.end
618                    << " is not a multiple of the block size, " << sectors_per_block;
619 
620             // If for some reason the final region is mis-sized we still want
621             // to be able to grow partitions. So just to be safe, round the
622             // region down to the nearest block.
623             region.end = region.start + (region.length() / sectors_per_block) * sectors_per_block;
624             if (!region.length()) {
625                 continue;
626             }
627         }
628 
629         uint64_t sectors = std::min(sectors_needed, region.length());
630         CHECK(sectors % sectors_per_block == 0);
631 
632         auto extent = std::make_unique<LinearExtent>(sectors, region.device_index, region.start);
633         new_extents.push_back(std::move(extent));
634         sectors_needed -= sectors;
635     }
636     if (sectors_needed) {
637         LERROR << "Not enough free space to expand partition: " << partition->name();
638         return false;
639     }
640 
641     // Everything succeeded, so commit the new extents.
642     for (auto& extent : new_extents) {
643         partition->AddExtent(std::move(extent));
644     }
645     return true;
646 }
647 
PrioritizeSecondHalfOfSuper(const std::vector<Interval> & free_list)648 std::vector<MetadataBuilder::Interval> MetadataBuilder::PrioritizeSecondHalfOfSuper(
649         const std::vector<Interval>& free_list) {
650     const auto& super = block_devices_[0];
651     uint64_t first_sector = super.first_logical_sector;
652     uint64_t last_sector = super.size / LP_SECTOR_SIZE;
653     uint64_t midpoint = first_sector + (last_sector - first_sector) / 2;
654 
655     // Choose an aligned sector for the midpoint. This could lead to one half
656     // being slightly larger than the other, but this will not restrict the
657     // size of partitions (it might lead to one extra extent if "B" overflows).
658     midpoint = AlignSector(super, midpoint);
659 
660     std::vector<Interval> first_half;
661     std::vector<Interval> second_half;
662     for (const auto& region : free_list) {
663         // Note: deprioritze if not the main super partition. Even though we
664         // don't call this for retrofit devices, we will allow adding additional
665         // block devices on non-retrofit devices.
666         if (region.device_index != 0 || region.end <= midpoint) {
667             first_half.emplace_back(region);
668             continue;
669         }
670         if (region.start < midpoint && region.end > midpoint) {
671             // Split this into two regions.
672             first_half.emplace_back(region.device_index, region.start, midpoint);
673             second_half.emplace_back(region.device_index, midpoint, region.end);
674         } else {
675             second_half.emplace_back(region);
676         }
677     }
678     second_half.insert(second_half.end(), first_half.begin(), first_half.end());
679     return second_half;
680 }
681 
ExtendFinalExtent(Partition * partition,const std::vector<Interval> & free_list,uint64_t sectors_needed) const682 std::unique_ptr<LinearExtent> MetadataBuilder::ExtendFinalExtent(
683         Partition* partition, const std::vector<Interval>& free_list,
684         uint64_t sectors_needed) const {
685     if (partition->extents().empty()) {
686         return nullptr;
687     }
688     LinearExtent* extent = partition->extents().back()->AsLinearExtent();
689     if (!extent) {
690         return nullptr;
691     }
692 
693     // If the sector ends where the next aligned chunk begins, then there's
694     // no missing gap to try and allocate.
695     const auto& block_device = block_devices_[extent->device_index()];
696     uint64_t next_aligned_sector = AlignSector(block_device, extent->end_sector());
697     if (extent->end_sector() == next_aligned_sector) {
698         return nullptr;
699     }
700 
701     uint64_t num_sectors = std::min(next_aligned_sector - extent->end_sector(), sectors_needed);
702     auto new_extent = std::make_unique<LinearExtent>(num_sectors, extent->device_index(),
703                                                      extent->end_sector());
704     if (IsAnyRegionAllocated(*new_extent.get()) ||
705         IsAnyRegionCovered(free_list, *new_extent.get())) {
706         LERROR << "Misaligned region " << new_extent->physical_sector() << ".."
707                << new_extent->end_sector() << " was allocated or marked allocatable.";
708         return nullptr;
709     }
710     return new_extent;
711 }
712 
IsAnyRegionCovered(const std::vector<Interval> & regions,const LinearExtent & candidate) const713 bool MetadataBuilder::IsAnyRegionCovered(const std::vector<Interval>& regions,
714                                          const LinearExtent& candidate) const {
715     for (const auto& region : regions) {
716         if (region.device_index == candidate.device_index() &&
717             (candidate.OwnsSector(region.start) || candidate.OwnsSector(region.end))) {
718             return true;
719         }
720     }
721     return false;
722 }
723 
IsAnyRegionAllocated(const LinearExtent & candidate) const724 bool MetadataBuilder::IsAnyRegionAllocated(const LinearExtent& candidate) const {
725     for (const auto& partition : partitions_) {
726         for (const auto& extent : partition->extents()) {
727             LinearExtent* linear = extent->AsLinearExtent();
728             if (!linear || linear->device_index() != candidate.device_index()) {
729                 continue;
730             }
731             if (linear->OwnsSector(candidate.physical_sector()) ||
732                 linear->OwnsSector(candidate.end_sector() - 1)) {
733                 return true;
734             }
735         }
736     }
737     return false;
738 }
739 
ShrinkPartition(Partition * partition,uint64_t aligned_size)740 void MetadataBuilder::ShrinkPartition(Partition* partition, uint64_t aligned_size) {
741     partition->ShrinkTo(aligned_size);
742 }
743 
Export()744 std::unique_ptr<LpMetadata> MetadataBuilder::Export() {
745     if (!ValidatePartitionGroups()) {
746         return nullptr;
747     }
748 
749     std::unique_ptr<LpMetadata> metadata = std::make_unique<LpMetadata>();
750     metadata->header = header_;
751     metadata->geometry = geometry_;
752 
753     // Assign this early so the extent table can read it.
754     for (const auto& block_device : block_devices_) {
755         metadata->block_devices.emplace_back(block_device);
756         if (auto_slot_suffixing_) {
757             metadata->block_devices.back().flags |= LP_BLOCK_DEVICE_SLOT_SUFFIXED;
758         }
759     }
760 
761     std::map<std::string, size_t> group_indices;
762     for (const auto& group : groups_) {
763         LpMetadataPartitionGroup out = {};
764 
765         if (group->name().size() > sizeof(out.name)) {
766             LERROR << "Partition group name is too long: " << group->name();
767             return nullptr;
768         }
769         if (auto_slot_suffixing_ && group->name() != kDefaultGroup) {
770             out.flags |= LP_GROUP_SLOT_SUFFIXED;
771         }
772         strncpy(out.name, group->name().c_str(), sizeof(out.name));
773         out.maximum_size = group->maximum_size();
774 
775         group_indices[group->name()] = metadata->groups.size();
776         metadata->groups.push_back(out);
777     }
778 
779     // Flatten the partition and extent structures into an LpMetadata, which
780     // makes it very easy to validate, serialize, or pass on to device-mapper.
781     for (const auto& partition : partitions_) {
782         LpMetadataPartition part;
783         memset(&part, 0, sizeof(part));
784 
785         if (partition->name().size() > sizeof(part.name)) {
786             LERROR << "Partition name is too long: " << partition->name();
787             return nullptr;
788         }
789         if (partition->attributes() & ~(LP_PARTITION_ATTRIBUTE_MASK)) {
790             LERROR << "Partition " << partition->name() << " has unsupported attribute.";
791             return nullptr;
792         }
793 
794         strncpy(part.name, partition->name().c_str(), sizeof(part.name));
795         part.first_extent_index = static_cast<uint32_t>(metadata->extents.size());
796         part.num_extents = static_cast<uint32_t>(partition->extents().size());
797         part.attributes = partition->attributes();
798         if (auto_slot_suffixing_) {
799             part.attributes |= LP_PARTITION_ATTR_SLOT_SUFFIXED;
800         }
801 
802         auto iter = group_indices.find(partition->group_name());
803         if (iter == group_indices.end()) {
804             LERROR << "Partition " << partition->name() << " is a member of unknown group "
805                    << partition->group_name();
806             return nullptr;
807         }
808         part.group_index = iter->second;
809 
810         for (const auto& extent : partition->extents()) {
811             if (!extent->AddTo(metadata.get())) {
812                 return nullptr;
813             }
814         }
815         metadata->partitions.push_back(part);
816     }
817 
818     metadata->header.partitions.num_entries = static_cast<uint32_t>(metadata->partitions.size());
819     metadata->header.extents.num_entries = static_cast<uint32_t>(metadata->extents.size());
820     metadata->header.groups.num_entries = static_cast<uint32_t>(metadata->groups.size());
821     metadata->header.block_devices.num_entries =
822             static_cast<uint32_t>(metadata->block_devices.size());
823     return metadata;
824 }
825 
AllocatableSpace() const826 uint64_t MetadataBuilder::AllocatableSpace() const {
827     uint64_t total_size = 0;
828     for (const auto& block_device : block_devices_) {
829         total_size += block_device.size - (block_device.first_logical_sector * LP_SECTOR_SIZE);
830     }
831     return total_size;
832 }
833 
UsedSpace() const834 uint64_t MetadataBuilder::UsedSpace() const {
835     uint64_t size = 0;
836     for (const auto& partition : partitions_) {
837         size += partition->size();
838     }
839     return size;
840 }
841 
AlignSector(const LpMetadataBlockDevice & block_device,uint64_t sector) const842 uint64_t MetadataBuilder::AlignSector(const LpMetadataBlockDevice& block_device,
843                                       uint64_t sector) const {
844     // Note: when reading alignment info from the Kernel, we don't assume it
845     // is aligned to the sector size, so we round up to the nearest sector.
846     uint64_t lba = sector * LP_SECTOR_SIZE;
847     uint64_t aligned = AlignTo(lba, block_device.alignment, block_device.alignment_offset);
848     return AlignTo(aligned, LP_SECTOR_SIZE) / LP_SECTOR_SIZE;
849 }
850 
FindBlockDeviceByName(const std::string & partition_name,uint32_t * index) const851 bool MetadataBuilder::FindBlockDeviceByName(const std::string& partition_name,
852                                             uint32_t* index) const {
853     for (size_t i = 0; i < block_devices_.size(); i++) {
854         if (GetBlockDevicePartitionName(block_devices_[i]) == partition_name) {
855             *index = i;
856             return true;
857         }
858     }
859     return false;
860 }
861 
HasBlockDevice(const std::string & partition_name) const862 bool MetadataBuilder::HasBlockDevice(const std::string& partition_name) const {
863     uint32_t index;
864     return FindBlockDeviceByName(partition_name, &index);
865 }
866 
GetBlockDeviceInfo(const std::string & partition_name,BlockDeviceInfo * info) const867 bool MetadataBuilder::GetBlockDeviceInfo(const std::string& partition_name,
868                                          BlockDeviceInfo* info) const {
869     uint32_t index;
870     if (!FindBlockDeviceByName(partition_name, &index)) {
871         LERROR << "No device named " << partition_name;
872         return false;
873     }
874     info->size = block_devices_[index].size;
875     info->alignment = block_devices_[index].alignment;
876     info->alignment_offset = block_devices_[index].alignment_offset;
877     info->logical_block_size = geometry_.logical_block_size;
878     info->partition_name = partition_name;
879     return true;
880 }
881 
UpdateBlockDeviceInfo(const std::string & partition_name,const BlockDeviceInfo & device_info)882 bool MetadataBuilder::UpdateBlockDeviceInfo(const std::string& partition_name,
883                                             const BlockDeviceInfo& device_info) {
884     uint32_t index;
885     if (!FindBlockDeviceByName(partition_name, &index)) {
886         LERROR << "No device named " << partition_name;
887         return false;
888     }
889     return UpdateBlockDeviceInfo(index, device_info);
890 }
891 
UpdateBlockDeviceInfo(size_t index,const BlockDeviceInfo & device_info)892 bool MetadataBuilder::UpdateBlockDeviceInfo(size_t index, const BlockDeviceInfo& device_info) {
893     CHECK(index < block_devices_.size());
894 
895     LpMetadataBlockDevice& block_device = block_devices_[index];
896     if (device_info.size != block_device.size) {
897         LERROR << "Device size does not match (got " << device_info.size << ", expected "
898                << block_device.size << ")";
899         return false;
900     }
901     if (geometry_.logical_block_size % device_info.logical_block_size) {
902         LERROR << "Device logical block size is misaligned (block size="
903                << device_info.logical_block_size << ", alignment=" << geometry_.logical_block_size
904                << ")";
905         return false;
906     }
907 
908     // The kernel does not guarantee these values are present, so we only
909     // replace existing values if the new values are non-zero.
910     if (device_info.alignment) {
911         block_device.alignment = device_info.alignment;
912     }
913     if (device_info.alignment_offset) {
914         block_device.alignment_offset = device_info.alignment_offset;
915     }
916     return true;
917 }
918 
ResizePartition(Partition * partition,uint64_t requested_size)919 bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) {
920     // Align the space needed up to the nearest sector.
921     uint64_t aligned_size = AlignTo(requested_size, geometry_.logical_block_size);
922     uint64_t old_size = partition->size();
923 
924     if (!ValidatePartitionSizeChange(partition, old_size, aligned_size, false)) {
925         return false;
926     }
927 
928     if (aligned_size > old_size) {
929         if (!GrowPartition(partition, aligned_size)) {
930             return false;
931         }
932     } else if (aligned_size < partition->size()) {
933         ShrinkPartition(partition, aligned_size);
934     }
935 
936     if (partition->size() != old_size) {
937         LINFO << "Partition " << partition->name() << " will resize from " << old_size
938               << " bytes to " << aligned_size << " bytes";
939     }
940     return true;
941 }
942 
ListGroups() const943 std::vector<std::string> MetadataBuilder::ListGroups() const {
944     std::vector<std::string> names;
945     for (const auto& group : groups_) {
946         names.emplace_back(group->name());
947     }
948     return names;
949 }
950 
RemoveGroupAndPartitions(const std::string & group_name)951 void MetadataBuilder::RemoveGroupAndPartitions(const std::string& group_name) {
952     if (group_name == kDefaultGroup) {
953         // Cannot remove the default group.
954         return;
955     }
956     std::vector<std::string> partition_names;
957     for (const auto& partition : partitions_) {
958         if (partition->group_name() == group_name) {
959             partition_names.emplace_back(partition->name());
960         }
961     }
962 
963     for (const auto& partition_name : partition_names) {
964         RemovePartition(partition_name);
965     }
966     for (auto iter = groups_.begin(); iter != groups_.end(); iter++) {
967         if ((*iter)->name() == group_name) {
968             groups_.erase(iter);
969             break;
970         }
971     }
972 }
973 
CompareBlockDevices(const LpMetadataBlockDevice & first,const LpMetadataBlockDevice & second)974 static bool CompareBlockDevices(const LpMetadataBlockDevice& first,
975                                 const LpMetadataBlockDevice& second) {
976     // Note: we don't compare alignment, since it's a performance thing and
977     // won't affect whether old extents continue to work.
978     return first.first_logical_sector == second.first_logical_sector && first.size == second.size &&
979            GetBlockDevicePartitionName(first) == GetBlockDevicePartitionName(second);
980 }
981 
ImportPartitions(const LpMetadata & metadata,const std::set<std::string> & partition_names)982 bool MetadataBuilder::ImportPartitions(const LpMetadata& metadata,
983                                        const std::set<std::string>& partition_names) {
984     // The block device list must be identical. We do not try to be clever and
985     // allow ordering changes or changes that don't affect partitions. This
986     // process is designed to allow the most common flashing scenarios and more
987     // complex ones should require a wipe.
988     if (metadata.block_devices.size() != block_devices_.size()) {
989         LINFO << "Block device tables does not match.";
990         return false;
991     }
992     for (size_t i = 0; i < metadata.block_devices.size(); i++) {
993         const LpMetadataBlockDevice& old_device = metadata.block_devices[i];
994         const LpMetadataBlockDevice& new_device = block_devices_[i];
995         if (!CompareBlockDevices(old_device, new_device)) {
996             LINFO << "Block device tables do not match";
997             return false;
998         }
999     }
1000 
1001     // Import named partitions. Note that we do not attempt to merge group
1002     // information here. If the device changed its group names, the old
1003     // partitions will fail to merge. The same could happen if the group
1004     // allocation sizes change.
1005     for (const auto& partition : metadata.partitions) {
1006         std::string partition_name = GetPartitionName(partition);
1007         if (partition_names.find(partition_name) == partition_names.end()) {
1008             continue;
1009         }
1010         if (!ImportPartition(metadata, partition)) {
1011             return false;
1012         }
1013     }
1014     return true;
1015 }
1016 
ImportPartition(const LpMetadata & metadata,const LpMetadataPartition & source)1017 bool MetadataBuilder::ImportPartition(const LpMetadata& metadata,
1018                                       const LpMetadataPartition& source) {
1019     std::string partition_name = GetPartitionName(source);
1020     Partition* partition = FindPartition(partition_name);
1021     if (!partition) {
1022         std::string group_name = GetPartitionGroupName(metadata.groups[source.group_index]);
1023         partition = AddPartition(partition_name, group_name, source.attributes);
1024         if (!partition) {
1025             return false;
1026         }
1027     }
1028     if (partition->size() > 0) {
1029         LINFO << "Importing partition table would overwrite non-empty partition: "
1030               << partition_name;
1031         return false;
1032     }
1033 
1034     ImportExtents(partition, metadata, source);
1035 
1036     // Note: we've already increased the partition size by calling
1037     // ImportExtents(). In order to figure out the size before that,
1038     // we would have to iterate the extents and add up the linear
1039     // segments. Instead, we just force ValidatePartitionSizeChange
1040     // to check if the current configuration is acceptable.
1041     if (!ValidatePartitionSizeChange(partition, partition->size(), partition->size(), true)) {
1042         partition->RemoveExtents();
1043         return false;
1044     }
1045     return true;
1046 }
1047 
SetAutoSlotSuffixing()1048 void MetadataBuilder::SetAutoSlotSuffixing() {
1049     auto_slot_suffixing_ = true;
1050 }
1051 
IgnoreSlotSuffixing()1052 void MetadataBuilder::IgnoreSlotSuffixing() {
1053     ignore_slot_suffixing_ = true;
1054 }
1055 
IsABDevice() const1056 bool MetadataBuilder::IsABDevice() const {
1057     if (sABOverrideSet) {
1058         return sABOverrideValue;
1059     }
1060     return android::base::GetBoolProperty("ro.build.ab_update", false);
1061 }
1062 
IsRetrofitDevice() const1063 bool MetadataBuilder::IsRetrofitDevice() const {
1064     return GetBlockDevicePartitionName(block_devices_[0]) != LP_METADATA_DEFAULT_PARTITION_NAME;
1065 }
1066 
AddLinearExtent(Partition * partition,const std::string & block_device,uint64_t num_sectors,uint64_t physical_sector)1067 bool MetadataBuilder::AddLinearExtent(Partition* partition, const std::string& block_device,
1068                                       uint64_t num_sectors, uint64_t physical_sector) {
1069     uint32_t device_index;
1070     if (!FindBlockDeviceByName(block_device, &device_index)) {
1071         LERROR << "Could not find backing block device for extent: " << block_device;
1072         return false;
1073     }
1074 
1075     auto extent = std::make_unique<LinearExtent>(num_sectors, device_index, physical_sector);
1076     partition->AddExtent(std::move(extent));
1077     return true;
1078 }
1079 
ListPartitionsInGroup(const std::string & group_name)1080 std::vector<Partition*> MetadataBuilder::ListPartitionsInGroup(const std::string& group_name) {
1081     std::vector<Partition*> partitions;
1082     for (const auto& partition : partitions_) {
1083         if (partition->group_name() == group_name) {
1084             partitions.emplace_back(partition.get());
1085         }
1086     }
1087     return partitions;
1088 }
1089 
ChangePartitionGroup(Partition * partition,const std::string & group_name)1090 bool MetadataBuilder::ChangePartitionGroup(Partition* partition, const std::string& group_name) {
1091     if (!FindGroup(group_name)) {
1092         LERROR << "Partition cannot change to unknown group: " << group_name;
1093         return false;
1094     }
1095     partition->set_group_name(group_name);
1096     return true;
1097 }
1098 
ValidatePartitionGroups() const1099 bool MetadataBuilder::ValidatePartitionGroups() const {
1100     for (const auto& group : groups_) {
1101         if (!group->maximum_size()) {
1102             continue;
1103         }
1104         uint64_t used = TotalSizeOfGroup(group.get());
1105         if (used > group->maximum_size()) {
1106             LERROR << "Partition group " << group->name() << " exceeds maximum size (" << used
1107                    << " bytes used, maximum " << group->maximum_size() << ")";
1108             return false;
1109         }
1110     }
1111     return true;
1112 }
1113 
ChangeGroupSize(const std::string & group_name,uint64_t maximum_size)1114 bool MetadataBuilder::ChangeGroupSize(const std::string& group_name, uint64_t maximum_size) {
1115     if (group_name == kDefaultGroup) {
1116         LERROR << "Cannot change the size of the default group";
1117         return false;
1118     }
1119     PartitionGroup* group = FindGroup(group_name);
1120     if (!group) {
1121         LERROR << "Cannot change size of unknown partition group: " << group_name;
1122         return false;
1123     }
1124     group->set_maximum_size(maximum_size);
1125     return true;
1126 }
1127 
1128 }  // namespace fs_mgr
1129 }  // namespace android
1130