1*00c7fec1SAndroid Build Coastguard Worker /*
2*00c7fec1SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*00c7fec1SAndroid Build Coastguard Worker *
4*00c7fec1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*00c7fec1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*00c7fec1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*00c7fec1SAndroid Build Coastguard Worker *
8*00c7fec1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*00c7fec1SAndroid Build Coastguard Worker *
10*00c7fec1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*00c7fec1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*00c7fec1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*00c7fec1SAndroid Build Coastguard Worker * See the License for the specic language governing permissions and
14*00c7fec1SAndroid Build Coastguard Worker * limitations under the License.
15*00c7fec1SAndroid Build Coastguard Worker */
16*00c7fec1SAndroid Build Coastguard Worker
17*00c7fec1SAndroid Build Coastguard Worker #include "libappfuse/FuseBridgeLoop.h"
18*00c7fec1SAndroid Build Coastguard Worker
19*00c7fec1SAndroid Build Coastguard Worker #include <sys/epoll.h>
20*00c7fec1SAndroid Build Coastguard Worker #include <sys/socket.h>
21*00c7fec1SAndroid Build Coastguard Worker
22*00c7fec1SAndroid Build Coastguard Worker #include <unordered_map>
23*00c7fec1SAndroid Build Coastguard Worker
24*00c7fec1SAndroid Build Coastguard Worker #include <android-base/logging.h>
25*00c7fec1SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
26*00c7fec1SAndroid Build Coastguard Worker
27*00c7fec1SAndroid Build Coastguard Worker #include "libappfuse/EpollController.h"
28*00c7fec1SAndroid Build Coastguard Worker
29*00c7fec1SAndroid Build Coastguard Worker namespace android {
30*00c7fec1SAndroid Build Coastguard Worker namespace fuse {
31*00c7fec1SAndroid Build Coastguard Worker namespace {
32*00c7fec1SAndroid Build Coastguard Worker
33*00c7fec1SAndroid Build Coastguard Worker enum class FuseBridgeState { kWaitToReadEither, kWaitToReadProxy, kWaitToWriteProxy, kClosing };
34*00c7fec1SAndroid Build Coastguard Worker
35*00c7fec1SAndroid Build Coastguard Worker struct FuseBridgeEntryEvent {
36*00c7fec1SAndroid Build Coastguard Worker FuseBridgeEntry* entry;
37*00c7fec1SAndroid Build Coastguard Worker int events;
38*00c7fec1SAndroid Build Coastguard Worker };
39*00c7fec1SAndroid Build Coastguard Worker
GetObservedEvents(FuseBridgeState state,int * device_events,int * proxy_events)40*00c7fec1SAndroid Build Coastguard Worker void GetObservedEvents(FuseBridgeState state, int* device_events, int* proxy_events) {
41*00c7fec1SAndroid Build Coastguard Worker switch (state) {
42*00c7fec1SAndroid Build Coastguard Worker case FuseBridgeState::kWaitToReadEither:
43*00c7fec1SAndroid Build Coastguard Worker *device_events = EPOLLIN;
44*00c7fec1SAndroid Build Coastguard Worker *proxy_events = EPOLLIN;
45*00c7fec1SAndroid Build Coastguard Worker return;
46*00c7fec1SAndroid Build Coastguard Worker case FuseBridgeState::kWaitToReadProxy:
47*00c7fec1SAndroid Build Coastguard Worker *device_events = 0;
48*00c7fec1SAndroid Build Coastguard Worker *proxy_events = EPOLLIN;
49*00c7fec1SAndroid Build Coastguard Worker return;
50*00c7fec1SAndroid Build Coastguard Worker case FuseBridgeState::kWaitToWriteProxy:
51*00c7fec1SAndroid Build Coastguard Worker *device_events = 0;
52*00c7fec1SAndroid Build Coastguard Worker *proxy_events = EPOLLOUT;
53*00c7fec1SAndroid Build Coastguard Worker return;
54*00c7fec1SAndroid Build Coastguard Worker case FuseBridgeState::kClosing:
55*00c7fec1SAndroid Build Coastguard Worker *device_events = 0;
56*00c7fec1SAndroid Build Coastguard Worker *proxy_events = 0;
57*00c7fec1SAndroid Build Coastguard Worker return;
58*00c7fec1SAndroid Build Coastguard Worker }
59*00c7fec1SAndroid Build Coastguard Worker }
60*00c7fec1SAndroid Build Coastguard Worker
LogResponseError(const std::string & message,const FuseResponse & response)61*00c7fec1SAndroid Build Coastguard Worker void LogResponseError(const std::string& message, const FuseResponse& response) {
62*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << message << ": header.len=" << response.header.len
63*00c7fec1SAndroid Build Coastguard Worker << " header.error=" << response.header.error
64*00c7fec1SAndroid Build Coastguard Worker << " header.unique=" << response.header.unique;
65*00c7fec1SAndroid Build Coastguard Worker }
66*00c7fec1SAndroid Build Coastguard Worker }
67*00c7fec1SAndroid Build Coastguard Worker
68*00c7fec1SAndroid Build Coastguard Worker class FuseBridgeEntry {
69*00c7fec1SAndroid Build Coastguard Worker public:
FuseBridgeEntry(int mount_id,base::unique_fd && dev_fd,base::unique_fd && proxy_fd)70*00c7fec1SAndroid Build Coastguard Worker FuseBridgeEntry(int mount_id, base::unique_fd&& dev_fd, base::unique_fd&& proxy_fd)
71*00c7fec1SAndroid Build Coastguard Worker : mount_id_(mount_id),
72*00c7fec1SAndroid Build Coastguard Worker device_fd_(std::move(dev_fd)),
73*00c7fec1SAndroid Build Coastguard Worker proxy_fd_(std::move(proxy_fd)),
74*00c7fec1SAndroid Build Coastguard Worker state_(FuseBridgeState::kWaitToReadEither),
75*00c7fec1SAndroid Build Coastguard Worker last_state_(FuseBridgeState::kWaitToReadEither),
76*00c7fec1SAndroid Build Coastguard Worker last_device_events_({this, 0}),
77*00c7fec1SAndroid Build Coastguard Worker last_proxy_events_({this, 0}),
78*00c7fec1SAndroid Build Coastguard Worker open_count_(0) {}
79*00c7fec1SAndroid Build Coastguard Worker
80*00c7fec1SAndroid Build Coastguard Worker // Transfer bytes depends on availability of FDs and the internal |state_|.
Transfer(FuseBridgeLoopCallback * callback)81*00c7fec1SAndroid Build Coastguard Worker void Transfer(FuseBridgeLoopCallback* callback) {
82*00c7fec1SAndroid Build Coastguard Worker constexpr int kUnexpectedEventMask = ~(EPOLLIN | EPOLLOUT);
83*00c7fec1SAndroid Build Coastguard Worker const bool unexpected_event = (last_device_events_.events & kUnexpectedEventMask) ||
84*00c7fec1SAndroid Build Coastguard Worker (last_proxy_events_.events & kUnexpectedEventMask);
85*00c7fec1SAndroid Build Coastguard Worker const bool device_read_ready = last_device_events_.events & EPOLLIN;
86*00c7fec1SAndroid Build Coastguard Worker const bool proxy_read_ready = last_proxy_events_.events & EPOLLIN;
87*00c7fec1SAndroid Build Coastguard Worker const bool proxy_write_ready = last_proxy_events_.events & EPOLLOUT;
88*00c7fec1SAndroid Build Coastguard Worker
89*00c7fec1SAndroid Build Coastguard Worker last_state_ = state_;
90*00c7fec1SAndroid Build Coastguard Worker last_device_events_.events = 0;
91*00c7fec1SAndroid Build Coastguard Worker last_proxy_events_.events = 0;
92*00c7fec1SAndroid Build Coastguard Worker
93*00c7fec1SAndroid Build Coastguard Worker LOG(VERBOSE) << "Transfer device_read_ready=" << device_read_ready
94*00c7fec1SAndroid Build Coastguard Worker << " proxy_read_ready=" << proxy_read_ready
95*00c7fec1SAndroid Build Coastguard Worker << " proxy_write_ready=" << proxy_write_ready;
96*00c7fec1SAndroid Build Coastguard Worker
97*00c7fec1SAndroid Build Coastguard Worker if (unexpected_event) {
98*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "Invalid epoll event is observed";
99*00c7fec1SAndroid Build Coastguard Worker state_ = FuseBridgeState::kClosing;
100*00c7fec1SAndroid Build Coastguard Worker return;
101*00c7fec1SAndroid Build Coastguard Worker }
102*00c7fec1SAndroid Build Coastguard Worker
103*00c7fec1SAndroid Build Coastguard Worker switch (state_) {
104*00c7fec1SAndroid Build Coastguard Worker case FuseBridgeState::kWaitToReadEither:
105*00c7fec1SAndroid Build Coastguard Worker if (proxy_read_ready) {
106*00c7fec1SAndroid Build Coastguard Worker state_ = ReadFromProxy();
107*00c7fec1SAndroid Build Coastguard Worker } else if (device_read_ready) {
108*00c7fec1SAndroid Build Coastguard Worker state_ = ReadFromDevice(callback);
109*00c7fec1SAndroid Build Coastguard Worker }
110*00c7fec1SAndroid Build Coastguard Worker return;
111*00c7fec1SAndroid Build Coastguard Worker
112*00c7fec1SAndroid Build Coastguard Worker case FuseBridgeState::kWaitToReadProxy:
113*00c7fec1SAndroid Build Coastguard Worker CHECK(proxy_read_ready);
114*00c7fec1SAndroid Build Coastguard Worker state_ = ReadFromProxy();
115*00c7fec1SAndroid Build Coastguard Worker return;
116*00c7fec1SAndroid Build Coastguard Worker
117*00c7fec1SAndroid Build Coastguard Worker case FuseBridgeState::kWaitToWriteProxy:
118*00c7fec1SAndroid Build Coastguard Worker CHECK(proxy_write_ready);
119*00c7fec1SAndroid Build Coastguard Worker state_ = WriteToProxy();
120*00c7fec1SAndroid Build Coastguard Worker return;
121*00c7fec1SAndroid Build Coastguard Worker
122*00c7fec1SAndroid Build Coastguard Worker case FuseBridgeState::kClosing:
123*00c7fec1SAndroid Build Coastguard Worker return;
124*00c7fec1SAndroid Build Coastguard Worker }
125*00c7fec1SAndroid Build Coastguard Worker }
126*00c7fec1SAndroid Build Coastguard Worker
IsClosing() const127*00c7fec1SAndroid Build Coastguard Worker bool IsClosing() const { return state_ == FuseBridgeState::kClosing; }
128*00c7fec1SAndroid Build Coastguard Worker
mount_id() const129*00c7fec1SAndroid Build Coastguard Worker int mount_id() const { return mount_id_; }
130*00c7fec1SAndroid Build Coastguard Worker
131*00c7fec1SAndroid Build Coastguard Worker private:
132*00c7fec1SAndroid Build Coastguard Worker friend class BridgeEpollController;
133*00c7fec1SAndroid Build Coastguard Worker
ReadFromProxy()134*00c7fec1SAndroid Build Coastguard Worker FuseBridgeState ReadFromProxy() {
135*00c7fec1SAndroid Build Coastguard Worker switch (buffer_.response.ReadOrAgain(proxy_fd_)) {
136*00c7fec1SAndroid Build Coastguard Worker case ResultOrAgain::kSuccess:
137*00c7fec1SAndroid Build Coastguard Worker break;
138*00c7fec1SAndroid Build Coastguard Worker case ResultOrAgain::kFailure:
139*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kClosing;
140*00c7fec1SAndroid Build Coastguard Worker case ResultOrAgain::kAgain:
141*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kWaitToReadProxy;
142*00c7fec1SAndroid Build Coastguard Worker }
143*00c7fec1SAndroid Build Coastguard Worker
144*00c7fec1SAndroid Build Coastguard Worker if (!buffer_.response.Write(device_fd_)) {
145*00c7fec1SAndroid Build Coastguard Worker LogResponseError("Failed to write a reply from proxy to device", buffer_.response);
146*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kClosing;
147*00c7fec1SAndroid Build Coastguard Worker }
148*00c7fec1SAndroid Build Coastguard Worker
149*00c7fec1SAndroid Build Coastguard Worker auto it = opcode_map_.find(buffer_.response.header.unique);
150*00c7fec1SAndroid Build Coastguard Worker if (it != opcode_map_.end()) {
151*00c7fec1SAndroid Build Coastguard Worker switch (it->second) {
152*00c7fec1SAndroid Build Coastguard Worker case FUSE_OPEN:
153*00c7fec1SAndroid Build Coastguard Worker if (buffer_.response.header.error == fuse::kFuseSuccess) {
154*00c7fec1SAndroid Build Coastguard Worker open_count_++;
155*00c7fec1SAndroid Build Coastguard Worker }
156*00c7fec1SAndroid Build Coastguard Worker break;
157*00c7fec1SAndroid Build Coastguard Worker
158*00c7fec1SAndroid Build Coastguard Worker case FUSE_RELEASE:
159*00c7fec1SAndroid Build Coastguard Worker if (open_count_ > 0) {
160*00c7fec1SAndroid Build Coastguard Worker open_count_--;
161*00c7fec1SAndroid Build Coastguard Worker } else {
162*00c7fec1SAndroid Build Coastguard Worker LOG(WARNING) << "Unexpected FUSE_RELEASE before opening a file.";
163*00c7fec1SAndroid Build Coastguard Worker break;
164*00c7fec1SAndroid Build Coastguard Worker }
165*00c7fec1SAndroid Build Coastguard Worker if (open_count_ == 0) {
166*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kClosing;
167*00c7fec1SAndroid Build Coastguard Worker }
168*00c7fec1SAndroid Build Coastguard Worker break;
169*00c7fec1SAndroid Build Coastguard Worker }
170*00c7fec1SAndroid Build Coastguard Worker opcode_map_.erase(it);
171*00c7fec1SAndroid Build Coastguard Worker }
172*00c7fec1SAndroid Build Coastguard Worker
173*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kWaitToReadEither;
174*00c7fec1SAndroid Build Coastguard Worker }
175*00c7fec1SAndroid Build Coastguard Worker
ReadFromDevice(FuseBridgeLoopCallback * callback)176*00c7fec1SAndroid Build Coastguard Worker FuseBridgeState ReadFromDevice(FuseBridgeLoopCallback* callback) {
177*00c7fec1SAndroid Build Coastguard Worker LOG(VERBOSE) << "ReadFromDevice";
178*00c7fec1SAndroid Build Coastguard Worker if (!buffer_.request.Read(device_fd_)) {
179*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kClosing;
180*00c7fec1SAndroid Build Coastguard Worker }
181*00c7fec1SAndroid Build Coastguard Worker
182*00c7fec1SAndroid Build Coastguard Worker const uint32_t opcode = buffer_.request.header.opcode;
183*00c7fec1SAndroid Build Coastguard Worker const uint64_t unique = buffer_.request.header.unique;
184*00c7fec1SAndroid Build Coastguard Worker LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode << " unique=" << unique;
185*00c7fec1SAndroid Build Coastguard Worker if (unique == 0) {
186*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kWaitToReadEither;
187*00c7fec1SAndroid Build Coastguard Worker }
188*00c7fec1SAndroid Build Coastguard Worker switch (opcode) {
189*00c7fec1SAndroid Build Coastguard Worker case FUSE_FORGET:
190*00c7fec1SAndroid Build Coastguard Worker // Do not reply to FUSE_FORGET.
191*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kWaitToReadEither;
192*00c7fec1SAndroid Build Coastguard Worker
193*00c7fec1SAndroid Build Coastguard Worker case FUSE_LOOKUP:
194*00c7fec1SAndroid Build Coastguard Worker case FUSE_GETATTR:
195*00c7fec1SAndroid Build Coastguard Worker case FUSE_OPEN:
196*00c7fec1SAndroid Build Coastguard Worker case FUSE_READ:
197*00c7fec1SAndroid Build Coastguard Worker case FUSE_WRITE:
198*00c7fec1SAndroid Build Coastguard Worker case FUSE_RELEASE:
199*00c7fec1SAndroid Build Coastguard Worker case FUSE_FSYNC:
200*00c7fec1SAndroid Build Coastguard Worker if (opcode == FUSE_OPEN || opcode == FUSE_RELEASE) {
201*00c7fec1SAndroid Build Coastguard Worker opcode_map_.emplace(buffer_.request.header.unique, opcode);
202*00c7fec1SAndroid Build Coastguard Worker }
203*00c7fec1SAndroid Build Coastguard Worker return WriteToProxy();
204*00c7fec1SAndroid Build Coastguard Worker
205*00c7fec1SAndroid Build Coastguard Worker case FUSE_INIT:
206*00c7fec1SAndroid Build Coastguard Worker buffer_.HandleInit();
207*00c7fec1SAndroid Build Coastguard Worker break;
208*00c7fec1SAndroid Build Coastguard Worker
209*00c7fec1SAndroid Build Coastguard Worker default:
210*00c7fec1SAndroid Build Coastguard Worker buffer_.HandleNotImpl();
211*00c7fec1SAndroid Build Coastguard Worker break;
212*00c7fec1SAndroid Build Coastguard Worker }
213*00c7fec1SAndroid Build Coastguard Worker
214*00c7fec1SAndroid Build Coastguard Worker if (!buffer_.response.Write(device_fd_)) {
215*00c7fec1SAndroid Build Coastguard Worker LogResponseError("Failed to write a response to device", buffer_.response);
216*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kClosing;
217*00c7fec1SAndroid Build Coastguard Worker }
218*00c7fec1SAndroid Build Coastguard Worker
219*00c7fec1SAndroid Build Coastguard Worker if (opcode == FUSE_INIT) {
220*00c7fec1SAndroid Build Coastguard Worker callback->OnMount(mount_id_);
221*00c7fec1SAndroid Build Coastguard Worker }
222*00c7fec1SAndroid Build Coastguard Worker
223*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kWaitToReadEither;
224*00c7fec1SAndroid Build Coastguard Worker }
225*00c7fec1SAndroid Build Coastguard Worker
WriteToProxy()226*00c7fec1SAndroid Build Coastguard Worker FuseBridgeState WriteToProxy() {
227*00c7fec1SAndroid Build Coastguard Worker switch (buffer_.request.WriteOrAgain(proxy_fd_)) {
228*00c7fec1SAndroid Build Coastguard Worker case ResultOrAgain::kSuccess:
229*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kWaitToReadEither;
230*00c7fec1SAndroid Build Coastguard Worker case ResultOrAgain::kFailure:
231*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to write a request to proxy:"
232*00c7fec1SAndroid Build Coastguard Worker << " header.len=" << buffer_.request.header.len
233*00c7fec1SAndroid Build Coastguard Worker << " header.opcode=" << buffer_.request.header.opcode
234*00c7fec1SAndroid Build Coastguard Worker << " header.unique=" << buffer_.request.header.unique
235*00c7fec1SAndroid Build Coastguard Worker << " header.nodeid=" << buffer_.request.header.nodeid;
236*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kClosing;
237*00c7fec1SAndroid Build Coastguard Worker case ResultOrAgain::kAgain:
238*00c7fec1SAndroid Build Coastguard Worker return FuseBridgeState::kWaitToWriteProxy;
239*00c7fec1SAndroid Build Coastguard Worker }
240*00c7fec1SAndroid Build Coastguard Worker }
241*00c7fec1SAndroid Build Coastguard Worker
242*00c7fec1SAndroid Build Coastguard Worker const int mount_id_;
243*00c7fec1SAndroid Build Coastguard Worker base::unique_fd device_fd_;
244*00c7fec1SAndroid Build Coastguard Worker base::unique_fd proxy_fd_;
245*00c7fec1SAndroid Build Coastguard Worker FuseBuffer buffer_;
246*00c7fec1SAndroid Build Coastguard Worker FuseBridgeState state_;
247*00c7fec1SAndroid Build Coastguard Worker FuseBridgeState last_state_;
248*00c7fec1SAndroid Build Coastguard Worker FuseBridgeEntryEvent last_device_events_;
249*00c7fec1SAndroid Build Coastguard Worker FuseBridgeEntryEvent last_proxy_events_;
250*00c7fec1SAndroid Build Coastguard Worker
251*00c7fec1SAndroid Build Coastguard Worker // Remember map between unique and opcode in fuse_in_header so that we can
252*00c7fec1SAndroid Build Coastguard Worker // refer the opcode later.
253*00c7fec1SAndroid Build Coastguard Worker std::unordered_map<uint64_t, uint32_t> opcode_map_;
254*00c7fec1SAndroid Build Coastguard Worker
255*00c7fec1SAndroid Build Coastguard Worker int open_count_;
256*00c7fec1SAndroid Build Coastguard Worker
257*00c7fec1SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(FuseBridgeEntry);
258*00c7fec1SAndroid Build Coastguard Worker };
259*00c7fec1SAndroid Build Coastguard Worker
260*00c7fec1SAndroid Build Coastguard Worker class BridgeEpollController : private EpollController {
261*00c7fec1SAndroid Build Coastguard Worker public:
BridgeEpollController(base::unique_fd && poll_fd)262*00c7fec1SAndroid Build Coastguard Worker BridgeEpollController(base::unique_fd&& poll_fd) : EpollController(std::move(poll_fd)) {}
263*00c7fec1SAndroid Build Coastguard Worker
AddBridgePoll(FuseBridgeEntry * bridge) const264*00c7fec1SAndroid Build Coastguard Worker bool AddBridgePoll(FuseBridgeEntry* bridge) const {
265*00c7fec1SAndroid Build Coastguard Worker return InvokeControl(EPOLL_CTL_ADD, bridge);
266*00c7fec1SAndroid Build Coastguard Worker }
267*00c7fec1SAndroid Build Coastguard Worker
UpdateOrDeleteBridgePoll(FuseBridgeEntry * bridge) const268*00c7fec1SAndroid Build Coastguard Worker bool UpdateOrDeleteBridgePoll(FuseBridgeEntry* bridge) const {
269*00c7fec1SAndroid Build Coastguard Worker return InvokeControl(
270*00c7fec1SAndroid Build Coastguard Worker bridge->state_ != FuseBridgeState::kClosing ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, bridge);
271*00c7fec1SAndroid Build Coastguard Worker }
272*00c7fec1SAndroid Build Coastguard Worker
Wait(size_t bridge_count,std::unordered_set<FuseBridgeEntry * > * entries_out)273*00c7fec1SAndroid Build Coastguard Worker bool Wait(size_t bridge_count, std::unordered_set<FuseBridgeEntry*>* entries_out) {
274*00c7fec1SAndroid Build Coastguard Worker CHECK(entries_out);
275*00c7fec1SAndroid Build Coastguard Worker const size_t event_count = std::max<size_t>(bridge_count * 2, 1);
276*00c7fec1SAndroid Build Coastguard Worker if (!EpollController::Wait(event_count)) {
277*00c7fec1SAndroid Build Coastguard Worker return false;
278*00c7fec1SAndroid Build Coastguard Worker }
279*00c7fec1SAndroid Build Coastguard Worker entries_out->clear();
280*00c7fec1SAndroid Build Coastguard Worker for (const auto& event : events()) {
281*00c7fec1SAndroid Build Coastguard Worker FuseBridgeEntryEvent* const entry_event =
282*00c7fec1SAndroid Build Coastguard Worker reinterpret_cast<FuseBridgeEntryEvent*>(event.data.ptr);
283*00c7fec1SAndroid Build Coastguard Worker entry_event->events = event.events;
284*00c7fec1SAndroid Build Coastguard Worker entries_out->insert(entry_event->entry);
285*00c7fec1SAndroid Build Coastguard Worker }
286*00c7fec1SAndroid Build Coastguard Worker return true;
287*00c7fec1SAndroid Build Coastguard Worker }
288*00c7fec1SAndroid Build Coastguard Worker
289*00c7fec1SAndroid Build Coastguard Worker private:
InvokeControl(int op,FuseBridgeEntry * bridge) const290*00c7fec1SAndroid Build Coastguard Worker bool InvokeControl(int op, FuseBridgeEntry* bridge) const {
291*00c7fec1SAndroid Build Coastguard Worker LOG(VERBOSE) << "InvokeControl op=" << op << " bridge=" << bridge->mount_id_
292*00c7fec1SAndroid Build Coastguard Worker << " state=" << static_cast<int>(bridge->state_)
293*00c7fec1SAndroid Build Coastguard Worker << " last_state=" << static_cast<int>(bridge->last_state_);
294*00c7fec1SAndroid Build Coastguard Worker
295*00c7fec1SAndroid Build Coastguard Worker int last_device_events;
296*00c7fec1SAndroid Build Coastguard Worker int last_proxy_events;
297*00c7fec1SAndroid Build Coastguard Worker int device_events;
298*00c7fec1SAndroid Build Coastguard Worker int proxy_events;
299*00c7fec1SAndroid Build Coastguard Worker GetObservedEvents(bridge->last_state_, &last_device_events, &last_proxy_events);
300*00c7fec1SAndroid Build Coastguard Worker GetObservedEvents(bridge->state_, &device_events, &proxy_events);
301*00c7fec1SAndroid Build Coastguard Worker bool result = true;
302*00c7fec1SAndroid Build Coastguard Worker if (op != EPOLL_CTL_MOD || last_device_events != device_events) {
303*00c7fec1SAndroid Build Coastguard Worker result &= EpollController::InvokeControl(op, bridge->device_fd_, device_events,
304*00c7fec1SAndroid Build Coastguard Worker &bridge->last_device_events_);
305*00c7fec1SAndroid Build Coastguard Worker }
306*00c7fec1SAndroid Build Coastguard Worker if (op != EPOLL_CTL_MOD || last_proxy_events != proxy_events) {
307*00c7fec1SAndroid Build Coastguard Worker result &= EpollController::InvokeControl(op, bridge->proxy_fd_, proxy_events,
308*00c7fec1SAndroid Build Coastguard Worker &bridge->last_proxy_events_);
309*00c7fec1SAndroid Build Coastguard Worker }
310*00c7fec1SAndroid Build Coastguard Worker return result;
311*00c7fec1SAndroid Build Coastguard Worker }
312*00c7fec1SAndroid Build Coastguard Worker };
313*00c7fec1SAndroid Build Coastguard Worker
314*00c7fec1SAndroid Build Coastguard Worker std::recursive_mutex FuseBridgeLoop::mutex_;
315*00c7fec1SAndroid Build Coastguard Worker
FuseBridgeLoop()316*00c7fec1SAndroid Build Coastguard Worker FuseBridgeLoop::FuseBridgeLoop() : opened_(true) {
317*00c7fec1SAndroid Build Coastguard Worker base::unique_fd epoll_fd(epoll_create1(EPOLL_CLOEXEC));
318*00c7fec1SAndroid Build Coastguard Worker if (epoll_fd.get() == -1) {
319*00c7fec1SAndroid Build Coastguard Worker PLOG(ERROR) << "Failed to open FD for epoll";
320*00c7fec1SAndroid Build Coastguard Worker opened_ = false;
321*00c7fec1SAndroid Build Coastguard Worker return;
322*00c7fec1SAndroid Build Coastguard Worker }
323*00c7fec1SAndroid Build Coastguard Worker epoll_controller_.reset(new BridgeEpollController(std::move(epoll_fd)));
324*00c7fec1SAndroid Build Coastguard Worker }
325*00c7fec1SAndroid Build Coastguard Worker
~FuseBridgeLoop()326*00c7fec1SAndroid Build Coastguard Worker FuseBridgeLoop::~FuseBridgeLoop() { CHECK(bridges_.empty()); }
327*00c7fec1SAndroid Build Coastguard Worker
AddBridge(int mount_id,base::unique_fd dev_fd,base::unique_fd proxy_fd)328*00c7fec1SAndroid Build Coastguard Worker bool FuseBridgeLoop::AddBridge(int mount_id, base::unique_fd dev_fd, base::unique_fd proxy_fd) {
329*00c7fec1SAndroid Build Coastguard Worker LOG(VERBOSE) << "Adding bridge " << mount_id;
330*00c7fec1SAndroid Build Coastguard Worker
331*00c7fec1SAndroid Build Coastguard Worker std::unique_ptr<FuseBridgeEntry> bridge(
332*00c7fec1SAndroid Build Coastguard Worker new FuseBridgeEntry(mount_id, std::move(dev_fd), std::move(proxy_fd)));
333*00c7fec1SAndroid Build Coastguard Worker std::lock_guard<std::recursive_mutex> lock(mutex_);
334*00c7fec1SAndroid Build Coastguard Worker if (!opened_) {
335*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "Tried to add a mount to a closed bridge";
336*00c7fec1SAndroid Build Coastguard Worker return false;
337*00c7fec1SAndroid Build Coastguard Worker }
338*00c7fec1SAndroid Build Coastguard Worker if (bridges_.count(mount_id)) {
339*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "Tried to add a mount point that has already been added";
340*00c7fec1SAndroid Build Coastguard Worker return false;
341*00c7fec1SAndroid Build Coastguard Worker }
342*00c7fec1SAndroid Build Coastguard Worker if (!epoll_controller_->AddBridgePoll(bridge.get())) {
343*00c7fec1SAndroid Build Coastguard Worker return false;
344*00c7fec1SAndroid Build Coastguard Worker }
345*00c7fec1SAndroid Build Coastguard Worker
346*00c7fec1SAndroid Build Coastguard Worker bridges_.emplace(mount_id, std::move(bridge));
347*00c7fec1SAndroid Build Coastguard Worker return true;
348*00c7fec1SAndroid Build Coastguard Worker }
349*00c7fec1SAndroid Build Coastguard Worker
ProcessEventLocked(const std::unordered_set<FuseBridgeEntry * > & entries,FuseBridgeLoopCallback * callback)350*00c7fec1SAndroid Build Coastguard Worker bool FuseBridgeLoop::ProcessEventLocked(const std::unordered_set<FuseBridgeEntry*>& entries,
351*00c7fec1SAndroid Build Coastguard Worker FuseBridgeLoopCallback* callback) {
352*00c7fec1SAndroid Build Coastguard Worker for (auto entry : entries) {
353*00c7fec1SAndroid Build Coastguard Worker entry->Transfer(callback);
354*00c7fec1SAndroid Build Coastguard Worker if (!epoll_controller_->UpdateOrDeleteBridgePoll(entry)) {
355*00c7fec1SAndroid Build Coastguard Worker return false;
356*00c7fec1SAndroid Build Coastguard Worker }
357*00c7fec1SAndroid Build Coastguard Worker if (entry->IsClosing()) {
358*00c7fec1SAndroid Build Coastguard Worker const int mount_id = entry->mount_id();
359*00c7fec1SAndroid Build Coastguard Worker bridges_.erase(mount_id);
360*00c7fec1SAndroid Build Coastguard Worker callback->OnClosed(mount_id);
361*00c7fec1SAndroid Build Coastguard Worker if (bridges_.size() == 0) {
362*00c7fec1SAndroid Build Coastguard Worker // All bridges are now closed.
363*00c7fec1SAndroid Build Coastguard Worker return false;
364*00c7fec1SAndroid Build Coastguard Worker }
365*00c7fec1SAndroid Build Coastguard Worker }
366*00c7fec1SAndroid Build Coastguard Worker }
367*00c7fec1SAndroid Build Coastguard Worker return true;
368*00c7fec1SAndroid Build Coastguard Worker }
369*00c7fec1SAndroid Build Coastguard Worker
Start(FuseBridgeLoopCallback * callback)370*00c7fec1SAndroid Build Coastguard Worker void FuseBridgeLoop::Start(FuseBridgeLoopCallback* callback) {
371*00c7fec1SAndroid Build Coastguard Worker LOG(DEBUG) << "Start fuse bridge loop";
372*00c7fec1SAndroid Build Coastguard Worker std::unordered_set<FuseBridgeEntry*> entries;
373*00c7fec1SAndroid Build Coastguard Worker while (true) {
374*00c7fec1SAndroid Build Coastguard Worker const bool wait_result = epoll_controller_->Wait(bridges_.size(), &entries);
375*00c7fec1SAndroid Build Coastguard Worker LOG(VERBOSE) << "Receive epoll events";
376*00c7fec1SAndroid Build Coastguard Worker {
377*00c7fec1SAndroid Build Coastguard Worker std::lock_guard<std::recursive_mutex> lock(mutex_);
378*00c7fec1SAndroid Build Coastguard Worker if (!(wait_result && ProcessEventLocked(entries, callback))) {
379*00c7fec1SAndroid Build Coastguard Worker for (auto it = bridges_.begin(); it != bridges_.end();) {
380*00c7fec1SAndroid Build Coastguard Worker callback->OnClosed(it->second->mount_id());
381*00c7fec1SAndroid Build Coastguard Worker it = bridges_.erase(it);
382*00c7fec1SAndroid Build Coastguard Worker }
383*00c7fec1SAndroid Build Coastguard Worker opened_ = false;
384*00c7fec1SAndroid Build Coastguard Worker return;
385*00c7fec1SAndroid Build Coastguard Worker }
386*00c7fec1SAndroid Build Coastguard Worker }
387*00c7fec1SAndroid Build Coastguard Worker }
388*00c7fec1SAndroid Build Coastguard Worker }
389*00c7fec1SAndroid Build Coastguard Worker
Lock()390*00c7fec1SAndroid Build Coastguard Worker void FuseBridgeLoop::Lock() {
391*00c7fec1SAndroid Build Coastguard Worker mutex_.lock();
392*00c7fec1SAndroid Build Coastguard Worker }
393*00c7fec1SAndroid Build Coastguard Worker
Unlock()394*00c7fec1SAndroid Build Coastguard Worker void FuseBridgeLoop::Unlock() {
395*00c7fec1SAndroid Build Coastguard Worker mutex_.unlock();
396*00c7fec1SAndroid Build Coastguard Worker }
397*00c7fec1SAndroid Build Coastguard Worker
398*00c7fec1SAndroid Build Coastguard Worker } // namespace fuse
399*00c7fec1SAndroid Build Coastguard Worker } // namespace android
400