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

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
« no previous file with comments | « chrome/chrome_browser_chromeos.gypi ('k') | components/arc/arc_bridge_service.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/sys_info.h"
19 #include "base/task_runner_util.h" 20 #include "base/task_runner_util.h"
20 #include "base/threading/thread_checker.h" 21 #include "base/threading/thread_checker.h"
21 #include "base/threading/thread_task_runner_handle.h" 22 #include "base/threading/thread_task_runner_handle.h"
22 #include "base/threading/worker_pool.h" 23 #include "base/threading/worker_pool.h"
23 #include "chromeos/cryptohome/cryptohome_parameters.h" 24 #include "chromeos/cryptohome/cryptohome_parameters.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 base::FilePath::CharType kDiskCheckPath[] = "/home";
47
48 const int64_t kCriticalDiskFreeBytes = 64 << 20; // 64MB
49
45 // This is called when StopArcInstance D-Bus method completes. Since we have the 50 // This is called when StopArcInstance D-Bus method completes. Since we have the
46 // ArcInstanceStopped() callback and are notified if StartArcInstance fails, we 51 // ArcInstanceStopped() callback and are notified if StartArcInstance fails, we
47 // don't need to do anything when StopArcInstance completes. 52 // don't need to do anything when StopArcInstance completes.
48 void DoNothingInstanceStopped(bool) {} 53 void DoNothingInstanceStopped(bool) {}
49 54
50 chromeos::SessionManagerClient* GetSessionManagerClient() { 55 chromeos::SessionManagerClient* GetSessionManagerClient() {
51 // If the DBusThreadManager or the SessionManagerClient aren't available, 56 // If the DBusThreadManager or the SessionManagerClient aren't available,
52 // there isn't much we can do. This should only happen when running tests. 57 // there isn't much we can do. This should only happen when running tests.
53 if (!chromeos::DBusThreadManager::IsInitialized() || 58 if (!chromeos::DBusThreadManager::IsInitialized() ||
54 !chromeos::DBusThreadManager::Get() || 59 !chromeos::DBusThreadManager::Get() ||
55 !chromeos::DBusThreadManager::Get()->GetSessionManagerClient()) 60 !chromeos::DBusThreadManager::Get()->GetSessionManagerClient())
56 return nullptr; 61 return nullptr;
57 return chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); 62 return chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
58 } 63 }
59 64
60 class ArcBridgeBootstrapImpl : public ArcBridgeBootstrap, 65 class ArcBridgeBootstrapImpl : public ArcBridgeBootstrap,
61 public chromeos::SessionManagerClient::Observer { 66 public chromeos::SessionManagerClient::Observer {
62 public: 67 public:
63 // The possible states of the bootstrap connection. In the normal flow, 68 // The possible states of the bootstrap connection. In the normal flow,
64 // the state changes in the following sequence: 69 // the state changes in the following sequence:
65 // 70 //
66 // STOPPED 71 // STOPPED
67 // Start() -> 72 // Start() ->
73 // DISK_SPACE_CHECKING
74 // CheckDiskSpace() -> OnDiskSpaceChecked() ->
68 // SOCKET_CREATING 75 // SOCKET_CREATING
69 // CreateSocket() -> OnSocketCreated() -> 76 // CreateSocket() -> OnSocketCreated() ->
70 // STARTING 77 // STARTING
71 // StartArcInstance() -> OnInstanceStarted() -> 78 // StartArcInstance() -> OnInstanceStarted() ->
72 // STARTED 79 // STARTED
73 // AcceptInstanceConnection() -> OnInstanceConnected() -> 80 // AcceptInstanceConnection() -> OnInstanceConnected() ->
74 // READY 81 // READY
75 // 82 //
76 // When Stop() or AbortBoot() is called from any state, either because an 83 // 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: 84 // operation resulted in an error or because the user is logging out:
78 // 85 //
79 // (any) 86 // (any)
80 // Stop()/AbortBoot() -> 87 // Stop()/AbortBoot() ->
81 // STOPPING 88 // STOPPING
82 // StopInstance() -> 89 // StopInstance() ->
83 // STOPPED 90 // STOPPED
84 // 91 //
85 // When the instance crashes while it was ready, it will be stopped: 92 // When the instance crashes while it was ready, it will be stopped:
86 // READY -> STOPPING -> STOPPED 93 // READY -> STOPPING -> STOPPED
87 // and then restarted: 94 // and then restarted:
88 // STOPPED -> SOCKET_CREATING -> ... -> READY). 95 // STOPPED -> DISK_SPACE_CHECKING -> ... -> READY).
89 // 96 //
90 // Note: Order of constants below matters. Please make sure to sort them 97 // Note: Order of constants below matters. Please make sure to sort them
91 // in chronological order. 98 // in chronological order.
92 enum class State { 99 enum class State {
93 // ARC is not currently running. 100 // ARC is not currently running.
94 STOPPED, 101 STOPPED,
95 102
103 // Checking the disk space.
104 DISK_SPACE_CHECKING,
105
96 // An UNIX socket is being created. 106 // An UNIX socket is being created.
97 SOCKET_CREATING, 107 SOCKET_CREATING,
98 108
99 // The request to start the instance has been sent. 109 // The request to start the instance has been sent.
100 STARTING, 110 STARTING,
101 111
102 // The instance has started. Waiting for it to connect to the IPC bridge. 112 // The instance has started. Waiting for it to connect to the IPC bridge.
103 STARTED, 113 STARTED,
104 114
105 // The instance is fully connected. 115 // The instance is fully connected.
106 READY, 116 READY,
107 117
108 // The request to shut down the instance has been sent. 118 // The request to shut down the instance has been sent.
109 STOPPING, 119 STOPPING,
110 }; 120 };
111 121
112 ArcBridgeBootstrapImpl(); 122 ArcBridgeBootstrapImpl();
113 ~ArcBridgeBootstrapImpl() override; 123 ~ArcBridgeBootstrapImpl() override;
114 124
115 // ArcBridgeBootstrap: 125 // ArcBridgeBootstrap:
116 void Start() override; 126 void Start() override;
117 void Stop() override; 127 void Stop() override;
118 128
119 private: 129 private:
120 // Aborts ARC instance boot. This is called from various state-machine 130 // Aborts ARC instance boot. This is called from various state-machine
121 // functions when they encounter an error during boot. 131 // functions when they encounter an error during boot.
122 void AbortBoot(ArcBridgeService::StopReason reason); 132 void AbortBoot(ArcBridgeService::StopReason reason);
123 133
134 // Checks the device disk space.
135 static int64_t CheckDiskSpace();
hidehiko 2016/07/15 14:47:25 Optional: how about "GetFreeDiskSpace()"? "Check"
Shuhei Takahashi 2016/07/19 04:38:00 Good point that we can just bind to AmountOfFreeDi
136 void OnDiskSpaceChecked(int64_t disk_free_bytes);
137
124 // Creates the UNIX socket on the bootstrap thread and then processes its 138 // Creates the UNIX socket on the bootstrap thread and then processes its
125 // file descriptor. 139 // file descriptor.
126 static base::ScopedFD CreateSocket(); 140 static base::ScopedFD CreateSocket();
127 void OnSocketCreated(base::ScopedFD fd); 141 void OnSocketCreated(base::ScopedFD fd);
128 142
129 // Synchronously accepts a connection on |socket_fd| and then processes the 143 // Synchronously accepts a connection on |socket_fd| and then processes the
130 // connected socket's file descriptor. 144 // connected socket's file descriptor.
131 static base::ScopedFD AcceptInstanceConnection(base::ScopedFD socket_fd); 145 static base::ScopedFD AcceptInstanceConnection(base::ScopedFD socket_fd);
132 void OnInstanceConnected(base::ScopedFD fd); 146 void OnInstanceConnected(base::ScopedFD fd);
133 147
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 } 187 }
174 188
175 void ArcBridgeBootstrapImpl::Start() { 189 void ArcBridgeBootstrapImpl::Start() {
176 DCHECK(thread_checker_.CalledOnValidThread()); 190 DCHECK(thread_checker_.CalledOnValidThread());
177 DCHECK(delegate_); 191 DCHECK(delegate_);
178 if (state_ != State::STOPPED) { 192 if (state_ != State::STOPPED) {
179 VLOG(1) << "Start() called when instance is not stopped"; 193 VLOG(1) << "Start() called when instance is not stopped";
180 return; 194 return;
181 } 195 }
182 stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN; 196 stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN;
197 // TODO(crbug.com/628124): Move disk space checking logic to session_manager.
198 SetState(State::DISK_SPACE_CHECKING);
199 base::PostTaskAndReplyWithResult(
200 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE,
201 base::Bind(&ArcBridgeBootstrapImpl::CheckDiskSpace),
202 base::Bind(&ArcBridgeBootstrapImpl::OnDiskSpaceChecked,
203 weak_factory_.GetWeakPtr()));
204 }
205
206 // static
207 int64_t ArcBridgeBootstrapImpl::CheckDiskSpace() {
208 return base::SysInfo::AmountOfFreeDiskSpace(base::FilePath(kDiskCheckPath));
209 }
210
211 void ArcBridgeBootstrapImpl::OnDiskSpaceChecked(int64_t disk_free_bytes) {
212 DCHECK(thread_checker_.CalledOnValidThread());
213 if (state_ != State::DISK_SPACE_CHECKING) {
214 VLOG(1) << "Stop() called while checking disk space";
215 return;
216 }
217 if (disk_free_bytes < 0) {
218 LOG(ERROR) << "ARC: Failed to get free disk space";
219 AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE);
220 return;
221 } else if (disk_free_bytes < kCriticalDiskFreeBytes) {
hidehiko 2016/07/15 14:47:25 return; } if (...) { : return; } to standardi
Shuhei Takahashi 2016/07/19 04:38:00 Done.
222 LOG(ERROR) << "ARC: The device is too low on disk space to start ARC";
223 AbortBoot(ArcBridgeService::StopReason::LOW_DISK_SPACE);
224 return;
225 }
183 SetState(State::SOCKET_CREATING); 226 SetState(State::SOCKET_CREATING);
184 base::PostTaskAndReplyWithResult( 227 base::PostTaskAndReplyWithResult(
185 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, 228 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE,
186 base::Bind(&ArcBridgeBootstrapImpl::CreateSocket), 229 base::Bind(&ArcBridgeBootstrapImpl::CreateSocket),
187 base::Bind(&ArcBridgeBootstrapImpl::OnSocketCreated, 230 base::Bind(&ArcBridgeBootstrapImpl::OnSocketCreated,
188 weak_factory_.GetWeakPtr())); 231 weak_factory_.GetWeakPtr()));
189 } 232 }
190 233
191 // static 234 // static
192 base::ScopedFD ArcBridgeBootstrapImpl::CreateSocket() { 235 base::ScopedFD ArcBridgeBootstrapImpl::CreateSocket() {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 } 445 }
403 446
404 } // namespace 447 } // namespace
405 448
406 // static 449 // static
407 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() { 450 std::unique_ptr<ArcBridgeBootstrap> ArcBridgeBootstrap::Create() {
408 return base::WrapUnique(new ArcBridgeBootstrapImpl()); 451 return base::WrapUnique(new ArcBridgeBootstrapImpl());
409 } 452 }
410 453
411 } // namespace arc 454 } // namespace arc
OLDNEW
« no previous file with comments | « chrome/chrome_browser_chromeos.gypi ('k') | components/arc/arc_bridge_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698