blob: 3b19c06fbb0e25be5bd27b1a9e465eade2abf789 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_STORAGE_FSHOST_MINFS_MANIPULATOR_H_
#define SRC_STORAGE_FSHOST_MINFS_MANIPULATOR_H_
#include <fuchsia/hardware/block/llcpp/fidl.h>
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/zx/channel.h>
#include <lib/zx/status.h>
#include <cstdint>
#include <fbl/unique_fd.h>
#include "src/storage/fshost/copier.h"
#include "src/storage/fshost/fs-manager.h"
namespace devmgr {
constexpr char kGracefulRebootReasonFilePath[] =
"cache/de3e6f95d17b22bcc6b8bb5389301dc9fa60a16e2c5a4d35eb4a35dd9ac571c3/"
"graceful_reboot_reason.txt";
// Gets the BlockInfo from |device|.
zx::status<fuchsia_hardware_block::wire::BlockInfo> GetBlockDeviceInfo(
const zx::unowned_channel& device);
// Parses |excluded_paths| into a list of paths. White space and empty paths are removed.
std::vector<std::filesystem::path> ParseExcludedPaths(std::string_view excluded_paths);
enum class MaybeResizeMinfsResult {
// Minfs was either not resized or successfully resized and can be mounted as it normally would
// be.
kMinfsMountable,
// Minfs was likely corrupted while resizing and the device should be rebooted to trigger a
// factory reset.
kRebootRequired,
};
// For a given block |device| formatted with minfs, resizes minfs if it's not the correct size.
//
// "correct size" is defined as: the size of the minfs partition is less than or equal to
// |partition_size_limit| and the number of inodes in minfs is equal to |required_inodes|.
//
// The resize won't be done if the amount of data in minfs is greater than |data_size_limit| after
// filtering out all of the files and directories that match |excluded_paths|.
//
// This method is slow and may destroy files or corrupt minfs. Not tolerant to power interruptions.
[[nodiscard]] MaybeResizeMinfsResult MaybeResizeMinfs(
zx::channel device, uint64_t partition_size_limit, uint64_t required_inodes,
uint64_t data_size_limit, const std::vector<std::filesystem::path>& excluded_paths,
FsManager& manager);
// RAII wrapper around a mounted minfs that unmounts minfs when destroyed.
class MountedMinfs {
public:
MountedMinfs(MountedMinfs&&) = default;
MountedMinfs(const MountedMinfs&) = delete;
MountedMinfs& operator=(MountedMinfs&&) = default;
MountedMinfs& operator=(const MountedMinfs&) = delete;
~MountedMinfs();
// Mounts minfs on the given block |device|.
static zx::status<MountedMinfs> Mount(zx::channel device);
// Explicitly unmounts minfs and returns any errors instead of swallowing the errors in the
// destructor.
static zx::status<> Unmount(MountedMinfs fs);
// Calls DirectoryAdmin::QueryFilesystem.
zx::status<fuchsia_io::wire::FilesystemInfo> GetFilesystemInfo() const;
// Copies the contents of minfs into ram.
zx::status<Copier> ReadFilesystem(const std::vector<std::filesystem::path>& excluded_paths) const;
// Populates minfs with the contents of |copier|.
zx::status<> PopulateFilesystem(Copier copier) const;
// Creates a file at the root of minfs to indicate that |PopulateFilesystem| was started.
zx::status<> SetResizeInProgress() const;
// Removes the file created by |SetResizeInProgress|.
zx::status<> ClearResizeInProgress() const;
// Returns true if the file created by |SetResizeInProgress| exists.
zx::status<bool> IsResizeInProgress() const;
// Gets a file descriptor to the root directory of minfs.
zx::status<fbl::unique_fd> GetRootFd() const;
private:
explicit MountedMinfs(zx::channel root);
zx::status<> Unmount();
zx::channel root_;
};
} // namespace devmgr
#endif // SRC_STORAGE_FSHOST_MINFS_MANIPULATOR_H_