blob: e20a049d31957ff58b9a92cba148802b86980db7 [file] [log] [blame]
Jeff Sharkeydeb24052015-03-02 21:01:40 -08001/*
2 * Copyright (C) 2015 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
Jeff Sharkeydeb24052015-03-02 21:01:40 -080017#include "VolumeBase.h"
Paul Crowleyedf7a4e2018-09-18 15:14:18 -070018#include "Utils.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070019#include "VolumeManager.h"
Jeff Sharkeydeb24052015-03-02 21:01:40 -080020
Elliott Hughes7e128fb2015-12-04 15:50:53 -080021#include <android-base/logging.h>
Paul Crowleyedf7a4e2018-09-18 15:14:18 -070022#include <android-base/stringprintf.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080023
24#include <fcntl.h>
25#include <stdlib.h>
26#include <sys/mount.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29
Jeff Sharkey36801cc2015-03-13 16:09:20 -070030using android::base::StringPrintf;
31
Jeff Sharkeydeb24052015-03-02 21:01:40 -080032namespace android {
33namespace vold {
34
Paul Crowleyedf7a4e2018-09-18 15:14:18 -070035VolumeBase::VolumeBase(Type type)
36 : mType(type),
37 mMountFlags(0),
Sudheer Shanka40ab6742018-09-18 13:07:45 -070038 mMountUserId(USER_UNKNOWN),
Paul Crowleyedf7a4e2018-09-18 15:14:18 -070039 mCreated(false),
40 mState(State::kUnmounted),
41 mSilent(false) {}
Jeff Sharkeydeb24052015-03-02 21:01:40 -080042
43VolumeBase::~VolumeBase() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -070044 CHECK(!mCreated);
Jeff Sharkeydeb24052015-03-02 21:01:40 -080045}
46
Jeff Sharkey36801cc2015-03-13 16:09:20 -070047void VolumeBase::setState(State state) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -080048 mState = state;
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -060049
Jeff Sharkey814e9d32017-09-13 11:49:44 -060050 auto listener = getListener();
Paul Crowleyedf7a4e2018-09-18 15:14:18 -070051 if (listener) {
Arnab Senf96d81f2023-07-11 18:14:18 +053052 listener->onVolumeStateChanged(getId(), static_cast<int32_t>(mState),
53 static_cast<int32_t>(mMountUserId));
Paul Crowleyedf7a4e2018-09-18 15:14:18 -070054 }
Jeff Sharkeydeb24052015-03-02 21:01:40 -080055}
56
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070057status_t VolumeBase::setDiskId(const std::string& diskId) {
58 if (mCreated) {
59 LOG(WARNING) << getId() << " diskId change requires destroyed";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080060 return -EBUSY;
61 }
62
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070063 mDiskId = diskId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070064 return OK;
65}
66
Jeff Sharkeybc40cc82015-06-18 14:25:08 -070067status_t VolumeBase::setPartGuid(const std::string& partGuid) {
68 if (mCreated) {
69 LOG(WARNING) << getId() << " partGuid change requires destroyed";
70 return -EBUSY;
71 }
72
73 mPartGuid = partGuid;
74 return OK;
75}
76
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070077status_t VolumeBase::setMountFlags(int mountFlags) {
78 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
79 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -070080 return -EBUSY;
81 }
82
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070083 mMountFlags = mountFlags;
84 return OK;
85}
86
87status_t VolumeBase::setMountUserId(userid_t mountUserId) {
88 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
89 LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
90 return -EBUSY;
91 }
92
93 mMountUserId = mountUserId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070094 return OK;
95}
96
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070097status_t VolumeBase::setSilent(bool silent) {
98 if (mCreated) {
99 LOG(WARNING) << getId() << " silence change requires destroyed";
100 return -EBUSY;
101 }
102
103 mSilent = silent;
104 return OK;
105}
106
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700107status_t VolumeBase::setId(const std::string& id) {
108 if (mCreated) {
109 LOG(WARNING) << getId() << " id change requires not created";
110 return -EBUSY;
111 }
112
113 mId = id;
114 return OK;
115}
116
117status_t VolumeBase::setPath(const std::string& path) {
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700118 if (mState != State::kChecking) {
119 LOG(WARNING) << getId() << " path change requires state checking";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700120 return -EBUSY;
121 }
122
123 mPath = path;
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600124
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600125 auto listener = getListener();
126 if (listener) listener->onVolumePathChanged(getId(), mPath);
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600127
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700128 return OK;
129}
130
Jeff Sharkey1d6fbcc2015-04-24 16:00:03 -0700131status_t VolumeBase::setInternalPath(const std::string& internalPath) {
132 if (mState != State::kChecking) {
133 LOG(WARNING) << getId() << " internal path change requires state checking";
134 return -EBUSY;
135 }
136
137 mInternalPath = internalPath;
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600138
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600139 auto listener = getListener();
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700140 if (listener) {
141 listener->onVolumeInternalPathChanged(getId(), mInternalPath);
142 }
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600143
Jeff Sharkey1d6fbcc2015-04-24 16:00:03 -0700144 return OK;
145}
146
Zim5048b4b2019-11-19 09:16:03 +0000147status_t VolumeBase::setMountCallback(
148 const android::sp<android::os::IVoldMountCallback>& callback) {
149 mMountCallback = callback;
Zim3623a212019-07-19 16:46:53 +0100150 return OK;
151}
152
Zim5048b4b2019-11-19 09:16:03 +0000153sp<android::os::IVoldMountCallback> VolumeBase::getMountCallback() const {
154 return mMountCallback;
155}
156
Greg Kaiser2bc201e2018-12-18 08:42:08 -0800157android::sp<android::os::IVoldListener> VolumeBase::getListener() const {
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600158 if (mSilent) {
159 return nullptr;
160 } else {
161 return VolumeManager::Instance()->getListener();
162 }
163}
164
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700165void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
166 mVolumes.push_back(volume);
167}
168
169void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
170 mVolumes.remove(volume);
171}
172
173std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
174 for (auto vol : mVolumes) {
175 if (vol->getId() == id) {
176 return vol;
177 }
178 }
179 return nullptr;
180}
181
182status_t VolumeBase::create() {
183 CHECK(!mCreated);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700184
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700185 mCreated = true;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700186 status_t res = doCreate();
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600187
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600188 auto listener = getListener();
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700189 if (listener) {
Zima438b242019-09-25 14:37:38 +0100190 listener->onVolumeCreated(getId(), static_cast<int32_t>(mType), mDiskId, mPartGuid,
191 mMountUserId);
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700192 }
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600193
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700194 setState(State::kUnmounted);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700195 return res;
196}
197
198status_t VolumeBase::doCreate() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700199 return OK;
200}
201
202status_t VolumeBase::destroy() {
203 CHECK(mCreated);
204
205 if (mState == State::kMounted) {
206 unmount();
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700207 setState(State::kBadRemoval);
208 } else {
209 setState(State::kRemoved);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700210 }
211
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600212 auto listener = getListener();
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700213 if (listener) {
214 listener->onVolumeDestroyed(getId());
215 }
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600216
Jeff Sharkey9c484982015-03-31 10:35:33 -0700217 status_t res = doDestroy();
218 mCreated = false;
219 return res;
220}
221
222status_t VolumeBase::doDestroy() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700223 return OK;
224}
225
226status_t VolumeBase::mount() {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700227 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
228 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700229 return -EBUSY;
230 }
231
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700232 setState(State::kChecking);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800233 status_t res = doMount();
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700234 setState(res == OK ? State::kMounted : State::kUnmountable);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800235
Martijn Coenen5ec86582020-05-04 14:57:35 +0200236 if (res == OK) {
237 doPostMount();
238 }
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800239 return res;
240}
241
Martijn Coenen5ec86582020-05-04 14:57:35 +0200242void VolumeBase::doPostMount() {}
243
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800244status_t VolumeBase::unmount() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700245 if (mState != State::kMounted) {
246 LOG(WARNING) << getId() << " unmount requires state mounted";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800247 return -EBUSY;
248 }
249
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700250 setState(State::kEjecting);
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700251 for (const auto& vol : mVolumes) {
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700252 if (vol->destroy()) {
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700253 LOG(WARNING) << getId() << " failed to destroy " << vol->getId() << " stacked above";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800254 }
255 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700256 mVolumes.clear();
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800257
Sudheer Shanka4112c122019-04-29 10:46:35 -0700258 status_t res = doUnmount();
259 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800260 return res;
261}
262
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700263status_t VolumeBase::format(const std::string& fsType) {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700264 if (mState == State::kMounted) {
265 unmount();
266 }
267
268 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
269 LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800270 return -EBUSY;
271 }
272
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700273 setState(State::kFormatting);
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700274 status_t res = doFormat(fsType);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700275 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800276 return res;
277}
278
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700279status_t VolumeBase::doFormat(const std::string& fsType) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800280 return -ENOTSUP;
281}
282
Martijn Coenen62a4b272020-01-31 15:23:09 +0100283std::string VolumeBase::getRootPath() const {
284 // Usually the same as the internal path, except for emulated volumes.
285 return getInternalPath();
286}
287
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700288std::ostream& VolumeBase::operator<<(std::ostream& stream) const {
Sudheer Shanka4112c122019-04-29 10:46:35 -0700289 return stream << " VolumeBase{id=" << mId << ",mountFlags=" << mMountFlags
290 << ",mountUserId=" << mMountUserId << "}";
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700291}
292
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800293} // namespace vold
294} // namespace android