OSDN Git Service

Progress towards dynamic storage support.
[android-x86/system-vold.git] / VolumeBase.cpp
1 /*
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
17 #include "Utils.h"
18 #include "VolumeBase.h"
19 #include "VolumeManager.h"
20 #include "ResponseCode.h"
21
22 #include <base/stringprintf.h>
23 #include <base/logging.h>
24
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <sys/mount.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30
31 using android::base::StringPrintf;
32
33 #define DEBUG 1
34
35 namespace android {
36 namespace vold {
37
38 VolumeBase::VolumeBase(Type type) :
39         mType(type), mFlags(0), mUser(-1), mCreated(false), mState(State::kUnmounted) {
40 }
41
42 VolumeBase::~VolumeBase() {
43     CHECK(!mCreated);
44 }
45
46 void VolumeBase::setState(State state) {
47     mState = state;
48
49     VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
50             ResponseCode::VolumeStateChanged,
51             StringPrintf("%s %d", getId().c_str(), mState).c_str(), false);
52 }
53
54 status_t VolumeBase::setFlags(int flags) {
55     if (mState != State::kUnmounted) {
56         LOG(WARNING) << getId() << " flags change requires state unmounted";
57         return -EBUSY;
58     }
59
60     mFlags = flags;
61     return OK;
62 }
63
64 status_t VolumeBase::setUser(userid_t user) {
65     if (mState != State::kUnmounted) {
66         LOG(WARNING) << getId() << " user change requires state unmounted";
67         return -EBUSY;
68     }
69
70     mUser = user;
71     return OK;
72 }
73
74 status_t VolumeBase::setId(const std::string& id) {
75     if (mCreated) {
76         LOG(WARNING) << getId() << " id change requires not created";
77         return -EBUSY;
78     }
79
80     mId = id;
81     return OK;
82 }
83
84 status_t VolumeBase::setPath(const std::string& path) {
85     if (mState != State::kMounting) {
86         LOG(WARNING) << getId() << " path change requires state mounting";
87         return -EBUSY;
88     }
89
90     mPath = path;
91     VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
92             ResponseCode::VolumePathChanged,
93             StringPrintf("%s %s", getId().c_str(), mPath.c_str()).c_str(), false);
94     return OK;
95 }
96
97 void VolumeBase::addVolume(const std::shared_ptr<VolumeBase>& volume) {
98     mVolumes.push_back(volume);
99 }
100
101 void VolumeBase::removeVolume(const std::shared_ptr<VolumeBase>& volume) {
102     mVolumes.remove(volume);
103 }
104
105 std::shared_ptr<VolumeBase> VolumeBase::findVolume(const std::string& id) {
106     for (auto vol : mVolumes) {
107         if (vol->getId() == id) {
108             return vol;
109         }
110     }
111     return nullptr;
112 }
113
114 status_t VolumeBase::create() {
115     CHECK(!mCreated);
116     mCreated = true;
117     VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
118             ResponseCode::VolumeCreated,
119             StringPrintf("%s %d", getId().c_str(), mType).c_str(), false);
120     return OK;
121 }
122
123 status_t VolumeBase::destroy() {
124     CHECK(mCreated);
125
126     if (mState == State::kMounted) {
127         unmount();
128     }
129
130     mCreated = false;
131     VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
132             ResponseCode::VolumeDestroyed, getId().c_str(), false);
133     return OK;
134 }
135
136 status_t VolumeBase::mount() {
137     if (mState != State::kUnmounted) {
138         LOG(WARNING) << getId() << " mount requires state unmounted";
139         return -EBUSY;
140     }
141
142     setState(State::kMounting);
143     status_t res = doMount();
144     if (res == OK) {
145         setState(State::kMounted);
146     } else {
147         setState(State::kUnmounted);
148     }
149
150     return res;
151 }
152
153 status_t VolumeBase::unmount() {
154     if (mState != State::kMounted) {
155         LOG(WARNING) << getId() << " unmount requires state mounted";
156         return -EBUSY;
157     }
158
159     setState(State::kUnmounting);
160
161     for (auto vol : mVolumes) {
162         if (vol->unmount()) {
163             LOG(WARNING) << getId() << " failed to unmount " << vol->getId()
164                     << " stacked above";
165         }
166     }
167     mVolumes.clear();
168
169     status_t res = doUnmount();
170     setState(State::kUnmounted);
171     return res;
172 }
173
174 status_t VolumeBase::format() {
175     if (mState != State::kUnmounted) {
176         LOG(WARNING) << getId() << " format requires state unmounted";
177         return -EBUSY;
178     }
179
180     setState(State::kFormatting);
181     status_t res = doFormat();
182     setState(State::kUnmounted);
183     return res;
184 }
185
186 status_t VolumeBase::doFormat() {
187     return -ENOTSUP;
188 }
189
190 }  // namespace vold
191 }  // namespace android