/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "VoldUtil.h" #include "Utils.h" #include #include #include #include #include using android::base::Basename; using android::base::Realpath; using namespace android::dm; android::fs_mgr::Fstab fstab_default; static std::string GetUfsHostControllerSysfsPathOnce() { android::fs_mgr::FstabEntry* entry = android::fs_mgr::GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT); if (entry == nullptr) { LOG(ERROR) << "No mount point entry for " << DATA_MNT_POINT; return ""; } // Handle symlinks. std::string real_path; if (!Realpath(entry->blk_device, &real_path)) { real_path = entry->blk_device; } // Handle logical volumes. android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance(); for (;;) { std::optional parent = dm.GetParentBlockDeviceByPath(real_path); if (!parent.has_value()) break; real_path = *parent; } std::string path = "/sys/class/block/" + Basename(real_path); // Walk up the sysfs directory tree from the partition (e.g, /sys/class/block/sda34) // or from the disk (e.g., /sys/class/block/sda) to reach the UFS host controller's directory // (e.g., /sys/class/block/sda34/../device/../../.. --> /sys/devices/platform/00000000.ufs). if (android::vold::pathExists(path + "/../device")) { path += "/../device/../../.."; } else if (android::vold::pathExists(path + "/device")) { path += "/device/../../.."; } else { LOG(WARNING) << "Failed to get sysfs_path for user data partition"; return ""; } // Verify the block device is UFS by checking for the presence of "uic_link_state", // which is UFS interconnect layer link state. // If not UFS, return an empty path. if (!android::vold::pathExists(path + "/uic_link_state")) { LOG(ERROR) << "The block device (" << Basename(real_path) << ") of " << DATA_MNT_POINT << " is not UFS."; return ""; } LOG(DEBUG) << "The sysfs directory for the ufs host controller is found at " << path; return path; } // get sysfs directory for the ufs host controller containing userdata // returns an empty string on failures. std::string GetUfsHostControllerSysfsPath() { static std::string ufshc_sysfs_path = GetUfsHostControllerSysfsPathOnce(); return ufshc_sysfs_path; }