| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chromeos/disks/disk_mount_manager.h" | 5 #include "chromeos/disks/disk_mount_manager.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 base::Bind(&DiskMountManagerImpl::OnMountCompleted, | 76 base::Bind(&DiskMountManagerImpl::OnMountCompleted, |
| 77 weak_ptr_factory_.GetWeakPtr(), | 77 weak_ptr_factory_.GetWeakPtr(), |
| 78 MOUNT_ERROR_INTERNAL, | 78 MOUNT_ERROR_INTERNAL, |
| 79 source_path, | 79 source_path, |
| 80 type, | 80 type, |
| 81 "")); | 81 "")); |
| 82 } | 82 } |
| 83 | 83 |
| 84 // DiskMountManager override. | 84 // DiskMountManager override. |
| 85 virtual void UnmountPath(const std::string& mount_path, | 85 virtual void UnmountPath(const std::string& mount_path, |
| 86 UnmountOptions options) OVERRIDE { | 86 UnmountOptions options, |
| 87 const UnmountPathCallback& callback) OVERRIDE { |
| 87 UnmountChildMounts(mount_path); | 88 UnmountChildMounts(mount_path); |
| 88 cros_disks_client_->Unmount(mount_path, options, | 89 cros_disks_client_->Unmount(mount_path, options, |
| 89 base::Bind(&DiskMountManagerImpl::OnUnmountPath, | 90 base::Bind(&DiskMountManagerImpl::OnUnmountPath, |
| 90 weak_ptr_factory_.GetWeakPtr(), | 91 weak_ptr_factory_.GetWeakPtr(), |
| 92 callback, |
| 91 true), | 93 true), |
| 92 base::Bind(&DiskMountManagerImpl::OnUnmountPath, | 94 base::Bind(&DiskMountManagerImpl::OnUnmountPath, |
| 93 weak_ptr_factory_.GetWeakPtr(), | 95 weak_ptr_factory_.GetWeakPtr(), |
| 96 callback, |
| 94 false)); | 97 false)); |
| 95 } | 98 } |
| 96 | 99 |
| 97 // DiskMountManager override. | 100 // DiskMountManager override. |
| 98 virtual void FormatMountedDevice(const std::string& mount_path) OVERRIDE { | 101 virtual void FormatMountedDevice(const std::string& mount_path) OVERRIDE { |
| 99 MountPointMap::const_iterator mount_point = mount_points_.find(mount_path); | 102 MountPointMap::const_iterator mount_point = mount_points_.find(mount_path); |
| 100 if (mount_point == mount_points_.end()) { | 103 if (mount_point == mount_points_.end()) { |
| 101 LOG(ERROR) << "Mount point with path \"" << mount_path << "\" not found."; | 104 LOG(ERROR) << "Mount point with path \"" << mount_path << "\" not found."; |
| 102 OnFormatDevice(mount_path, false); | 105 OnFormatDevice(mount_path, false); |
| 103 return; | 106 return; |
| 104 } | 107 } |
| 105 | 108 |
| 106 std::string device_path = mount_point->second.source_path; | 109 std::string device_path = mount_point->second.source_path; |
| 107 DiskMap::const_iterator disk = disks_.find(device_path); | 110 DiskMap::const_iterator disk = disks_.find(device_path); |
| 108 if (disk == disks_.end()) { | 111 if (disk == disks_.end()) { |
| 109 LOG(ERROR) << "Device with path \"" << device_path << "\" not found."; | 112 LOG(ERROR) << "Device with path \"" << device_path << "\" not found."; |
| 110 OnFormatDevice(device_path, false); | 113 OnFormatDevice(device_path, false); |
| 111 return; | 114 return; |
| 112 } | 115 } |
| 113 | 116 |
| 114 if (formatting_pending_.find(device_path) != formatting_pending_.end()) { | 117 UnmountPath(disk->second->mount_path(), |
| 115 LOG(ERROR) << "Formatting is already pending: " << mount_path; | 118 UNMOUNT_OPTIONS_NONE, |
| 116 OnFormatDevice(device_path, false); | 119 base::Bind(&DiskMountManagerImpl::OnUnmountPathForFormat, |
| 117 return; | 120 weak_ptr_factory_.GetWeakPtr(), |
| 118 } | 121 device_path)); |
| 119 | |
| 120 // Formatting process continues, after unmounting. | |
| 121 formatting_pending_.insert(device_path); | |
| 122 UnmountPath(disk->second->mount_path(), UNMOUNT_OPTIONS_NONE); | |
| 123 } | 122 } |
| 124 | 123 |
| 125 // DiskMountManager override. | 124 // DiskMountManager override. |
| 126 virtual void UnmountDeviceRecursively( | 125 virtual void UnmountDeviceRecursively( |
| 127 const std::string& device_path, | 126 const std::string& device_path, |
| 128 const UnmountDeviceRecursivelyCallbackType& callback) OVERRIDE { | 127 const UnmountDeviceRecursivelyCallbackType& callback) OVERRIDE { |
| 129 std::vector<std::string> devices_to_unmount; | 128 std::vector<std::string> devices_to_unmount; |
| 130 | 129 |
| 131 // Get list of all devices to unmount. | 130 // Get list of all devices to unmount. |
| 132 int device_path_len = device_path.length(); | 131 int device_path_len = device_path.length(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 std::string mount_path = mount_path_in; | 250 std::string mount_path = mount_path_in; |
| 252 // Let's make sure mount path has trailing slash. | 251 // Let's make sure mount path has trailing slash. |
| 253 if (mount_path[mount_path.length() - 1] != '/') | 252 if (mount_path[mount_path.length() - 1] != '/') |
| 254 mount_path += '/'; | 253 mount_path += '/'; |
| 255 | 254 |
| 256 for (MountPointMap::iterator it = mount_points_.begin(); | 255 for (MountPointMap::iterator it = mount_points_.begin(); |
| 257 it != mount_points_.end(); | 256 it != mount_points_.end(); |
| 258 ++it) { | 257 ++it) { |
| 259 if (StartsWithASCII(it->second.source_path, mount_path, | 258 if (StartsWithASCII(it->second.source_path, mount_path, |
| 260 true /*case sensitive*/)) { | 259 true /*case sensitive*/)) { |
| 261 UnmountPath(it->second.mount_path, UNMOUNT_OPTIONS_NONE); | 260 // TODO(tbarzic): Handle the case where this fails. |
| 261 UnmountPath(it->second.mount_path, |
| 262 UNMOUNT_OPTIONS_NONE, |
| 263 UnmountPathCallback()); |
| 262 } | 264 } |
| 263 } | 265 } |
| 264 } | 266 } |
| 265 | 267 |
| 266 // Callback for UnmountDeviceRecursively. | 268 // Callback for UnmountDeviceRecursively. |
| 267 void OnUnmountDeviceRecursively( | 269 void OnUnmountDeviceRecursively( |
| 268 UnmountDeviceRecursivelyCallbackData* cb_data, | 270 UnmountDeviceRecursivelyCallbackData* cb_data, |
| 269 bool success, | 271 bool success, |
| 270 const std::string& mount_path) { | 272 const std::string& mount_path) { |
| 271 if (success) { | 273 if (success) { |
| 272 // Do standard processing for Unmount event. | 274 // Do standard processing for Unmount event. |
| 273 OnUnmountPath(true, mount_path); | 275 OnUnmountPath(UnmountPathCallback(), true, mount_path); |
| 274 LOG(INFO) << mount_path << " unmounted."; | 276 LOG(INFO) << mount_path << " unmounted."; |
| 275 } | 277 } |
| 276 // This is safe as long as all callbacks are called on the same thread as | 278 // This is safe as long as all callbacks are called on the same thread as |
| 277 // UnmountDeviceRecursively. | 279 // UnmountDeviceRecursively. |
| 278 cb_data->num_pending_callbacks--; | 280 cb_data->num_pending_callbacks--; |
| 279 | 281 |
| 280 if (cb_data->num_pending_callbacks == 0) { | 282 if (cb_data->num_pending_callbacks == 0) { |
| 281 // This code has a problem that the |success| status used here is for the | 283 // This code has a problem that the |success| status used here is for the |
| 282 // last "unmount" callback, but not whether all unmounting is succeeded. | 284 // last "unmount" callback, but not whether all unmounting is succeeded. |
| 283 // TODO(hidehiko): Fix the issue. | 285 // TODO(hidehiko): Fix the issue. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 // disk might have been removed by now? | 323 // disk might have been removed by now? |
| 322 return; | 324 return; |
| 323 } | 325 } |
| 324 Disk* disk = iter->second; | 326 Disk* disk = iter->second; |
| 325 DCHECK(disk); | 327 DCHECK(disk); |
| 326 disk->set_mount_path(mount_info.mount_path); | 328 disk->set_mount_path(mount_info.mount_path); |
| 327 } | 329 } |
| 328 } | 330 } |
| 329 | 331 |
| 330 // Callback for UnmountPath. | 332 // Callback for UnmountPath. |
| 331 void OnUnmountPath(bool success, const std::string& mount_path) { | 333 void OnUnmountPath(const UnmountPathCallback& callback, |
| 334 bool success, |
| 335 const std::string& mount_path) { |
| 332 MountPointMap::iterator mount_points_it = mount_points_.find(mount_path); | 336 MountPointMap::iterator mount_points_it = mount_points_.find(mount_path); |
| 333 if (mount_points_it == mount_points_.end()) | 337 if (mount_points_it == mount_points_.end()) { |
| 338 // The path was unmounted, but not as a result of this unmount request, |
| 339 // so return error. |
| 340 if (!callback.is_null()) |
| 341 callback.Run(MOUNT_ERROR_INTERNAL); |
| 334 return; | 342 return; |
| 343 } |
| 335 | 344 |
| 336 NotifyMountStatusUpdate( | 345 NotifyMountStatusUpdate( |
| 337 UNMOUNTING, | 346 UNMOUNTING, |
| 338 success ? MOUNT_ERROR_NONE : MOUNT_ERROR_INTERNAL, | 347 success ? MOUNT_ERROR_NONE : MOUNT_ERROR_INTERNAL, |
| 339 MountPointInfo(mount_points_it->second.source_path, | 348 MountPointInfo(mount_points_it->second.source_path, |
| 340 mount_points_it->second.mount_path, | 349 mount_points_it->second.mount_path, |
| 341 mount_points_it->second.mount_type, | 350 mount_points_it->second.mount_type, |
| 342 mount_points_it->second.mount_condition)); | 351 mount_points_it->second.mount_condition)); |
| 343 | 352 |
| 344 std::string path(mount_points_it->second.source_path); | 353 std::string path(mount_points_it->second.source_path); |
| 345 if (success) | 354 if (success) |
| 346 mount_points_.erase(mount_points_it); | 355 mount_points_.erase(mount_points_it); |
| 347 | 356 |
| 348 DiskMap::iterator disk_iter = disks_.find(path); | 357 DiskMap::iterator disk_iter = disks_.find(path); |
| 349 if (disk_iter != disks_.end()) { | 358 if (disk_iter != disks_.end()) { |
| 350 DCHECK(disk_iter->second); | 359 DCHECK(disk_iter->second); |
| 351 if (success) | 360 if (success) |
| 352 disk_iter->second->clear_mount_path(); | 361 disk_iter->second->clear_mount_path(); |
| 353 } | 362 } |
| 354 | 363 |
| 355 FormatTaskSet::iterator format_iter = formatting_pending_.find(path); | 364 if (!callback.is_null()) |
| 356 // Check if there is a formatting scheduled. | 365 callback.Run(success ? MOUNT_ERROR_NONE : MOUNT_ERROR_INTERNAL); |
| 357 if (format_iter != formatting_pending_.end()) { | 366 } |
| 358 formatting_pending_.erase(format_iter); | 367 |
| 359 if (success && disk_iter != disks_.end()) { | 368 void OnUnmountPathForFormat(const std::string& device_path, |
| 360 FormatUnmountedDevice(path); | 369 MountError error_code) { |
| 361 } else { | 370 if (error_code == MOUNT_ERROR_NONE && |
| 362 OnFormatDevice(path, false); | 371 disks_.find(device_path) != disks_.end()) { |
| 363 } | 372 FormatUnmountedDevice(device_path); |
| 373 } else { |
| 374 OnFormatDevice(device_path, false); |
| 364 } | 375 } |
| 365 } | 376 } |
| 366 | 377 |
| 367 // Starts device formatting. | 378 // Starts device formatting. |
| 368 void FormatUnmountedDevice(const std::string& device_path) { | 379 void FormatUnmountedDevice(const std::string& device_path) { |
| 369 DiskMap::const_iterator disk = disks_.find(device_path); | 380 DiskMap::const_iterator disk = disks_.find(device_path); |
| 370 DCHECK(disk != disks_.end() && disk->second->mount_path().empty()); | 381 DCHECK(disk != disks_.end() && disk->second->mount_path().empty()); |
| 371 | 382 |
| 372 const char kFormatVFAT[] = "vfat"; | 383 const char kFormatVFAT[] = "vfat"; |
| 373 cros_disks_client_->FormatDevice( | 384 cros_disks_client_->FormatDevice( |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 CrosDisksClient* cros_disks_client_; | 598 CrosDisksClient* cros_disks_client_; |
| 588 | 599 |
| 589 // The list of disks found. | 600 // The list of disks found. |
| 590 DiskMountManager::DiskMap disks_; | 601 DiskMountManager::DiskMap disks_; |
| 591 | 602 |
| 592 DiskMountManager::MountPointMap mount_points_; | 603 DiskMountManager::MountPointMap mount_points_; |
| 593 | 604 |
| 594 typedef std::set<std::string> SystemPathPrefixSet; | 605 typedef std::set<std::string> SystemPathPrefixSet; |
| 595 SystemPathPrefixSet system_path_prefixes_; | 606 SystemPathPrefixSet system_path_prefixes_; |
| 596 | 607 |
| 597 // A map from device path (e.g. /sys/devices/pci0000:00/.../sdb/sdb1)) to file | |
| 598 // path (e.g. /dev/sdb). | |
| 599 // Devices in this map are supposed to be formatted, but are currently waiting | |
| 600 // to be unmounted. When device is in this map, the formatting process HAVEN'T | |
| 601 // started yet. | |
| 602 typedef std::set<std::string> FormatTaskSet; | |
| 603 FormatTaskSet formatting_pending_; | |
| 604 | |
| 605 base::WeakPtrFactory<DiskMountManagerImpl> weak_ptr_factory_; | 608 base::WeakPtrFactory<DiskMountManagerImpl> weak_ptr_factory_; |
| 606 | 609 |
| 607 DISALLOW_COPY_AND_ASSIGN(DiskMountManagerImpl); | 610 DISALLOW_COPY_AND_ASSIGN(DiskMountManagerImpl); |
| 608 }; | 611 }; |
| 609 | 612 |
| 610 } // namespace | 613 } // namespace |
| 611 | 614 |
| 612 DiskMountManager::Disk::Disk(const std::string& device_path, | 615 DiskMountManager::Disk::Disk(const std::string& device_path, |
| 613 const std::string& mount_path, | 616 const std::string& mount_path, |
| 614 const std::string& system_path, | 617 const std::string& system_path, |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 VLOG(1) << "DiskMountManager Shutdown completed"; | 758 VLOG(1) << "DiskMountManager Shutdown completed"; |
| 756 } | 759 } |
| 757 | 760 |
| 758 // static | 761 // static |
| 759 DiskMountManager* DiskMountManager::GetInstance() { | 762 DiskMountManager* DiskMountManager::GetInstance() { |
| 760 return g_disk_mount_manager; | 763 return g_disk_mount_manager; |
| 761 } | 764 } |
| 762 | 765 |
| 763 } // namespace disks | 766 } // namespace disks |
| 764 } // namespace chromeos | 767 } // namespace chromeos |
| OLD | NEW |