blob: 742e510d5275aa7244841f503388f2246b0cc7f1 [file] [log] [blame]
Ben Chan1e5a0cb2012-03-22 00:41:52 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Ben Chan8dcede82011-07-25 20:56:13 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Chand30e7432011-11-28 13:43:17 -08005// Defines cros-disks::MountManager, which is a base class for implementing
6// the filesystem mounting service used by CrosDisksServer. It is further
7// subclassed to provide the mounting service for particular types of
8// filesystem.
9
Ben Chan8dcede82011-07-25 20:56:13 -070010#ifndef CROS_DISKS_MOUNT_MANAGER_H_
11#define CROS_DISKS_MOUNT_MANAGER_H_
12
Anand K Mistrye9a60fb2019-11-07 16:41:03 +110013#include <memory>
Ben Chan8dcede82011-07-25 20:56:13 -070014#include <string>
Sergei Datsenko7e7c7642021-01-08 19:15:34 +110015#include <unordered_map>
Ben Chan8dcede82011-07-25 20:56:13 -070016#include <vector>
17
Anand K Mistry09f2db12019-11-07 17:06:56 +110018#include <base/files/file_path.h>
Anand K Mistrye9a60fb2019-11-07 16:41:03 +110019#include <base/optional.h>
Ben Chan6d0b2722011-11-18 08:24:14 -080020#include <chromeos/dbus/service_constants.h>
Ben Chan8dcede82011-07-25 20:56:13 -070021#include <gtest/gtest_prod.h>
22
Ben Chan0214e302017-10-17 15:39:16 -070023#include "cros-disks/mount_entry.h"
Anand K Mistrye9a60fb2019-11-07 16:41:03 +110024#include "cros-disks/mount_point.h"
Tatsuhisa Yamaguchi5a6a3032016-08-19 20:03:54 +090025
Sergei Datsenkoa910bba2019-06-18 13:31:59 +100026namespace brillo {
27class ProcessReaper;
28} // namespace brillo
29
Ben Chan8dcede82011-07-25 20:56:13 -070030namespace cros_disks {
31
Ben Chanbe2b4a72011-11-08 13:42:23 -080032class Metrics;
Ben Chan8dcede82011-07-25 20:56:13 -070033class Platform;
34
35// A base class for managing mounted filesystems of certain kinds.
36// It provides template methods for mounting and unmounting filesystems.
Anand K Mistry2481ce82020-01-24 14:46:53 +110037// A derived class implements pure virtual methods CanMount, DoMount, and
38// SuggestMountPath to provide specific operations for supporting certain kinds
39// of filesystem.
Ben Chan8dcede82011-07-25 20:56:13 -070040class MountManager {
41 public:
Ben Chand30e7432011-11-28 13:43:17 -080042 // Constructor that takes a mount root directory, an object for providing
43 // platform service, and an object for collecting UMA metrics. The mount
44 // root directory |mount_root| must be a non-empty path string, but it is
45 // OK if the directory does not exist. Both |platform| and |metrics| must
46 // be a valid object. An instance of this class does not take ownership
47 // of the |platform| and |metrics| object, and thus expects these objects
48 // to exist until its destruction. No actual operation is performed at
49 // construction. Initialization is performed when Initializes() is called.
Ben Chande0e3f62017-09-26 06:28:39 -070050 MountManager(const std::string& mount_root,
51 Platform* platform,
Sergei Datsenkoa910bba2019-06-18 13:31:59 +100052 Metrics* metrics,
53 brillo::ProcessReaper* process_reaper);
Qijiang Fan6bc59e12020-11-11 02:51:06 +090054 MountManager(const MountManager&) = delete;
55 MountManager& operator=(const MountManager&) = delete;
Ben Chand30e7432011-11-28 13:43:17 -080056
57 // Destructor that performs no specific operations and does not unmount
58 // any mounted or reserved mount paths. A derived class should override
59 // the destructor to perform appropriate cleanup, such as unmounting
60 // mounted filesystems.
Ben Chan8dcede82011-07-25 20:56:13 -070061 virtual ~MountManager();
62
63 // Initializes the mount manager. Returns true on success.
Ben Chand30e7432011-11-28 13:43:17 -080064 // It must be called only once before other methods are called.
Ben Chan8dcede82011-07-25 20:56:13 -070065 // This base class provides a default implementation that creates the
66 // mount root directory. A derived class can override this method to
67 // perform any necessary initialization.
68 virtual bool Initialize();
69
Ben Chanb3bf8d12013-04-23 13:57:55 -070070 // Starts a session. Returns true on success.
Ben Chan8dcede82011-07-25 20:56:13 -070071 // This base class provides a default implementation that does nothing.
72 // A derived class can override this method to perform any necessary
Ben Chand30e7432011-11-28 13:43:17 -080073 // operations when a session starts. This method is called in response
74 // to a SessionStateChanged event from the Chromium OS session manager.
Ben Chanb3bf8d12013-04-23 13:57:55 -070075 virtual bool StartSession();
Ben Chan8dcede82011-07-25 20:56:13 -070076
Ben Chanb3bf8d12013-04-23 13:57:55 -070077 // Stops a session. Returns true on success.
Ben Chan2d733562019-03-18 23:55:10 -070078 // This base class provides a default implementation that calls UnmountAll()
79 // to unmount all mounted paths managed by this mount manager.
Ben Chan8dcede82011-07-25 20:56:13 -070080 // A derived class can override this method to perform any necessary
Ben Chand30e7432011-11-28 13:43:17 -080081 // operations when a session stops. This method is called in response
82 // to a SessionStateChanged event from the Chromium OS session manager.
Ben Chanb3bf8d12013-04-23 13:57:55 -070083 virtual bool StopSession();
Ben Chan8dcede82011-07-25 20:56:13 -070084
85 // Implemented by a derived class to return true if it supports mounting
86 // |source_path|.
87 virtual bool CanMount(const std::string& source_path) const = 0;
88
Ben Chan8dcede82011-07-25 20:56:13 -070089 // Implemented by a derived class to return the type of mount sources
90 // it supports.
91 virtual MountSourceType GetMountSourceType() const = 0;
92
93 // Mounts |source_path| to |mount_path| as |filesystem_type| with |options|.
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +090094 // If "remount" option exists in |options|, attempts to remount |source_path|
95 // to the mount path which it's currently mounted to. Content of |mount_path|
96 // will be ignored and |mount_path| is set to the existing mount path.
97 // Otherwise, attempts to mount a new source. When mounting a new source, if
98 // |mount_path| is an empty string, SuggestMountPath() is called to obtain a
99 // suggested mount path. |mount_path| is set to actual mount path on success.
100 // If an error occurs and ShouldReserveMountPathOnError() returns true for
101 // that type of error, the mount path is reserved and |mount_path| is set to
102 // the reserved mount path.
Ben Chan8dcede82011-07-25 20:56:13 -0700103 MountErrorType Mount(const std::string& source_path,
104 const std::string& filesystem_type,
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100105 std::vector<std::string> options,
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900106 std::string* mount_path);
Ben Chan8dcede82011-07-25 20:56:13 -0700107
Anand K Mistry5a6d5fa2019-11-05 17:21:48 +1100108 // Unmounts |path|, which can be a source path or a mount path. If the mount
109 // path is reserved during Mount(), this method releases the reserved mount
110 // path.
111 MountErrorType Unmount(const std::string& path);
Ben Chan8dcede82011-07-25 20:56:13 -0700112
113 // Unmounts all mounted paths.
Ben Chan1e5a0cb2012-03-22 00:41:52 -0700114 virtual bool UnmountAll();
Ben Chan8dcede82011-07-25 20:56:13 -0700115
Ben Chan7dfb8102017-10-17 15:47:37 -0700116 // Returns the mount entries managed by this mount manager.
117 std::vector<MountEntry> GetMountEntries() const;
Ben Chan8fb742b2014-04-28 23:46:57 -0700118
Ben Chan8dcede82011-07-25 20:56:13 -0700119 protected:
Tatsuhisa Yamaguchi5a6a3032016-08-19 20:03:54 +0900120 // Type definition of a cache mapping a source path to its mount state of
Ben Chan8dcede82011-07-25 20:56:13 -0700121 // filesystems mounted by the manager.
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100122 using MountStateMap =
123 std::unordered_map<std::string, std::unique_ptr<MountPoint>>;
Ben Chan8dcede82011-07-25 20:56:13 -0700124
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100125 MountPoint* FindMountBySource(const std::string& source);
126 MountPoint* FindMountByMountPath(const base::FilePath& path);
127 bool RemoveMount(MountPoint* mount_point);
Sergei Datsenko0ba12032021-01-07 08:51:14 +1100128
Ben Chan632c9f82011-10-11 12:22:16 -0700129 // Type definition of a cache mapping a reserved mount path to the mount
130 // error that caused the mount path to be reserved.
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100131 using ReservedMountPathMap =
132 std::unordered_map<base::FilePath, MountErrorType>;
Ben Chan632c9f82011-10-11 12:22:16 -0700133
Jorge Lucangeli Obes0a388a22020-04-06 11:43:21 -0400134 // The base class calls Platform::GetRealPath(), derived classes can override
135 // it.
136 virtual bool ResolvePath(const std::string& path, std::string* real_path);
137
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900138 // Mounts |source_path| to |mount_path| as |filesystem_type| with |options|.
139 MountErrorType MountNewSource(const std::string& source_path,
140 const std::string& filesystem_type,
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100141 std::vector<std::string> options,
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900142 std::string* mount_path);
143
144 // Remounts |source_path| on |mount_path| as |filesystem_type| with |options|.
145 MountErrorType Remount(const std::string& source_path,
146 const std::string& filesystem_type,
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100147 std::vector<std::string> options,
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900148 std::string* mount_path);
149
Nigel Taoca7a4ef2021-05-14 11:44:25 +1000150 // Implemented by a derived class to mount |source_path| to |mount_path| as
151 // |filesystem_type| with |options|. An implementation may append their own
152 // mount options to |options|. On success, an implementation MUST set |error|
153 // to MOUNT_ERROR_NONE and return a non-null MountPoint. On failure, |error|
154 // must be set to an appropriate error code and nullptr is returned.
Anand K Mistryd0a05232020-01-24 14:04:18 +1100155 virtual std::unique_ptr<MountPoint> DoMount(
Anand K Mistryf41a6962019-12-19 17:41:04 +1100156 const std::string& source_path,
157 const std::string& filesystem_type,
158 const std::vector<std::string>& options,
159 const base::FilePath& mount_path,
Anand K Mistryd0a05232020-01-24 14:04:18 +1100160 MountErrorType* error) = 0;
Ben Chan8dcede82011-07-25 20:56:13 -0700161
Ben Chan8dcede82011-07-25 20:56:13 -0700162 // Returns a suggested mount path for |source_path|.
163 virtual std::string SuggestMountPath(
164 const std::string& source_path) const = 0;
165
Ben Chanf8692882011-08-21 10:15:30 -0700166 // Returns true if the manager should reserve a mount path if the mount
167 // operation returns a particular type of error. The default implementation
168 // returns false on any error. A derived class should override this method
169 // if it needs to reserve mount paths on certain types of error.
170 virtual bool ShouldReserveMountPathOnError(MountErrorType error_type) const;
171
Ben Chan8dcede82011-07-25 20:56:13 -0700172 // Returns true if |path| is an immediate child of |parent|, i.e.
173 // |path| is an immediate file or directory under |parent|.
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100174 static bool IsPathImmediateChildOfParent(const base::FilePath& path,
175 const base::FilePath& parent);
Ben Chan8dcede82011-07-25 20:56:13 -0700176
Ben Chanadc5d002014-03-12 15:02:26 -0700177 // Returns true if |mount_path| is a valid mount path, which should be an
178 // immediate child of the mount root specified by |mount_root_|. The check
179 // performed by this method takes the simplest approach and does not first try
180 // to canonicalize |mount_path|, resolve symlinks or determine the absolute
181 // path of |mount_path|, so a legitimate mount path may be deemed as invalid.
182 // But we don't consider these cases as part of the use cases of cros-disks.
Anand K Mistry09f2db12019-11-07 17:06:56 +1100183 bool IsValidMountPath(const base::FilePath& mount_path) const;
Ben Chanadc5d002014-03-12 15:02:26 -0700184
Ben Chan9ed09e32011-11-22 16:24:06 -0800185 // Returns the root directory under which mount directories are created.
Anand K Mistry09f2db12019-11-07 17:06:56 +1100186 const base::FilePath& mount_root() const { return mount_root_; }
Ben Chan8dcede82011-07-25 20:56:13 -0700187
Ben Chan9ed09e32011-11-22 16:24:06 -0800188 // Returns an object that provides platform service.
Ben Chan930f18d2011-11-21 09:18:50 -0800189 Platform* platform() const { return platform_; }
190
Ben Chan9ed09e32011-11-22 16:24:06 -0800191 // Returns an object that collects UMA metrics.
Ben Chan930f18d2011-11-21 09:18:50 -0800192 Metrics* metrics() const { return metrics_; }
193
Sergei Datsenkoa910bba2019-06-18 13:31:59 +1000194 // Returns an object that monitors children processes.
195 brillo::ProcessReaper* process_reaper() const { return process_reaper_; }
196
Ben Chan930f18d2011-11-21 09:18:50 -0800197 private:
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100198 // Prepares empty directory to mount into. If |mount_path| contains a path
199 // it may be used, but not necessarily. Returns the status of the operation
200 // and if successful - fills |mount_path|.
201 MountErrorType CreateMountPathForSource(const std::string& source,
202 const std::string& label,
203 base::FilePath* mount_path);
204
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100205 // Returns true if |mount_path| is reserved.
206 bool IsMountPathReserved(const base::FilePath& mount_path) const;
207
208 // Returns the mount error that caused |mount_path| to be reserved, or
209 // kMountErrorNone if |mount_path| is not a reserved path.
210 MountErrorType GetMountErrorOfReservedMountPath(
211 const base::FilePath& mount_path) const;
212
213 // Adds |mount_path| to the set of reserved mount paths. Also records
214 // |error_type| that caused the mount path to be reserved. If a |mount_path|
215 // has been reserved, subsequent calls to this method with the same
216 // |mount_path| but different |error_type| are ignored.
217 void ReserveMountPath(base::FilePath mount_path, MountErrorType error_type);
218
219 // Removes |mount_path| from the set of reserved mount paths.
220 void UnreserveMountPath(const base::FilePath& mount_path);
221
Ben Chan8dcede82011-07-25 20:56:13 -0700222 // The root directory under which mount directories are created.
Anand K Mistry09f2db12019-11-07 17:06:56 +1100223 const base::FilePath mount_root_;
Ben Chan8dcede82011-07-25 20:56:13 -0700224
Ben Chan8dcede82011-07-25 20:56:13 -0700225 // An object that provides platform service.
Sergei Datsenkoa910bba2019-06-18 13:31:59 +1000226 Platform* const platform_;
Ben Chan8dcede82011-07-25 20:56:13 -0700227
Ben Chanbe2b4a72011-11-08 13:42:23 -0800228 // An object that collects UMA metrics.
Sergei Datsenkoa910bba2019-06-18 13:31:59 +1000229 Metrics* const metrics_;
230
231 // Object that monitors children processes.
232 brillo::ProcessReaper* const process_reaper_;
Ben Chanbe2b4a72011-11-08 13:42:23 -0800233
Tatsuhisa Yamaguchi5a6a3032016-08-19 20:03:54 +0900234 // A cache mapping a source path to its mount state of filesystems mounted
Ben Chan930f18d2011-11-21 09:18:50 -0800235 // by the manager.
Tatsuhisa Yamaguchi5a6a3032016-08-19 20:03:54 +0900236 MountStateMap mount_states_;
Ben Chan930f18d2011-11-21 09:18:50 -0800237
238 // A cache mapping a reserved mount path to the error that caused
239 // the path to reserved.
240 ReservedMountPathMap reserved_mount_paths_;
241
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100242 friend class MountManagerUnderTest;
243
Ben Chan09c90d02012-04-25 22:09:09 -0700244 FRIEND_TEST(MountManagerTest, ExtractMountLabelFromOptions);
245 FRIEND_TEST(MountManagerTest, ExtractMountLabelFromOptionsWithNoMountLabel);
246 FRIEND_TEST(MountManagerTest, ExtractMountLabelFromOptionsWithTwoMountLabels);
Ben Chan8dcede82011-07-25 20:56:13 -0700247 FRIEND_TEST(MountManagerTest, IsPathImmediateChildOfParent);
Ben Chanadc5d002014-03-12 15:02:26 -0700248 FRIEND_TEST(MountManagerTest, IsValidMountPath);
Ben Chan8dcede82011-07-25 20:56:13 -0700249};
250
251} // namespace cros_disks
252
253#endif // CROS_DISKS_MOUNT_MANAGER_H_