blob: b2eff3b0b2981503a9b541a4854834bb7d55d7b6 [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 "Utils.h"
18#include "VolumeBase.h"
Jeff Sharkey36801cc2015-03-13 16:09:20 -070019#include "VolumeManager.h"
20#include "ResponseCode.h"
Jeff Sharkeydeb24052015-03-02 21:01:40 -080021
Elliott Hughes7e128fb2015-12-04 15:50:53 -080022#include <android-base/stringprintf.h>
23#include <android-base/logging.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080024
25#include <fcntl.h>
26#include <stdlib.h>
27#include <sys/mount.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30
Jeff Sharkey36801cc2015-03-13 16:09:20 -070031using android::base::StringPrintf;
32
Jeff Sharkeydeb24052015-03-02 21:01:40 -080033namespace android {
34namespace vold {
35
Jeff Sharkey36801cc2015-03-13 16:09:20 -070036VolumeBase::VolumeBase(Type type) :
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070037 mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState(
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070038 State::kUnmounted), mSilent(false) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -080039}
40
41VolumeBase::~VolumeBase() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -070042 CHECK(!mCreated);
Jeff Sharkeydeb24052015-03-02 21:01:40 -080043}
44
Jeff Sharkey36801cc2015-03-13 16:09:20 -070045void VolumeBase::setState(State state) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -080046 mState = state;
Jeff Sharkey814e9d32017-09-13 11:49:44 -060047#if ENABLE_BINDER
48 auto listener = getListener();
49 if (listener) listener->onVolumeStateChanged(getId(), static_cast<int32_t>(mState));
50#else
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070051 notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState));
Jeff Sharkey814e9d32017-09-13 11:49:44 -060052#endif
Jeff Sharkeydeb24052015-03-02 21:01:40 -080053}
54
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070055status_t VolumeBase::setDiskId(const std::string& diskId) {
56 if (mCreated) {
57 LOG(WARNING) << getId() << " diskId change requires destroyed";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080058 return -EBUSY;
59 }
60
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070061 mDiskId = diskId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070062 return OK;
63}
64
Jeff Sharkeybc40cc82015-06-18 14:25:08 -070065status_t VolumeBase::setPartGuid(const std::string& partGuid) {
66 if (mCreated) {
67 LOG(WARNING) << getId() << " partGuid change requires destroyed";
68 return -EBUSY;
69 }
70
71 mPartGuid = partGuid;
72 return OK;
73}
74
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070075status_t VolumeBase::setMountFlags(int mountFlags) {
76 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
77 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -070078 return -EBUSY;
79 }
80
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070081 mMountFlags = mountFlags;
82 return OK;
83}
84
85status_t VolumeBase::setMountUserId(userid_t mountUserId) {
86 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
87 LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
88 return -EBUSY;
89 }
90
91 mMountUserId = mountUserId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070092 return OK;
93}
94
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070095status_t VolumeBase::setSilent(bool silent) {
96 if (mCreated) {
97 LOG(WARNING) << getId() << " silence change requires destroyed";
98 return -EBUSY;
99 }
100
101 mSilent = silent;
102 return OK;
103}
104
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700105status_t VolumeBase::setId(const std::string& id) {
106 if (mCreated) {
107 LOG(WARNING) << getId() << " id change requires not created";
108 return -EBUSY;
109 }
110
111 mId = id;
112 return OK;
113}
114
115status_t VolumeBase::setPath(const std::string& path) {
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700116 if (mState != State::kChecking) {
117 LOG(WARNING) << getId() << " path change requires state checking";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700118 return -EBUSY;
119 }
120
121 mPath = path;
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600122#if ENABLE_BINDER
123 auto listener = getListener();
124 if (listener) listener->onVolumePathChanged(getId(), mPath);
125#else
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700126 notifyEvent(ResponseCode::VolumePathChanged, mPath);
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600127#endif
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 Sharkey814e9d32017-09-13 11:49:44 -0600138#if ENABLE_BINDER
139 auto listener = getListener();
140 if (listener) listener->onVolumeInternalPathChanged(getId(), mInternalPath);
141#else
Jeff Sharkey1d6fbcc2015-04-24 16:00:03 -0700142 notifyEvent(ResponseCode::VolumeInternalPathChanged, mInternalPath);
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600143#endif
Jeff Sharkey1d6fbcc2015-04-24 16:00:03 -0700144 return OK;
145}
146
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700147void VolumeBase::notifyEvent(int event) {
148 if (mSilent) return;
149 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
150 getId().c_str(), false);
151}
152
153void VolumeBase::notifyEvent(int event, const std::string& value) {
154 if (mSilent) return;
155 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
156 StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false);
157}
158
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600159android::sp<android::os::IVoldListener> VolumeBase::getListener() {
160 if (mSilent) {
161 return nullptr;
162 } else {
163 return VolumeManager::Instance()->getListener();
164 }
165}
166
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700167void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
168 mVolumes.push_back(volume);
169}
170
171void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
172 mVolumes.remove(volume);
173}
174
175std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
176 for (auto vol : mVolumes) {
177 if (vol->getId() == id) {
178 return vol;
179 }
180 }
181 return nullptr;
182}
183
184status_t VolumeBase::create() {
185 CHECK(!mCreated);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700186
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700187 mCreated = true;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700188 status_t res = doCreate();
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600189#if ENABLE_BINDER
190 auto listener = getListener();
191 if (listener) listener->onVolumeCreated(getId(),
192 static_cast<int32_t>(mType), mDiskId, mPartGuid);
193#else
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700194 notifyEvent(ResponseCode::VolumeCreated,
195 StringPrintf("%d \"%s\" \"%s\"", mType, mDiskId.c_str(), mPartGuid.c_str()));
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600196#endif
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700197 setState(State::kUnmounted);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700198 return res;
199}
200
201status_t VolumeBase::doCreate() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700202 return OK;
203}
204
205status_t VolumeBase::destroy() {
206 CHECK(mCreated);
207
208 if (mState == State::kMounted) {
209 unmount();
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700210 setState(State::kBadRemoval);
211 } else {
212 setState(State::kRemoved);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700213 }
214
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600215#if ENABLE_BINDER
216 auto listener = getListener();
217 if (listener) listener->onVolumeDestroyed(getId());
218#else
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700219 notifyEvent(ResponseCode::VolumeDestroyed);
Jeff Sharkey814e9d32017-09-13 11:49:44 -0600220#endif
Jeff Sharkey9c484982015-03-31 10:35:33 -0700221 status_t res = doDestroy();
222 mCreated = false;
223 return res;
224}
225
226status_t VolumeBase::doDestroy() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700227 return OK;
228}
229
230status_t VolumeBase::mount() {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700231 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
232 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700233 return -EBUSY;
234 }
235
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700236 setState(State::kChecking);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800237 status_t res = doMount();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700238 if (res == OK) {
239 setState(State::kMounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800240 } else {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700241 setState(State::kUnmountable);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800242 }
243
244 return res;
245}
246
247status_t VolumeBase::unmount() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700248 if (mState != State::kMounted) {
249 LOG(WARNING) << getId() << " unmount requires state mounted";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800250 return -EBUSY;
251 }
252
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700253 setState(State::kEjecting);
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700254 for (const auto& vol : mVolumes) {
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700255 if (vol->destroy()) {
256 LOG(WARNING) << getId() << " failed to destroy " << vol->getId()
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700257 << " stacked above";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800258 }
259 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700260 mVolumes.clear();
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800261
262 status_t res = doUnmount();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700263 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800264 return res;
265}
266
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700267status_t VolumeBase::format(const std::string& fsType) {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700268 if (mState == State::kMounted) {
269 unmount();
270 }
271
272 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
273 LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800274 return -EBUSY;
275 }
276
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700277 setState(State::kFormatting);
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700278 status_t res = doFormat(fsType);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700279 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800280 return res;
281}
282
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700283status_t VolumeBase::doFormat(const std::string& fsType) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800284 return -ENOTSUP;
285}
286
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800287} // namespace vold
288} // namespace android