Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Side by Side Diff: components/arc/arc_bridge_bootstrap.cc

Issue 2136023002: arc: Abort booting ARC if the device is critically low on disk space. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/arc/arc_bridge_bootstrap.h" 5 #include "components/arc/arc_bridge_bootstrap.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <grp.h> 8 #include <grp.h>
9 #include <unistd.h> 9 #include <unistd.h>
10 10
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h" 14 #include "base/files/file_util.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/macros.h" 16 #include "base/macros.h"
17 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
18 #include "base/posix/eintr_wrapper.h" 18 #include "base/posix/eintr_wrapper.h"
19 #include "base/task_runner_util.h" 19 #include "base/task_runner_util.h"
20 #include "base/threading/thread_checker.h" 20 #include "base/threading/thread_checker.h"
21 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
22 #include "base/threading/worker_pool.h" 22 #include "base/threading/worker_pool.h"
23 #include "chromeos/cryptohome/cryptohome_parameters.h" 23 #include "chromeos/cryptohome/cryptohome_parameters.h"
24 #include "chromeos/dbus/cryptohome_client.h"
24 #include "chromeos/dbus/dbus_method_call_status.h" 25 #include "chromeos/dbus/dbus_method_call_status.h"
25 #include "chromeos/dbus/dbus_thread_manager.h" 26 #include "chromeos/dbus/dbus_thread_manager.h"
26 #include "chromeos/dbus/session_manager_client.h" 27 #include "chromeos/dbus/session_manager_client.h"
27 #include "components/user_manager/user_manager.h" 28 #include "components/user_manager/user_manager.h"
28 #include "ipc/unix_domain_socket_util.h" 29 #include "ipc/unix_domain_socket_util.h"
29 #include "mojo/edk/embedder/embedder.h" 30 #include "mojo/edk/embedder/embedder.h"
30 #include "mojo/edk/embedder/platform_channel_pair.h" 31 #include "mojo/edk/embedder/platform_channel_pair.h"
31 #include "mojo/edk/embedder/platform_channel_utils_posix.h" 32 #include "mojo/edk/embedder/platform_channel_utils_posix.h"
32 #include "mojo/edk/embedder/platform_handle_vector.h" 33 #include "mojo/edk/embedder/platform_handle_vector.h"
33 #include "mojo/edk/embedder/scoped_platform_handle.h" 34 #include "mojo/edk/embedder/scoped_platform_handle.h"
34 #include "mojo/public/cpp/bindings/binding.h" 35 #include "mojo/public/cpp/bindings/binding.h"
35 36
36 namespace arc { 37 namespace arc {
37 38
38 namespace { 39 namespace {
39 40
40 const base::FilePath::CharType kArcBridgeSocketPath[] = 41 const base::FilePath::CharType kArcBridgeSocketPath[] =
41 FILE_PATH_LITERAL("/var/run/chrome/arc_bridge.sock"); 42 FILE_PATH_LITERAL("/var/run/chrome/arc_bridge.sock");
42 43
43 const char kArcBridgeSocketGroup[] = "arc-bridge"; 44 const char kArcBridgeSocketGroup[] = "arc-bridge";
44 45
46 const uint64_t kCriticalDiskFreeBytes = 64 << 20; // 64MB
47
45 // This is called when StopArcInstance D-Bus method completes. Since we have the 48 // This is called when StopArcInstance D-Bus method completes. Since we have the
46 // ArcInstanceStopped() callback and are notified if StartArcInstance fails, we 49 // ArcInstanceStopped() callback and are notified if StartArcInstance fails, we
47 // don't need to do anything when StopArcInstance completes. 50 // don't need to do anything when StopArcInstance completes.
48 void DoNothingInstanceStopped(bool) {} 51 void DoNothingInstanceStopped(bool) {}
49 52
50 chromeos::SessionManagerClient* GetSessionManagerClient() { 53 chromeos::SessionManagerClient* GetSessionManagerClient() {
51 // If the DBusThreadManager or the SessionManagerClient aren't available, 54 // If the DBusThreadManager or the SessionManagerClient aren't available,
52 // there isn't much we can do. This should only happen when running tests. 55 // there isn't much we can do. This should only happen when running tests.
53 if (!chromeos::DBusThreadManager::IsInitialized() || 56 if (!chromeos::DBusThreadManager::IsInitialized() ||
54 !chromeos::DBusThreadManager::Get() || 57 !chromeos::DBusThreadManager::Get() ||
55 !chromeos::DBusThreadManager::Get()->GetSessionManagerClient()) 58 !chromeos::DBusThreadManager::Get()->GetSessionManagerClient())
56 return nullptr; 59 return nullptr;
57 return chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); 60 return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
58 } 61 }
59 62
60 class ArcBridgeBootstrapImpl : public ArcBridgeBootstrap, 63 class ArcBridgeBootstrapImpl : public ArcBridgeBootstrap,
61 public chromeos::SessionManagerClient::Observer { 64 public chromeos::SessionManagerClient::Observer {
62 public: 65 public:
63 // The possible states of the bootstrap connection. In the normal flow, 66 // The possible states of the bootstrap connection. In the normal flow,
64 // the state changes in the following sequence: 67 // the state changes in the following sequence:
65 // 68 //
66 // STOPPED 69 // STOPPED
67 // Start() -> 70 // Start() ->
71 // DISK_SPACE_CHECKING
72 // CheckDiskSpace() -> OnDiskSpaceChecked() ->
68 // SOCKET_CREATING 73 // SOCKET_CREATING
69 // CreateSocket() -> OnSocketCreated() -> 74 // CreateSocket() -> OnSocketCreated() ->
70 // STARTING 75 // STARTING
71 // StartArcInstance() -> OnInstanceStarted() -> 76 // StartArcInstance() -> OnInstanceStarted() ->
72 // STARTED 77 // STARTED
73 // AcceptInstanceConnection() -> OnInstanceConnected() -> 78 // AcceptInstanceConnection() -> OnInstanceConnected() ->
74 // READY 79 // READY
75 // 80 //
76 // When Stop() or AbortBoot() is called from any state, either because an 81 // When Stop() or AbortBoot() is called from any state, either because an
77 // operation resulted in an error or because the user is logging out: 82 // operation resulted in an error or because the user is logging out:
78 // 83 //
79 // (any) 84 // (any)
80 // Stop()/AbortBoot() -> 85 // Stop()/AbortBoot() ->
81 // STOPPING 86 // STOPPING
82 // StopInstance() -> 87 // StopInstance() ->
83 // STOPPED 88 // STOPPED
84 // 89 //
85 // When the instance crashes while it was ready, it will be stopped: 90 // When the instance crashes while it was ready, it will be stopped:
86 // READY -> STOPPING -> STOPPED 91 // READY -> STOPPING -> STOPPED
87 // and then restarted: 92 // and then restarted:
88 // STOPPED -> SOCKET_CREATING -> ... -> READY). 93 // STOPPED -> DISK_SPACE_CHECKING -> ... -> READY).
89 // 94 //
90 // Note: Order of constants below matters. Please make sure to sort them 95 // Note: Order of constants below matters. Please make sure to sort them
91 // in chronological order. 96 // in chronological order.
92 enum class State { 97 enum class State {
93 // ARC is not currently running. 98 // ARC is not currently running.
94 STOPPED, 99 STOPPED,
95 100
101 // Checking the disk space.
102 DISK_SPACE_CHECKING,
103
96 // An UNIX socket is being created. 104 // An UNIX socket is being created.
97 SOCKET_CREATING, 105 SOCKET_CREATING,
98 106
99 // The request to start the instance has been sent. 107 // The request to start the instance has been sent.
100 STARTING, 108 STARTING,
101 109
102 // The instance has started. Waiting for it to connect to the IPC bridge. 110 // The instance has started. Waiting for it to connect to the IPC bridge.
103 STARTED, 111 STARTED,
104 112
105 // The instance is fully connected. 113 // The instance is fully connected.
106 READY, 114 READY,
107 115
108 // The request to shut down the instance has been sent. 116 // The request to shut down the instance has been sent.
109 STOPPING, 117 STOPPING,
110 }; 118 };
111 119
112 ArcBridgeBootstrapImpl(); 120 ArcBridgeBootstrapImpl();
113 ~ArcBridgeBootstrapImpl() override; 121 ~ArcBridgeBootstrapImpl() override;
114 122
115 // ArcBridgeBootstrap: 123 // ArcBridgeBootstrap:
116 void Start() override; 124 void Start() override;
117 void Stop() override; 125 void Stop() override;
118 126
119 private: 127 private:
120 // Aborts ARC instance boot. This is called from various state-machine 128 // Aborts ARC instance boot. This is called from various state-machine
121 // functions when they encounter an error during boot. 129 // functions when they encounter an error during boot.
122 void AbortBoot(ArcBridgeService::StopReason reason); 130 void AbortBoot(ArcBridgeService::StopReason reason);
123 131
132 // Called after checking the device disk space.
133 void OnDiskSpaceChecked(chromeos::DBusMethodCallStatus call_status,
134 uint64_t disk_free_bytes);
135
124 // Creates the UNIX socket on the bootstrap thread and then processes its 136 // Creates the UNIX socket on the bootstrap thread and then processes its
125 // file descriptor. 137 // file descriptor.
126 static base::ScopedFD CreateSocket(); 138 static base::ScopedFD CreateSocket();
127 void OnSocketCreated(base::ScopedFD fd); 139 void OnSocketCreated(base::ScopedFD fd);
128 140
129 // Synchronously accepts a connection on |socket_fd| and then processes the 141 // Synchronously accepts a connection on |socket_fd| and then processes the
130 // connected socket's file descriptor. 142 // connected socket's file descriptor.
131 static base::ScopedFD AcceptInstanceConnection(base::ScopedFD socket_fd); 143 static base::ScopedFD AcceptInstanceConnection(base::ScopedFD socket_fd);
132 void OnInstanceConnected(base::ScopedFD fd); 144 void OnInstanceConnected(base::ScopedFD fd);
133 145
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 } 185 }
174 186
175 void ArcBridgeBootstrapImpl::Start() { 187 void ArcBridgeBootstrapImpl::Start() {
176 DCHECK(thread_checker_.CalledOnValidThread()); 188 DCHECK(thread_checker_.CalledOnValidThread());
177 DCHECK(delegate_); 189 DCHECK(delegate_);
178 if (state_ != State::STOPPED) { 190 if (state_ != State::STOPPED) {
179 VLOG(1) << "Start() called when instance is not stopped"; 191 VLOG(1) << "Start() called when instance is not stopped";
180 return; 192 return;
181 } 193 }
182 stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN; 194 stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN;
195 // TODO(crbug.com/628124): Move disk space checking logic to session_manager
196 // to avoid extra D-Bus method call cost.
197 SetState(State::DISK_SPACE_CHECKING);
198 chromeos::CryptohomeClient* cryptohome_client =
199 chromeos::DBusThreadManager::Get()->GetCryptohomeClient();
200 cryptohome_client->GetFreeDiskSpace(base::Bind(
201 &ArcBridgeBootstrapImpl::OnDiskSpaceChecked, weak_factory_.GetWeakPtr()));
202 }
203
204 void ArcBridgeBootstrapImpl::OnDiskSpaceChecked(
205 chromeos::DBusMethodCallStatus call_status,
206 uint64_t disk_free_bytes) {
207 DCHECK(thread_checker_.CalledOnValidThread());
hidehiko 2016/07/14 14:10:26 Could you check if Stop() is called between start(
Shuhei Takahashi 2016/07/15 06:06:09 Done.
208 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
209 LOG(ERROR) << "ARC: Failed to check free disk space.";
210 AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
211 return;
212 }
213 if (disk_free_bytes < kCriticalDiskFreeBytes) {
214 LOG(ERROR) << "ARC: The device is too low on disk space to start ARC";
215 AbortBoot(ArcBridgeService::StopReason::LOW_DISK_SPACE);
216 return;
217 }
183 SetState(State::SOCKET_CREATING); 218 SetState(State::SOCKET_CREATING);
184 base::PostTaskAndReplyWithResult( 219 base::PostTaskAndReplyWithResult(
185 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 220 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE,
186 base::Bind(&ArcBridgeBootstrapImpl::CreateSocket), 221 base::Bind(&ArcBridgeBootstrapImpl::CreateSocket),
187 base::Bind(&ArcBridgeBootstrapImpl::OnSocketCreated, 222 base::Bind(&ArcBridgeBootstrapImpl::OnSocketCreated,
188 weak_factory_.GetWeakPtr())); 223 weak_factory_.GetWeakPtr()));
189 } 224 }
190 225
191 // static 226 // static
192 base::ScopedFD ArcBridgeBootstrapImpl::CreateSocket() { 227 base::ScopedFD ArcBridgeBootstrapImpl::CreateSocket() {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 } 437 }
403 438
404 } // namespace 439 } // namespace
405 440
406 // static 441 // static
407 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() { 442 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() {
408 return base::WrapUnique(new ArcBridgeBootstrapImpl()); 443 return base::WrapUnique(new ArcBridgeBootstrapImpl());
409 } 444 }
410 445
411 } // namespace arc 446 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698