Skip to content

Commit b40a126

Browse files
committed
Merge tag 'android-12.0.0_r21' into S
2 parents a5ff990 + 2237faa commit b40a126

24 files changed

Lines changed: 886 additions & 114 deletions

File tree

fastboot/device/flashing.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,17 @@ bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wip
187187
", build may be missing broken or missing boot_devices");
188188
}
189189

190+
std::string slot_suffix = device->GetCurrentSlot();
191+
uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
192+
193+
std::string other_slot_suffix;
194+
if (!slot_suffix.empty()) {
195+
other_slot_suffix = (slot_suffix == "_a") ? "_b" : "_a";
196+
}
197+
190198
// If we are unable to read the existing metadata, then the super partition
191199
// is corrupt. In this case we reflash the whole thing using the provided
192200
// image.
193-
std::string slot_suffix = device->GetCurrentSlot();
194-
uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
195201
std::unique_ptr<LpMetadata> old_metadata = ReadMetadata(super_name, slot_number);
196202
if (wipe || !old_metadata) {
197203
if (!FlashPartitionTable(super_name, *new_metadata.get())) {
@@ -203,11 +209,15 @@ bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wip
203209
}
204210

205211
std::set<std::string> partitions_to_keep;
212+
bool virtual_ab = android::base::GetBoolProperty("ro.virtual_ab.enabled", false);
206213
for (const auto& partition : old_metadata->partitions) {
207214
// Preserve partitions in the other slot, but not the current slot.
208215
std::string partition_name = GetPartitionName(partition);
209-
if (!slot_suffix.empty() && GetPartitionSlotSuffix(partition_name) == slot_suffix) {
210-
continue;
216+
if (!slot_suffix.empty()) {
217+
auto part_suffix = GetPartitionSlotSuffix(partition_name);
218+
if (part_suffix == slot_suffix || (part_suffix == other_slot_suffix && virtual_ab)) {
219+
continue;
220+
}
211221
}
212222
std::string group_name = GetPartitionGroupName(old_metadata->groups[partition.group_index]);
213223
// Skip partitions in the COW group

fs_mgr/Android.bp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ cc_defaults {
6363
"-D_FILE_OFFSET_BITS=64",
6464
],
6565
srcs: [
66+
"blockdev.cpp",
6667
"file_wait.cpp",
6768
"fs_mgr.cpp",
6869
"fs_mgr_format.cpp",

fs_mgr/blockdev.cpp

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright (C) 2021 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 <android-base/file.h>
18+
#include <android-base/logging.h>
19+
#include <android-base/stringprintf.h>
20+
#include <android-base/strings.h>
21+
22+
#include <dirent.h>
23+
#include <libdm/dm.h>
24+
#include <sys/stat.h>
25+
#include <sys/sysmacros.h>
26+
#include <sys/types.h>
27+
#include "blockdev.h"
28+
29+
using android::base::Basename;
30+
using android::base::ErrnoError;
31+
using android::base::Error;
32+
using android::base::Result;
33+
using android::base::ResultError;
34+
using android::base::StartsWith;
35+
using android::base::StringPrintf;
36+
using android::base::unique_fd;
37+
using android::dm::DeviceMapper;
38+
39+
// Return the parent device of a partition. Converts e.g. "sda26" into "sda".
40+
static std::string PartitionParent(const std::string& blockdev) {
41+
if (blockdev.find('/') != std::string::npos) {
42+
LOG(ERROR) << __func__ << ": invalid argument " << blockdev;
43+
return blockdev;
44+
}
45+
auto dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/sys/class/block"), closedir};
46+
if (!dir) {
47+
return blockdev;
48+
}
49+
for (struct dirent* ent = readdir(dir.get()); ent; ent = readdir(dir.get())) {
50+
if (ent->d_name[0] == '.') {
51+
continue;
52+
}
53+
std::string path = StringPrintf("/sys/class/block/%s/%s", ent->d_name, blockdev.c_str());
54+
struct stat statbuf;
55+
if (stat(path.c_str(), &statbuf) >= 0) {
56+
return ent->d_name;
57+
}
58+
}
59+
return blockdev;
60+
}
61+
62+
// Convert a major:minor pair into a block device name.
63+
static std::string BlockdevName(dev_t dev) {
64+
auto dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/dev/block"), closedir};
65+
if (!dir) {
66+
return {};
67+
}
68+
for (struct dirent* ent = readdir(dir.get()); ent; ent = readdir(dir.get())) {
69+
if (ent->d_name[0] == '.') {
70+
continue;
71+
}
72+
const std::string path = std::string("/dev/block/") + ent->d_name;
73+
struct stat statbuf;
74+
if (stat(path.c_str(), &statbuf) >= 0 && dev == statbuf.st_rdev) {
75+
return ent->d_name;
76+
}
77+
}
78+
return {};
79+
}
80+
81+
// Trim whitespace from the end of a string.
82+
static void rtrim(std::string& s) {
83+
s.erase(s.find_last_not_of('\n') + 1, s.length());
84+
}
85+
86+
// For file `file_path`, retrieve the block device backing the filesystem on
87+
// which the file exists and return the queue depth of the block device.
88+
static Result<uint32_t> BlockDeviceQueueDepth(const std::string& file_path) {
89+
struct stat statbuf;
90+
int res = stat(file_path.c_str(), &statbuf);
91+
if (res < 0) {
92+
return ErrnoError() << "stat(" << file_path << ")";
93+
}
94+
std::string blockdev = "/dev/block/" + BlockdevName(statbuf.st_dev);
95+
LOG(DEBUG) << __func__ << ": " << file_path << " -> " << blockdev;
96+
if (blockdev.empty()) {
97+
const std::string err_msg =
98+
StringPrintf("Failed to convert %u:%u (path %s)", major(statbuf.st_dev),
99+
minor(statbuf.st_dev), file_path.c_str());
100+
return ResultError(err_msg, 0);
101+
}
102+
auto& dm = DeviceMapper::Instance();
103+
for (;;) {
104+
std::optional<std::string> child = dm.GetParentBlockDeviceByPath(blockdev);
105+
if (!child) {
106+
break;
107+
}
108+
LOG(DEBUG) << __func__ << ": " << blockdev << " -> " << *child;
109+
blockdev = *child;
110+
}
111+
std::optional<std::string> maybe_blockdev = android::dm::ExtractBlockDeviceName(blockdev);
112+
if (!maybe_blockdev) {
113+
return ResultError("Failed to remove /dev/block/ prefix from " + blockdev, 0);
114+
}
115+
blockdev = PartitionParent(*maybe_blockdev);
116+
LOG(DEBUG) << __func__ << ": "
117+
<< "Partition parent: " << blockdev;
118+
const std::string nr_tags_path =
119+
StringPrintf("/sys/class/block/%s/mq/0/nr_tags", blockdev.c_str());
120+
std::string nr_tags;
121+
if (!android::base::ReadFileToString(nr_tags_path, &nr_tags)) {
122+
return ResultError("Failed to read " + nr_tags_path, 0);
123+
}
124+
rtrim(nr_tags);
125+
LOG(DEBUG) << __func__ << ": " << file_path << " is backed by /dev/" << blockdev
126+
<< " and that block device supports queue depth " << nr_tags;
127+
return strtol(nr_tags.c_str(), NULL, 0);
128+
}
129+
130+
// Set 'nr_requests' of `loop_device_path` to the queue depth of the block
131+
// device backing `file_path`.
132+
Result<void> ConfigureQueueDepth(const std::string& loop_device_path,
133+
const std::string& file_path) {
134+
if (!StartsWith(loop_device_path, "/dev/")) {
135+
return Error() << "Invalid argument " << loop_device_path;
136+
}
137+
138+
const std::string loop_device_name = Basename(loop_device_path);
139+
140+
const Result<uint32_t> qd = BlockDeviceQueueDepth(file_path);
141+
if (!qd.ok()) {
142+
LOG(DEBUG) << __func__ << ": "
143+
<< "BlockDeviceQueueDepth() returned " << qd.error();
144+
return ResultError(qd.error());
145+
}
146+
const std::string nr_requests = StringPrintf("%u", *qd);
147+
const std::string sysfs_path =
148+
StringPrintf("/sys/class/block/%s/queue/nr_requests", loop_device_name.c_str());
149+
unique_fd sysfs_fd(open(sysfs_path.c_str(), O_RDWR | O_CLOEXEC));
150+
if (sysfs_fd == -1) {
151+
return ErrnoError() << "Failed to open " << sysfs_path;
152+
}
153+
154+
const int res = write(sysfs_fd.get(), nr_requests.data(), nr_requests.length());
155+
if (res < 0) {
156+
return ErrnoError() << "Failed to write to " << sysfs_path;
157+
}
158+
return {};
159+
}

fs_mgr/blockdev.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (C) 2021 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 <android-base/result.h>
18+
#include <string>
19+
20+
android::base::Result<void> ConfigureQueueDepth(const std::string& loop_device_path,
21+
const std::string& file_path);

fs_mgr/fs_mgr.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#include <log/log_properties.h>
7171
#include <logwrap/logwrap.h>
7272

73+
#include "blockdev.h"
7374
#include "fs_mgr_priv.h"
7475

7576
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
@@ -2065,22 +2066,24 @@ static bool PrepareZramBackingDevice(off64_t size) {
20652066

20662067
// Allocate loop device and attach it to file_path.
20672068
LoopControl loop_control;
2068-
std::string device;
2069-
if (!loop_control.Attach(target_fd.get(), 5s, &device)) {
2069+
std::string loop_device;
2070+
if (!loop_control.Attach(target_fd.get(), 5s, &loop_device)) {
20702071
return false;
20712072
}
20722073

2074+
ConfigureQueueDepth(loop_device, "/");
2075+
20732076
// set block size & direct IO
2074-
unique_fd device_fd(TEMP_FAILURE_RETRY(open(device.c_str(), O_RDWR | O_CLOEXEC)));
2075-
if (device_fd.get() == -1) {
2076-
PERROR << "Cannot open " << device;
2077+
unique_fd loop_fd(TEMP_FAILURE_RETRY(open(loop_device.c_str(), O_RDWR | O_CLOEXEC)));
2078+
if (loop_fd.get() == -1) {
2079+
PERROR << "Cannot open " << loop_device;
20772080
return false;
20782081
}
2079-
if (!LoopControl::EnableDirectIo(device_fd.get())) {
2082+
if (!LoopControl::EnableDirectIo(loop_fd.get())) {
20802083
return false;
20812084
}
20822085

2083-
return InstallZramDevice(device);
2086+
return InstallZramDevice(loop_device);
20842087
}
20852088

20862089
bool fs_mgr_swapon_all(const Fstab& fstab) {

fs_mgr/fs_mgr_fstab.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -414,17 +414,24 @@ std::string ReadFstabFromDt() {
414414
return fstab_result;
415415
}
416416

417-
// Identify path to fstab file. Lookup is based on pattern
418-
// fstab.<fstab_suffix>, fstab.<hardware>, fstab.<hardware.platform> in
419-
// folders /odm/etc, vendor/etc, or /.
417+
// Return the path to the fstab file. There may be multiple fstab files; the
418+
// one that is returned will be the first that exists of fstab.<fstab_suffix>,
419+
// fstab.<hardware>, and fstab.<hardware.platform>. The fstab is searched for
420+
// in /odm/etc/ and /vendor/etc/, as well as in the locations where it may be in
421+
// the first stage ramdisk during early boot. Previously, the first stage
422+
// ramdisk's copy of the fstab had to be located in the root directory, but now
423+
// the system/etc directory is supported too and is the preferred location.
420424
std::string GetFstabPath() {
421425
for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
422426
std::string suffix;
423427

424428
if (!fs_mgr_get_boot_config(prop, &suffix)) continue;
425429

426-
for (const char* prefix :
427-
{"/odm/etc/fstab.", "/vendor/etc/fstab.", "/fstab.", "/first_stage_ramdisk/fstab."}) {
430+
for (const char* prefix : {// late-boot/post-boot locations
431+
"/odm/etc/fstab.", "/vendor/etc/fstab.",
432+
// early boot locations
433+
"/system/etc/fstab.", "/first_stage_ramdisk/system/etc/fstab.",
434+
"/fstab.", "/first_stage_ramdisk/fstab."}) {
428435
std::string fstab_path = prefix + suffix;
429436
if (access(fstab_path.c_str(), F_OK) == 0) {
430437
return fstab_path;

fs_mgr/libdm/dm.cpp

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -560,34 +560,30 @@ std::string DeviceMapper::GetTargetType(const struct dm_target_spec& spec) {
560560
return std::string{spec.target_type, sizeof(spec.target_type)};
561561
}
562562

563-
static bool ExtractBlockDeviceName(const std::string& path, std::string* name) {
563+
std::optional<std::string> ExtractBlockDeviceName(const std::string& path) {
564564
static constexpr std::string_view kDevBlockPrefix("/dev/block/");
565565
if (android::base::StartsWith(path, kDevBlockPrefix)) {
566-
*name = path.substr(kDevBlockPrefix.length());
567-
return true;
566+
return path.substr(kDevBlockPrefix.length());
568567
}
569-
return false;
568+
return {};
570569
}
571570

572571
bool DeviceMapper::IsDmBlockDevice(const std::string& path) {
573-
std::string name;
574-
if (!ExtractBlockDeviceName(path, &name)) {
575-
return false;
576-
}
577-
return android::base::StartsWith(name, "dm-");
572+
std::optional<std::string> name = ExtractBlockDeviceName(path);
573+
return name && android::base::StartsWith(*name, "dm-");
578574
}
579575

580576
std::optional<std::string> DeviceMapper::GetDmDeviceNameByPath(const std::string& path) {
581-
std::string name;
582-
if (!ExtractBlockDeviceName(path, &name)) {
577+
std::optional<std::string> name = ExtractBlockDeviceName(path);
578+
if (!name) {
583579
LOG(WARNING) << path << " is not a block device";
584580
return std::nullopt;
585581
}
586-
if (!android::base::StartsWith(name, "dm-")) {
582+
if (!android::base::StartsWith(*name, "dm-")) {
587583
LOG(WARNING) << path << " is not a dm device";
588584
return std::nullopt;
589585
}
590-
std::string dm_name_file = "/sys/block/" + name + "/dm/name";
586+
std::string dm_name_file = "/sys/block/" + *name + "/dm/name";
591587
std::string dm_name;
592588
if (!android::base::ReadFileToString(dm_name_file, &dm_name)) {
593589
PLOG(ERROR) << "Failed to read file " << dm_name_file;
@@ -598,16 +594,16 @@ std::optional<std::string> DeviceMapper::GetDmDeviceNameByPath(const std::string
598594
}
599595

600596
std::optional<std::string> DeviceMapper::GetParentBlockDeviceByPath(const std::string& path) {
601-
std::string name;
602-
if (!ExtractBlockDeviceName(path, &name)) {
597+
std::optional<std::string> name = ExtractBlockDeviceName(path);
598+
if (!name) {
603599
LOG(WARNING) << path << " is not a block device";
604600
return std::nullopt;
605601
}
606-
if (!android::base::StartsWith(name, "dm-")) {
602+
if (!android::base::StartsWith(*name, "dm-")) {
607603
// Reached bottom of the device mapper stack.
608604
return std::nullopt;
609605
}
610-
auto slaves_dir = "/sys/block/" + name + "/slaves";
606+
auto slaves_dir = "/sys/block/" + *name + "/slaves";
611607
auto dir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(slaves_dir.c_str()), closedir);
612608
if (dir == nullptr) {
613609
PLOG(ERROR) << "Failed to open: " << slaves_dir;

fs_mgr/libdm/include/libdm/dm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ enum class DmDeviceState { INVALID, SUSPENDED, ACTIVE };
4949

5050
static constexpr uint64_t kSectorSize = 512;
5151

52+
// Returns `path` without /dev/block prefix if and only if `path` starts with
53+
// that prefix.
54+
std::optional<std::string> ExtractBlockDeviceName(const std::string& path);
55+
5256
class DeviceMapper final {
5357
public:
5458
class DmBlockDevice final {

0 commit comments

Comments
 (0)