Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 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 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 17 | #define LOG_TAG "incfs-mounts" |
| 18 | |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 19 | #include "MountRegistry.h" |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 20 | |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 21 | #include "incfs.h" |
| 22 | #include "path.h" |
| 23 | #include "split.h" |
| 24 | |
| 25 | #include <android-base/logging.h> |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 26 | |
| 27 | #include <charconv> |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 28 | #include <unordered_map> |
| 29 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 30 | #include <poll.h> |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 31 | #include <stdlib.h> |
| 32 | |
| 33 | using namespace std::literals; |
| 34 | |
| 35 | namespace android::incfs { |
| 36 | |
| 37 | // /proc/self/mountinfo may have some special characters in paths replaced with their |
| 38 | // octal codes in the following pattern: '\xxx', e.g. \040 for space character. |
| 39 | // This function translates those patterns back into corresponding characters. |
| 40 | static void fixProcPath(std::string& path) { |
| 41 | static const auto kPrefix = "\\"sv; |
| 42 | static const auto kPatternLength = 4; |
| 43 | auto pos = std::search(path.begin(), path.end(), kPrefix.begin(), kPrefix.end()); |
| 44 | if (pos == path.end()) { |
| 45 | return; |
| 46 | } |
| 47 | auto dest = pos; |
| 48 | do { |
| 49 | if (path.end() - pos < kPatternLength || !std::equal(kPrefix.begin(), kPrefix.end(), pos)) { |
| 50 | *dest++ = *pos++; |
| 51 | } else { |
| 52 | int charCode; |
| 53 | auto res = std::from_chars(&*(pos + kPrefix.size()), &*(pos + kPatternLength), charCode, |
| 54 | 8); |
| 55 | if (res.ec == std::errc{}) { |
| 56 | *dest++ = char(charCode); |
| 57 | } else { |
| 58 | // Didn't convert, let's keep it as is. |
| 59 | dest = std::copy(pos, pos + kPatternLength, dest); |
| 60 | pos += kPatternLength; |
| 61 | } |
| 62 | } |
| 63 | } while (pos != path.end()); |
| 64 | path.erase(dest, path.end()); |
| 65 | } |
| 66 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 67 | std::vector<std::pair<std::string_view, std::string_view>> MountRegistry::Mounts::Mount::binds() |
| 68 | const { |
| 69 | std::vector<std::pair<std::string_view, std::string_view>> result; |
| 70 | result.reserve(mBase->binds.size()); |
| 71 | for (auto it : mBase->binds) { |
| 72 | result.emplace_back(it->second.first, it->first); |
| 73 | } |
| 74 | return result; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 75 | } |
| 76 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 77 | void MountRegistry::Mounts::swap(MountRegistry::Mounts& other) { |
| 78 | roots.swap(other.roots); |
| 79 | rootByBindPoint.swap(other.rootByBindPoint); |
| 80 | } |
| 81 | |
| 82 | void MountRegistry::Mounts::clear() { |
| 83 | roots.clear(); |
| 84 | rootByBindPoint.clear(); |
| 85 | } |
| 86 | |
| 87 | std::pair<int, MountRegistry::BindMap::const_iterator> MountRegistry::Mounts::rootIndex( |
| 88 | std::string_view path) const { |
| 89 | auto it = rootByBindPoint.lower_bound(path); |
| 90 | if (it != rootByBindPoint.end() && it->first == path) { |
| 91 | return {it->second.second, it}; |
| 92 | } |
| 93 | if (it != rootByBindPoint.begin()) { |
| 94 | --it; |
| 95 | if (path::startsWith(path, it->first) && path.size() > it->first.size()) { |
| 96 | const auto index = it->second.second; |
| 97 | if (index >= int(roots.size()) || roots[index].empty()) { |
| 98 | LOG(ERROR) << "[incfs] Root for path '" << path << "' #" << index |
| 99 | << " is not valid"; |
| 100 | return {-1, {}}; |
| 101 | } |
| 102 | return {index, it}; |
| 103 | } |
| 104 | } |
| 105 | return {-1, {}}; |
| 106 | } |
| 107 | |
| 108 | std::string_view MountRegistry::Mounts::rootFor(std::string_view path) const { |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 109 | auto [index, _] = rootIndex(path::normalize(path)); |
| 110 | if (index < 0) { |
| 111 | return {}; |
| 112 | } |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 113 | return roots[index].path; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 114 | } |
| 115 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 116 | std::pair<std::string_view, std::string> MountRegistry::Mounts::rootAndSubpathFor( |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 117 | std::string_view path) const { |
| 118 | auto normalPath = path::normalize(path); |
| 119 | auto [index, bindIt] = rootIndex(normalPath); |
| 120 | if (index < 0) { |
| 121 | return {}; |
| 122 | } |
| 123 | |
Yurii Zubrytskyi | ddfd543 | 2020-01-31 16:58:29 -0800 | [diff] [blame] | 124 | const auto& bindSubdir = bindIt->second.first; |
| 125 | const auto pastBindSubdir = path::relativize(bindIt->first, normalPath); |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 126 | const auto& root = roots[index]; |
| 127 | return {root.path, path::join(bindSubdir, pastBindSubdir)}; |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 128 | } |
| 129 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 130 | void MountRegistry::Mounts::addRoot(std::string_view root, std::string_view backingDir) { |
| 131 | const auto index = roots.size(); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 132 | auto absolute = path::normalize(root); |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 133 | auto it = rootByBindPoint.insert_or_assign(absolute, std::pair{std::string(), index}).first; |
| 134 | roots.push_back({std::move(absolute), path::normalize(backingDir), {it}}); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 135 | } |
| 136 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 137 | void MountRegistry::Mounts::removeRoot(std::string_view root) { |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 138 | auto absolute = path::normalize(root); |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 139 | auto it = rootByBindPoint.find(absolute); |
| 140 | if (it == rootByBindPoint.end()) { |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 141 | LOG(WARNING) << "[incfs] Trying to remove non-existent root '" << root << '\''; |
| 142 | return; |
| 143 | } |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 144 | const auto index = it->second.second; |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 145 | if (index >= int(roots.size())) { |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 146 | LOG(ERROR) << "[incfs] Root '" << root << "' has index " << index |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 147 | << " out of bounds (total roots count is " << roots.size(); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 148 | return; |
| 149 | } |
| 150 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 151 | if (index + 1 == int(roots.size())) { |
| 152 | roots.pop_back(); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 153 | // Run a small GC job here as we may be able to remove some obsolete |
| 154 | // entries. |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 155 | while (roots.back().empty()) { |
| 156 | roots.pop_back(); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 157 | } |
| 158 | } else { |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 159 | roots[index].clear(); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 160 | } |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 161 | rootByBindPoint.erase(it); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 162 | } |
| 163 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 164 | void MountRegistry::Mounts::moveBind(std::string_view src, std::string_view dest) { |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 165 | auto srcAbsolute = path::normalize(src); |
| 166 | auto destAbsolute = path::normalize(dest); |
| 167 | if (srcAbsolute == destAbsolute) { |
| 168 | return; |
| 169 | } |
| 170 | |
| 171 | auto [root, rootIt] = rootIndex(srcAbsolute); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 172 | if (root < 0) { |
| 173 | LOG(ERROR) << "[incfs] No root found for bind move from " << src << " to " << dest; |
| 174 | return; |
| 175 | } |
| 176 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 177 | if (roots[root].path == srcAbsolute) { |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 178 | // moving the whole root |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 179 | roots[root].path = destAbsolute; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 180 | } |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 181 | |
Yurii Zubrytskyi | 7b50c58 | 2020-04-22 15:43:56 -0700 | [diff] [blame] | 182 | // const_cast<> here is safe as we're erasing that element on the next line. |
| 183 | const auto newRootIt = rootByBindPoint |
| 184 | .insert_or_assign(std::move(destAbsolute), |
| 185 | std::pair{std::move(const_cast<std::string&>( |
| 186 | rootIt->second.first)), |
| 187 | root}) |
| 188 | .first; |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 189 | rootByBindPoint.erase(rootIt); |
| 190 | const auto bindIt = std::find(roots[root].binds.begin(), roots[root].binds.end(), rootIt); |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 191 | *bindIt = newRootIt; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 192 | } |
| 193 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 194 | void MountRegistry::Mounts::addBind(std::string_view what, std::string_view where) { |
| 195 | auto whatAbsolute = path::normalize(what); |
| 196 | auto [root, rootIt] = rootIndex(whatAbsolute); |
| 197 | if (root < 0) { |
| 198 | LOG(ERROR) << "[incfs] No root found for bind from " << what << " to " << where; |
| 199 | return; |
| 200 | } |
| 201 | |
| 202 | const auto& currentBind = rootIt->first; |
| 203 | auto whatSubpath = path::relativize(currentBind, whatAbsolute); |
| 204 | const auto& subdir = rootIt->second.first; |
| 205 | auto realSubdir = path::join(subdir, whatSubpath); |
| 206 | auto it = rootByBindPoint |
| 207 | .insert_or_assign(path::normalize(where), |
| 208 | std::pair{std::move(realSubdir), root}) |
| 209 | .first; |
| 210 | roots[root].binds.push_back(it); |
| 211 | } |
| 212 | |
| 213 | void MountRegistry::Mounts::removeBind(std::string_view what) { |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 214 | auto absolute = path::normalize(what); |
| 215 | auto [root, rootIt] = rootIndex(absolute); |
| 216 | if (root < 0) { |
| 217 | LOG(WARNING) << "[incfs] Trying to remove non-existent bind point '" << what << '\''; |
| 218 | return; |
| 219 | } |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 220 | if (roots[root].path == absolute) { |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 221 | removeRoot(absolute); |
| 222 | return; |
| 223 | } |
| 224 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 225 | rootByBindPoint.erase(rootIt); |
| 226 | auto& binds = roots[root].binds; |
| 227 | auto itBind = std::find(binds.begin(), binds.end(), rootIt); |
| 228 | std::swap(binds.back(), *itBind); |
| 229 | binds.pop_back(); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 230 | } |
| 231 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 232 | MountRegistry::MountRegistry(std::string_view filesystem) |
| 233 | : mFilesystem(filesystem.empty() ? INCFS_NAME : filesystem), |
| 234 | mMountInfo(::open("/proc/self/mountinfo", O_RDONLY | O_CLOEXEC)) { |
| 235 | if (!mMountInfo.ok()) { |
| 236 | PLOG(FATAL) << "Failed to open the /proc/mounts file"; |
| 237 | } |
| 238 | mMounts.loadFrom(mMountInfo, mFilesystem); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 239 | } |
| 240 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 241 | MountRegistry::~MountRegistry() = default; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 242 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 243 | std::string MountRegistry::rootFor(std::string_view path) { |
| 244 | auto lock = ensureUpToDate(); |
| 245 | return std::string(mMounts.rootFor(path)); |
| 246 | } |
| 247 | std::pair<std::string, std::string> MountRegistry::rootAndSubpathFor(std::string_view path) { |
| 248 | auto lock = ensureUpToDate(); |
| 249 | auto [root, subpath] = mMounts.rootAndSubpathFor(path); |
| 250 | return {std::string(root), std::move(subpath)}; |
| 251 | } |
| 252 | |
| 253 | MountRegistry::Mounts MountRegistry::copyMounts() { |
| 254 | auto lock = ensureUpToDate(); |
| 255 | return mMounts; |
| 256 | } |
| 257 | |
| 258 | void MountRegistry::reload() { |
| 259 | (void)ensureUpToDate(); |
| 260 | } |
| 261 | |
| 262 | std::unique_lock<std::mutex> MountRegistry::ensureUpToDate() { |
| 263 | pollfd pfd = {.fd = mMountInfo.get(), .events = POLLERR | POLLPRI}; |
| 264 | const auto res = TEMP_FAILURE_RETRY(poll(&pfd, 1, 0)); |
| 265 | if (res == 0) { |
| 266 | // timeout - nothing to do, up to date |
| 267 | return std::unique_lock{mDataMutex}; |
| 268 | } |
| 269 | |
| 270 | // reload even if poll() fails: (1) it usually doesn't and (2) it's better to be safe. |
| 271 | std::unique_lock lock(mDataMutex); |
| 272 | mMounts.loadFrom(mMountInfo, mFilesystem); |
| 273 | return lock; |
| 274 | } |
| 275 | |
| 276 | template <class Callback> |
| 277 | static bool forEachLine(base::borrowed_fd fd, Callback&& cb) { |
| 278 | static constexpr auto kBufSize = 128 * 1024; |
| 279 | char buffer[kBufSize]; |
| 280 | const char* nextLine = buffer; |
| 281 | char* nextRead = buffer; |
| 282 | int64_t pos = 0; |
| 283 | for (;;) { |
| 284 | const auto read = pread(fd.get(), nextRead, std::end(buffer) - nextRead, pos); |
| 285 | if (read == 0) { |
| 286 | break; |
| 287 | } |
| 288 | if (read < 0) { |
| 289 | if (errno == EINTR) { |
| 290 | continue; |
| 291 | } |
| 292 | return false; |
| 293 | } |
| 294 | |
| 295 | pos += read; |
| 296 | const auto readEnd = nextRead + read; |
| 297 | auto chunk = std::string_view{nextLine, size_t(readEnd - nextLine)}; |
| 298 | do { |
| 299 | auto lineEnd = chunk.find('\n'); |
| 300 | if (lineEnd == chunk.npos) { |
| 301 | break; |
| 302 | } |
| 303 | cb(chunk.substr(0, lineEnd)); |
| 304 | chunk.remove_prefix(lineEnd + 1); |
| 305 | } while (!chunk.empty()); |
| 306 | |
| 307 | const auto remainingSize = readEnd - chunk.end(); |
| 308 | memmove(buffer, chunk.end(), remainingSize); |
| 309 | nextLine = buffer; |
| 310 | nextRead = buffer + remainingSize; |
| 311 | } |
| 312 | |
| 313 | if (nextLine < nextRead) { |
| 314 | cb({nextLine, size_t(nextRead - nextLine)}); |
| 315 | } |
| 316 | |
| 317 | return true; |
| 318 | } |
| 319 | |
| 320 | bool MountRegistry::Mounts::loadFrom(base::borrowed_fd fd, std::string_view filesystem) { |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 321 | struct MountInfo { |
| 322 | std::string root; |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 323 | std::string backing; |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 324 | std::vector<std::pair<std::string, std::string>> bindPoints; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 325 | }; |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 326 | std::unordered_map<std::string, MountInfo> mountsByGroup(16); |
| 327 | std::vector<std::string_view> items(12); |
| 328 | const auto parsed = forEachLine(fd, [&](std::string_view line) { |
| 329 | if (line.empty()) { |
| 330 | return; |
| 331 | } |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 332 | Split(line, ' ', &items); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 333 | if (items.size() < 10) { |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 334 | LOG(WARNING) << "[incfs] bad line in mountinfo: '" << line << '\''; |
| 335 | return; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 336 | } |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 337 | // Note: there are optional fields in the line, starting at [6]. Anything after that should |
| 338 | // be indexed from the end. |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 339 | const auto name = items.rbegin()[2]; |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 340 | if (!name.starts_with(filesystem)) { |
| 341 | return; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 342 | } |
| 343 | const auto groupId = items[2]; |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 344 | auto subdir = items[3]; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 345 | auto mountPoint = std::string(items[4]); |
| 346 | fixProcPath(mountPoint); |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 347 | mountPoint = path::normalize(mountPoint); |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 348 | auto& mount = mountsByGroup[std::string(groupId)]; |
| 349 | if (subdir == "/"sv) { |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 350 | if (mount.root.empty()) { |
| 351 | mount.root.assign(mountPoint); |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 352 | mount.backing.assign(items.rbegin()[1]); |
| 353 | fixProcPath(mount.backing); |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 354 | } else { |
| 355 | LOG(WARNING) << "[incfs] incfs root '" << mount.root |
| 356 | << "' mounted in multiple places, ignoring later mount '" << mountPoint |
| 357 | << '\''; |
| 358 | } |
| 359 | subdir = ""sv; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 360 | } |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 361 | mount.bindPoints.emplace_back(std::string(subdir), std::move(mountPoint)); |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 362 | }); |
| 363 | |
| 364 | if (!parsed) { |
| 365 | return false; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 366 | } |
| 367 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 368 | rootByBindPoint.clear(); |
| 369 | // preserve the allocated capacity, but clean existing data |
| 370 | roots.resize(mountsByGroup.size()); |
| 371 | for (auto& root : roots) { |
| 372 | root.binds.clear(); |
| 373 | } |
| 374 | |
| 375 | int index = 0; |
| 376 | for (auto& [_, mount] : mountsByGroup) { |
| 377 | Root& root = roots[index]; |
| 378 | auto& binds = root.binds; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 379 | binds.reserve(mount.bindPoints.size()); |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 380 | for (auto& [subdir, bind] : mount.bindPoints) { |
| 381 | auto it = |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 382 | rootByBindPoint |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 383 | .insert_or_assign(std::move(bind), std::pair(std::move(subdir), index)) |
| 384 | .first; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 385 | binds.push_back(it); |
| 386 | } |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 387 | root.path = std::move(mount.root); |
| 388 | root.backing = std::move(mount.backing); |
| 389 | ++index; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 390 | } |
| 391 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 392 | LOG(INFO) << "[incfs] Loaded " << filesystem << " mount info: " << roots.size() |
| 393 | << " instances, " << rootByBindPoint.size() << " mount points"; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 394 | if (base::VERBOSE >= base::GetMinimumLogSeverity()) { |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 395 | for (auto&& [root, backing, binds] : roots) { |
| 396 | LOG(INFO) << "[incfs] '" << root << '\''; |
| 397 | LOG(INFO) << "[incfs] backing: '" << backing << '\''; |
| 398 | for (auto&& bind : binds) { |
| 399 | LOG(INFO) << "[incfs] bind : '" << bind->second.first << "'->'" << bind->first |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 400 | << '\''; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 401 | } |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 402 | } |
| 403 | } |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 404 | return true; |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 405 | } |
| 406 | |
Yurii Zubrytskyi | 003751d | 2020-04-16 12:45:39 -0700 | [diff] [blame] | 407 | auto MountRegistry::Mounts::load(base::borrowed_fd mountInfo, std::string_view filesystem) |
| 408 | -> Mounts { |
| 409 | Mounts res; |
| 410 | res.loadFrom(mountInfo, filesystem); |
Yurii Zubrytskyi | d668885 | 2019-11-26 17:39:08 -0800 | [diff] [blame] | 411 | return res; |
| 412 | } |
| 413 | |
Songchun Fan | 59eee56 | 2019-10-24 16:46:06 -0700 | [diff] [blame] | 414 | } // namespace android::incfs |