blob: 3f27d87c7d9fa013f030d8fe6e781ff4da1e19ed [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 Sharkeyce6a9132015-04-08 21:07:21 -070047 notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState));
Jeff Sharkeydeb24052015-03-02 21:01:40 -080048}
49
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070050status_t VolumeBase::setDiskId(const std::string& diskId) {
51 if (mCreated) {
52 LOG(WARNING) << getId() << " diskId change requires destroyed";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080053 return -EBUSY;
54 }
55
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070056 mDiskId = diskId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070057 return OK;
58}
59
Jeff Sharkeybc40cc82015-06-18 14:25:08 -070060status_t VolumeBase::setPartGuid(const std::string& partGuid) {
61 if (mCreated) {
62 LOG(WARNING) << getId() << " partGuid change requires destroyed";
63 return -EBUSY;
64 }
65
66 mPartGuid = partGuid;
67 return OK;
68}
69
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070070status_t VolumeBase::setMountFlags(int mountFlags) {
71 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
72 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -070073 return -EBUSY;
74 }
75
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070076 mMountFlags = mountFlags;
77 return OK;
78}
79
80status_t VolumeBase::setMountUserId(userid_t mountUserId) {
81 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
82 LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
83 return -EBUSY;
84 }
85
86 mMountUserId = mountUserId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070087 return OK;
88}
89
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070090status_t VolumeBase::setSilent(bool silent) {
91 if (mCreated) {
92 LOG(WARNING) << getId() << " silence change requires destroyed";
93 return -EBUSY;
94 }
95
96 mSilent = silent;
97 return OK;
98}
99
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700100status_t VolumeBase::setId(const std::string& id) {
101 if (mCreated) {
102 LOG(WARNING) << getId() << " id change requires not created";
103 return -EBUSY;
104 }
105
106 mId = id;
107 return OK;
108}
109
110status_t VolumeBase::setPath(const std::string& path) {
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700111 if (mState != State::kChecking) {
112 LOG(WARNING) << getId() << " path change requires state checking";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700113 return -EBUSY;
114 }
115
116 mPath = path;
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700117 notifyEvent(ResponseCode::VolumePathChanged, mPath);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700118 return OK;
119}
120
Jeff Sharkey1d6fbcc2015-04-24 16:00:03 -0700121status_t VolumeBase::setInternalPath(const std::string& internalPath) {
122 if (mState != State::kChecking) {
123 LOG(WARNING) << getId() << " internal path change requires state checking";
124 return -EBUSY;
125 }
126
127 mInternalPath = internalPath;
128 notifyEvent(ResponseCode::VolumeInternalPathChanged, mInternalPath);
129 return OK;
130}
131
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700132void VolumeBase::notifyEvent(int event) {
133 if (mSilent) return;
134 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
135 getId().c_str(), false);
136}
137
138void VolumeBase::notifyEvent(int event, const std::string& value) {
139 if (mSilent) return;
140 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
141 StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false);
142}
143
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700144void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
145 mVolumes.push_back(volume);
146}
147
148void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
149 mVolumes.remove(volume);
150}
151
152std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
153 for (auto vol : mVolumes) {
154 if (vol->getId() == id) {
155 return vol;
156 }
157 }
158 return nullptr;
159}
160
161status_t VolumeBase::create() {
162 CHECK(!mCreated);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700163
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700164 mCreated = true;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700165 status_t res = doCreate();
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700166 notifyEvent(ResponseCode::VolumeCreated,
167 StringPrintf("%d \"%s\" \"%s\"", mType, mDiskId.c_str(), mPartGuid.c_str()));
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700168 setState(State::kUnmounted);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700169 return res;
170}
171
172status_t VolumeBase::doCreate() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700173 return OK;
174}
175
176status_t VolumeBase::destroy() {
177 CHECK(mCreated);
178
179 if (mState == State::kMounted) {
180 unmount();
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700181 setState(State::kBadRemoval);
182 } else {
183 setState(State::kRemoved);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700184 }
185
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700186 notifyEvent(ResponseCode::VolumeDestroyed);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700187 status_t res = doDestroy();
188 mCreated = false;
189 return res;
190}
191
192status_t VolumeBase::doDestroy() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700193 return OK;
194}
195
196status_t VolumeBase::mount() {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700197 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
198 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700199 return -EBUSY;
200 }
201
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700202 setState(State::kChecking);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800203 status_t res = doMount();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700204 if (res == OK) {
205 setState(State::kMounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800206 } else {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700207 setState(State::kUnmountable);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800208 }
209
210 return res;
211}
212
213status_t VolumeBase::unmount() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700214 if (mState != State::kMounted) {
215 LOG(WARNING) << getId() << " unmount requires state mounted";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800216 return -EBUSY;
217 }
218
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700219 setState(State::kEjecting);
Chih-Hung Hsieh11a2ce82016-07-27 14:11:02 -0700220 for (const auto& vol : mVolumes) {
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700221 if (vol->destroy()) {
222 LOG(WARNING) << getId() << " failed to destroy " << vol->getId()
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700223 << " stacked above";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800224 }
225 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700226 mVolumes.clear();
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800227
228 status_t res = doUnmount();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700229 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800230 return res;
231}
232
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700233status_t VolumeBase::format(const std::string& fsType) {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700234 if (mState == State::kMounted) {
235 unmount();
236 }
237
238 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
239 LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800240 return -EBUSY;
241 }
242
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700243 setState(State::kFormatting);
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700244 status_t res = doFormat(fsType);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700245 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800246 return res;
247}
248
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700249status_t VolumeBase::doFormat(const std::string& fsType) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800250 return -ENOTSUP;
251}
252
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800253} // namespace vold
254} // namespace android