blob: 08da8f60ea84de7b27f4da158199756285b2e5fc [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) {
52 listener->onVolumeStateChanged(getId(), static_cast<int32_t>(mState));
53 }
Jeff Sharkeydeb24052015-03-02 21:01:40 -080054}
55
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070056status_t VolumeBase::setDiskId(const std::string& diskId) {
57 if (mCreated) {
58 LOG(WARNING) << getId() << " diskId change requires destroyed";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080059 return -EBUSY;
60 }
61
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070062 mDiskId = diskId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070063 return OK;
64}
65
Jeff Sharkeybc40cc82015-06-18 14:25:08 -070066status_t VolumeBase::setPartGuid(const std::string& partGuid) {
67 if (mCreated) {
68 LOG(WARNING) << getId() << " partGuid change requires destroyed";
69 return -EBUSY;
70 }
71
72 mPartGuid = partGuid;
73 return OK;
74}
75
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070076status_t VolumeBase::setMountFlags(int mountFlags) {
77 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
78 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -070079 return -EBUSY;
80 }
81
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070082 mMountFlags = mountFlags;
83 return OK;
84}
85
86status_t VolumeBase::setMountUserId(userid_t mountUserId) {
87 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
88 LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
89 return -EBUSY;
90 }
91
92 mMountUserId = mountUserId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070093 return OK;
94}
95
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070096status_t VolumeBase::setSilent(bool silent) {
97 if (mCreated) {
98 LOG(WARNING) << getId() << " silence change requires destroyed";
99 return -EBUSY;
100 }
101
102 mSilent = silent;
103 return OK;
104}
105
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700106status_t VolumeBase::setId(const std::string& id) {
107 if (mCreated) {
108 LOG(WARNING) << getId() << " id change requires not created";
109 return -EBUSY;
110 }
111
112 mId = id;
113 return OK;
114}
115
116status_t VolumeBase::setPath(const std::string& path) {
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700117 if (mState != State::kChecking) {
118 LOG(WARNING) << getId() << " path change requires state checking";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700119 return -EBUSY;
120 }
121
122 mPath = path;
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600123
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600124 auto listener = getListener();
125 if (listener) listener->onVolumePathChanged(getId(), mPath);
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600126
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700127 return OK;
128}
129
Jeff Sharkey1d6fbcc2015-04-24 16:00:03 -0700130status_t VolumeBase::setInternalPath(const std::string& internalPath) {
131 if (mState != State::kChecking) {
132 LOG(WARNING) << getId() << " internal path change requires state checking";
133 return -EBUSY;
134 }
135
136 mInternalPath = internalPath;
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600137
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600138 auto listener = getListener();
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700139 if (listener) {
140 listener->onVolumeInternalPathChanged(getId(), mInternalPath);
141 }
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600142
Jeff Sharkey1d6fbcc2015-04-24 16:00:03 -0700143 return OK;
144}
145
Nandana Dutta914cc72019-08-29 15:22:42 +0100146status_t VolumeBase::setFuseFd(android::base::unique_fd fuseFd) {
147 if ((mState != State::kChecking) && (mState != State::kEjecting)) {
148 LOG(WARNING) << getId() << " fuse fd change requires state checking or ejecting";
Zim3623a212019-07-19 16:46:53 +0100149 return -EBUSY;
150 }
151
Nandana Dutt23edfac2019-09-03 12:44:08 +0100152 mFuseFd = std::move(fuseFd);
Zim3623a212019-07-19 16:46:53 +0100153 return OK;
154}
155
Greg Kaiser2bc201e2018-12-18 08:42:08 -0800156android::sp<android::os::IVoldListener> VolumeBase::getListener() const {
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600157 if (mSilent) {
158 return nullptr;
159 } else {
160 return VolumeManager::Instance()->getListener();
161 }
162}
163
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700164void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
165 mVolumes.push_back(volume);
166}
167
168void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
169 mVolumes.remove(volume);
170}
171
172std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
173 for (auto vol : mVolumes) {
174 if (vol->getId() == id) {
175 return vol;
176 }
177 }
178 return nullptr;
179}
180
181status_t VolumeBase::create() {
182 CHECK(!mCreated);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700183
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700184 mCreated = true;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700185 status_t res = doCreate();
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600186
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600187 auto listener = getListener();
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700188 if (listener) {
189 listener->onVolumeCreated(getId(), static_cast<int32_t>(mType), mDiskId, mPartGuid);
190 }
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600191
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700192 setState(State::kUnmounted);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700193 return res;
194}
195
196status_t VolumeBase::doCreate() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700197 return OK;
198}
199
200status_t VolumeBase::destroy() {
201 CHECK(mCreated);
202
203 if (mState == State::kMounted) {
204 unmount();
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700205 setState(State::kBadRemoval);
206 } else {
207 setState(State::kRemoved);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700208 }
209
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600210 auto listener = getListener();
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700211 if (listener) {
212 listener->onVolumeDestroyed(getId());
213 }
Jeff Sharkeycbe69fc2017-09-15 16:50:28 -0600214
Jeff Sharkey9c484982015-03-31 10:35:33 -0700215 status_t res = doDestroy();
216 mCreated = false;
217 return res;
218}
219
220status_t VolumeBase::doDestroy() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700221 return OK;
222}
223
224status_t VolumeBase::mount() {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700225 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
226 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700227 return -EBUSY;
228 }
229
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700230 setState(State::kChecking);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800231 status_t res = doMount();
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700232 setState(res == OK ? State::kMounted : State::kUnmountable);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800233
234 return res;
235}
236
237status_t VolumeBase::unmount() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700238 if (mState != State::kMounted) {
239 LOG(WARNING) << getId() << " unmount requires state mounted";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800240 return -EBUSY;
241 }
242
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700243 setState(State::kEjecting);
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700244 for (const auto& vol : mVolumes) {
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700245 if (vol->destroy()) {
Paul Crowleyedf7a4e2018-09-18 15:14:18 -0700246 LOG(WARNING) << getId() << " failed to destroy " << vol->getId() << " stacked above";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800247 }
248 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700249 mVolumes.clear();
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800250
Sudheer Shanka4112c122019-04-29 10:46:35 -0700251 status_t res = doUnmount();
252 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800253 return res;
254}
255
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700256status_t VolumeBase::format(const std::string& fsType) {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700257 if (mState == State::kMounted) {
258 unmount();
259 }
260
261 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
262 LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800263 return -EBUSY;
264 }
265
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700266 setState(State::kFormatting);
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700267 status_t res = doFormat(fsType);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700268 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800269 return res;
270}
271
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700272status_t VolumeBase::doFormat(const std::string& fsType) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800273 return -ENOTSUP;
274}
275
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700276std::ostream& VolumeBase::operator<<(std::ostream& stream) const {
Sudheer Shanka4112c122019-04-29 10:46:35 -0700277 return stream << " VolumeBase{id=" << mId << ",mountFlags=" << mMountFlags
278 << ",mountUserId=" << mMountUserId << "}";
Sudheer Shanka40ab6742018-09-18 13:07:45 -0700279}
280
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800281} // namespace vold
282} // namespace android