blob: ea4d372effe48e2066d267d6eab2ba889e3714de [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
33#define DEBUG 1
34
Jeff Sharkeydeb24052015-03-02 21:01:40 -080035namespace android {
36namespace vold {
37
Jeff Sharkey36801cc2015-03-13 16:09:20 -070038VolumeBase::VolumeBase(Type type) :
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070039 mType(type), mMountFlags(0), mMountUserId(-1), mCreated(false), mState(
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070040 State::kUnmounted), mSilent(false) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -080041}
42
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 Sharkeyce6a9132015-04-08 21:07:21 -070049 notifyEvent(ResponseCode::VolumeStateChanged, StringPrintf("%d", mState));
Jeff Sharkeydeb24052015-03-02 21:01:40 -080050}
51
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070052status_t VolumeBase::setDiskId(const std::string& diskId) {
53 if (mCreated) {
54 LOG(WARNING) << getId() << " diskId change requires destroyed";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080055 return -EBUSY;
56 }
57
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070058 mDiskId = diskId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070059 return OK;
60}
61
Jeff Sharkeybc40cc82015-06-18 14:25:08 -070062status_t VolumeBase::setPartGuid(const std::string& partGuid) {
63 if (mCreated) {
64 LOG(WARNING) << getId() << " partGuid change requires destroyed";
65 return -EBUSY;
66 }
67
68 mPartGuid = partGuid;
69 return OK;
70}
71
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070072status_t VolumeBase::setMountFlags(int mountFlags) {
73 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
74 LOG(WARNING) << getId() << " flags change requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -070075 return -EBUSY;
76 }
77
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -070078 mMountFlags = mountFlags;
79 return OK;
80}
81
82status_t VolumeBase::setMountUserId(userid_t mountUserId) {
83 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
84 LOG(WARNING) << getId() << " user change requires state unmounted or unmountable";
85 return -EBUSY;
86 }
87
88 mMountUserId = mountUserId;
Jeff Sharkey36801cc2015-03-13 16:09:20 -070089 return OK;
90}
91
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070092status_t VolumeBase::setSilent(bool silent) {
93 if (mCreated) {
94 LOG(WARNING) << getId() << " silence change requires destroyed";
95 return -EBUSY;
96 }
97
98 mSilent = silent;
99 return OK;
100}
101
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700102status_t VolumeBase::setId(const std::string& id) {
103 if (mCreated) {
104 LOG(WARNING) << getId() << " id change requires not created";
105 return -EBUSY;
106 }
107
108 mId = id;
109 return OK;
110}
111
112status_t VolumeBase::setPath(const std::string& path) {
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700113 if (mState != State::kChecking) {
114 LOG(WARNING) << getId() << " path change requires state checking";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700115 return -EBUSY;
116 }
117
118 mPath = path;
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700119 notifyEvent(ResponseCode::VolumePathChanged, mPath);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700120 return OK;
121}
122
Jeff Sharkey1d6fbcc2015-04-24 16:00:03 -0700123status_t VolumeBase::setInternalPath(const std::string& internalPath) {
124 if (mState != State::kChecking) {
125 LOG(WARNING) << getId() << " internal path change requires state checking";
126 return -EBUSY;
127 }
128
129 mInternalPath = internalPath;
130 notifyEvent(ResponseCode::VolumeInternalPathChanged, mInternalPath);
131 return OK;
132}
133
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700134void VolumeBase::notifyEvent(int event) {
135 if (mSilent) return;
136 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
137 getId().c_str(), false);
138}
139
140void VolumeBase::notifyEvent(int event, const std::string& value) {
141 if (mSilent) return;
142 VolumeManager::Instance()->getBroadcaster()->sendBroadcast(event,
143 StringPrintf("%s %s", getId().c_str(), value.c_str()).c_str(), false);
144}
145
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700146void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
147 mVolumes.push_back(volume);
148}
149
150void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
151 mVolumes.remove(volume);
152}
153
154std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
155 for (auto vol : mVolumes) {
156 if (vol->getId() == id) {
157 return vol;
158 }
159 }
160 return nullptr;
161}
162
163status_t VolumeBase::create() {
164 CHECK(!mCreated);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700165
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700166 mCreated = true;
Jeff Sharkey9c484982015-03-31 10:35:33 -0700167 status_t res = doCreate();
Jeff Sharkeybc40cc82015-06-18 14:25:08 -0700168 notifyEvent(ResponseCode::VolumeCreated,
169 StringPrintf("%d \"%s\" \"%s\"", mType, mDiskId.c_str(), mPartGuid.c_str()));
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700170 setState(State::kUnmounted);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700171 return res;
172}
173
174status_t VolumeBase::doCreate() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700175 return OK;
176}
177
178status_t VolumeBase::destroy() {
179 CHECK(mCreated);
180
181 if (mState == State::kMounted) {
182 unmount();
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700183 setState(State::kBadRemoval);
184 } else {
185 setState(State::kRemoved);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700186 }
187
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700188 notifyEvent(ResponseCode::VolumeDestroyed);
Jeff Sharkey9c484982015-03-31 10:35:33 -0700189 status_t res = doDestroy();
190 mCreated = false;
191 return res;
192}
193
194status_t VolumeBase::doDestroy() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700195 return OK;
196}
197
198status_t VolumeBase::mount() {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700199 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
200 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700201 return -EBUSY;
202 }
203
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700204 setState(State::kChecking);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800205 status_t res = doMount();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700206 if (res == OK) {
207 setState(State::kMounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800208 } else {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700209 setState(State::kUnmountable);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800210 }
211
212 return res;
213}
214
215status_t VolumeBase::unmount() {
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700216 if (mState != State::kMounted) {
217 LOG(WARNING) << getId() << " unmount requires state mounted";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800218 return -EBUSY;
219 }
220
Jeff Sharkeyf1b996d2015-04-17 17:35:20 -0700221 setState(State::kEjecting);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700222 for (auto vol : mVolumes) {
Jeff Sharkey3161fb32015-04-12 16:03:33 -0700223 if (vol->destroy()) {
224 LOG(WARNING) << getId() << " failed to destroy " << vol->getId()
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700225 << " stacked above";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800226 }
227 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700228 mVolumes.clear();
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800229
230 status_t res = doUnmount();
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700231 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800232 return res;
233}
234
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700235status_t VolumeBase::format(const std::string& fsType) {
Jeff Sharkey0fd95352015-04-04 21:38:59 -0700236 if (mState == State::kMounted) {
237 unmount();
238 }
239
240 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
241 LOG(WARNING) << getId() << " format requires state unmounted or unmountable";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800242 return -EBUSY;
243 }
244
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700245 setState(State::kFormatting);
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700246 status_t res = doFormat(fsType);
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700247 setState(State::kUnmounted);
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800248 return res;
249}
250
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700251status_t VolumeBase::doFormat(const std::string& fsType) {
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800252 return -ENOTSUP;
253}
254
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800255} // namespace vold
256} // namespace android