1// Copyright 2015 The Chromium Authors 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "components/metrics/drive_metrics_provider.h" 6 7#include <CoreFoundation/CoreFoundation.h> 8#include <DiskArbitration/DiskArbitration.h> 9#import <Foundation/Foundation.h> 10#include <IOKit/IOKitLib.h> 11#include <IOKit/storage/IOStorageDeviceCharacteristics.h> 12#include <stdlib.h> 13#include <sys/stat.h> 14 15#include "base/files/file_path.h" 16#include "base/mac/foundation_util.h" 17#include "base/mac/mac_util.h" 18#include "base/mac/scoped_cftyperef.h" 19#include "base/mac/scoped_ioobject.h" 20 21namespace metrics { 22 23// static 24bool DriveMetricsProvider::HasSeekPenalty(const base::FilePath& path, 25 bool* has_seek_penalty) { 26 struct stat path_stat; 27 if (stat(path.value().c_str(), &path_stat) < 0) 28 return false; 29 30 const char* dev_name = devname(path_stat.st_dev, S_IFBLK); 31 if (!dev_name) 32 return false; 33 34 std::string bsd_name("/dev/"); 35 bsd_name.append(dev_name); 36 37 base::ScopedCFTypeRef<DASessionRef> session( 38 DASessionCreate(kCFAllocatorDefault)); 39 if (!session) 40 return false; 41 42 base::ScopedCFTypeRef<DADiskRef> disk( 43 DADiskCreateFromBSDName(kCFAllocatorDefault, session, bsd_name.c_str())); 44 if (!disk) 45 return false; 46 47 base::mac::ScopedIOObject<io_object_t> io_media(DADiskCopyIOMedia(disk)); 48 base::ScopedCFTypeRef<CFDictionaryRef> characteristics( 49 static_cast<CFDictionaryRef>(IORegistryEntrySearchCFProperty( 50 io_media, kIOServicePlane, CFSTR(kIOPropertyDeviceCharacteristicsKey), 51 kCFAllocatorDefault, 52 kIORegistryIterateRecursively | kIORegistryIterateParents))); 53 if (!characteristics) 54 return false; 55 56 CFStringRef type_ref = base::mac::GetValueFromDictionary<CFStringRef>( 57 characteristics, CFSTR(kIOPropertyMediumTypeKey)); 58 if (!type_ref) 59 return false; 60 61 NSString* type = base::mac::CFToNSCast(type_ref); 62 if ([type isEqualToString:@kIOPropertyMediumTypeRotationalKey]) { 63 *has_seek_penalty = true; 64 return true; 65 } 66 if ([type isEqualToString:@kIOPropertyMediumTypeSolidStateKey]) { 67 *has_seek_penalty = false; 68 return true; 69 } 70 71 // TODO(dbeam): should I look for these Rotational/Solid State keys in 72 // |characteristics|? What if I find device characteristic but there's no 73 // type? Assume rotational? 74 return false; 75} 76 77} // namespace metrics 78