summaryrefslogtreecommitdiff
path: root/fs_mgr/libsnapshot/utility.h
blob: e69bdadc93b50a5b78a4a1725b27d3f2626e2a26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (C) 2019 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.

#pragma once

#include <functional>
#include <iostream>
#include <string>

#include <android-base/macros.h>
#include <fstab/fstab.h>
#include <libdm/dm.h>
#include <libfiemap/image_manager.h>
#include <liblp/builder.h>
#include <libsnapshot/snapshot.h>
#include <update_engine/update_metadata.pb.h>

#include <libsnapshot/auto_device.h>
#include <libsnapshot/snapshot.h>

namespace android {
namespace snapshot {

// Unit is sectors, this is a 4K chunk.
static constexpr uint32_t kSnapshotChunkSize = 8;

// A list of devices we created along the way.
// - Whenever a device is created that is subject to GC'ed at the end of
//   this function, add it to this list.
// - If any error has occurred, the list is destroyed, and all these devices
//   are cleaned up.
// - Upon success, Release() should be called so that the created devices
//   are kept.
struct AutoDeviceList {
    ~AutoDeviceList();
    template <typename T, typename... Args>
    void EmplaceBack(Args&&... args) {
        devices_.emplace_back(std::make_unique<T>(std::forward<Args>(args)...));
    }
    void Release();

  private:
    std::vector<std::unique_ptr<AutoDevice>> devices_;
};

// Automatically unmap a device upon deletion.
struct AutoUnmapDevice : AutoDevice {
    // On destruct, delete |name| from device mapper.
    AutoUnmapDevice(android::dm::DeviceMapper* dm, const std::string& name)
        : AutoDevice(name), dm_(dm) {}
    AutoUnmapDevice(AutoUnmapDevice&& other) = default;
    ~AutoUnmapDevice();

  private:
    DISALLOW_COPY_AND_ASSIGN(AutoUnmapDevice);
    android::dm::DeviceMapper* dm_ = nullptr;
};

// Automatically unmap an image upon deletion.
struct AutoUnmapImage : AutoDevice {
    // On destruct, delete |name| from image manager.
    AutoUnmapImage(android::fiemap::IImageManager* images, const std::string& name)
        : AutoDevice(name), images_(images) {}
    AutoUnmapImage(AutoUnmapImage&& other) = default;
    ~AutoUnmapImage();

  private:
    DISALLOW_COPY_AND_ASSIGN(AutoUnmapImage);
    android::fiemap::IImageManager* images_ = nullptr;
};

// Automatically deletes a snapshot. |name| should be the name of the partition, e.g. "system_a".
// Client is responsible for maintaining the lifetime of |manager| and |lock|.
struct AutoDeleteSnapshot : AutoDevice {
    AutoDeleteSnapshot(SnapshotManager* manager, SnapshotManager::LockedFile* lock,
                       const std::string& name)
        : AutoDevice(name), manager_(manager), lock_(lock) {}
    AutoDeleteSnapshot(AutoDeleteSnapshot&& other);
    ~AutoDeleteSnapshot();

  private:
    DISALLOW_COPY_AND_ASSIGN(AutoDeleteSnapshot);
    SnapshotManager* manager_ = nullptr;
    SnapshotManager::LockedFile* lock_ = nullptr;
};

struct AutoUnmountDevice : AutoDevice {
    // Empty object that does nothing.
    AutoUnmountDevice() : AutoDevice("") {}
    static std::unique_ptr<AutoUnmountDevice> New(const std::string& path);
    ~AutoUnmountDevice();

  private:
    AutoUnmountDevice(const std::string& path, android::fs_mgr::Fstab&& fstab)
        : AutoDevice(path), fstab_(std::move(fstab)) {}
    android::fs_mgr::Fstab fstab_;
};

// Return a list of partitions in |builder| with the name ending in |suffix|.
std::vector<android::fs_mgr::Partition*> ListPartitionsWithSuffix(
        android::fs_mgr::MetadataBuilder* builder, const std::string& suffix);

// Initialize a device before using it as the COW device for a dm-snapshot device.
Return InitializeCow(const std::string& device);

// "Atomically" write string to file. This is done by a series of actions:
// 1. Write to path + ".tmp"
// 2. Move temporary file to path using rename()
// Note that rename() is an atomic operation. This function may not work properly if there
// is an open fd to |path|, because that fd has an old view of the file.
bool WriteStringToFileAtomic(const std::string& content, const std::string& path);

// Writes current time to a given stream.
struct Now {};
std::ostream& operator<<(std::ostream& os, const Now&);

// Append to |extents|. Merged into the last element if possible.
void AppendExtent(google::protobuf::RepeatedPtrField<chromeos_update_engine::Extent>* extents,
                  uint64_t start_block, uint64_t num_blocks);

}  // namespace snapshot
}  // namespace android