tags:

views:

43

answers:

2

Hi Guys I want to find out the natural block size of the IO media being used in an cocoa application. I saw a function in IOMedia.cpp called "getPreferredBlockSize()" which supposedly gives me my block size. Please can you guys explain me how to use this function in my app or if there is any other method using which i can find the natural block size of the underlying IO media.

Thanks

+1  A: 

You can use the C libc function, which takes a file descriptor and a stat struct and fills the struct in with data. Code like this would work (warning: I didn't test this myself):

#include <sys/stat.h>

/* ... */

struct stat info;
blksize_t preferredBlockSize;
int fd = [myFileHandle fileDescriptor];
if ((stat(fd, &info)) == 0) {
    preferredBlockSize = info.st_blksize;
} else {
    NSLog(@"Could not get file stats");
}

/* Do what you want with preferredBlockSize */

From the fstat() man page:

The st_blksize field gives the "preferred" blocksize for efficient file system I/O. (Writing to a file in smaller chunks may cause an inefficient read-modify-rewrite.)

mipadi
Thanks mipadi i was searching for this since a long time.
King
This is _not_ the native blocksize. For my HD it's around 13MB, but the native blocksize is only 512kb.
Georg
+1  A: 

Here's the code to get the native block size:

#include <sys/stat.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/storage/IOMedia.h>
#include <CoreFoundation/CoreFoundation.h>

// look up device number with stat
struct stat stats;
if (stat(path, &stats) != 0) {
    return;
}
// use st_rdev instead of st_dev if
// the path is a device (/dev/disk0)
int bsd_major = major(stats.st_dev);
int bsd_minor = minor(stats.st_dev);

CFTypeRef keys[2] = { CFSTR(kIOBSDMajorKey), CFSTR(kIOBSDMinorKey) };
CFTypeRef values[2];
values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bsd_major);
values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bsd_minor);

CFDictionaryRef matchingDictionary;
matchingDictionary = CFDictionaryCreate(kCFAllocatorDefault,
                                        &keys, &values,
                                        sizeof(keys) / sizeof(*keys),
                                        &kCFTypeDictionaryKeyCallBacks,
                                        &kCFTypeDictionaryValueCallBacks);

CFRelease(values[0]);
CFRelease(values[1]);
// IOServiceGetMatchingService uses up one reference to the dictionary
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
                                                   matchingDictionary);

if (!service) {
    return;
}
CFNumberRef blockSizeProperty;
blockSizeProperty = (CFNumberRef)IORegistryEntryCreateCFProperty(service,
                                        CFSTR(kIOMediaPreferredBlockSizeKey),
                                        kCFAllocatorDefault, 0);
if (!blockSizeProperty) {
    return;
}

int blockSize;
CFNumberGetValue(blockSizeProperty, kCFNumberIntType, &blockSize);
CFRelease(blockSizeProperty);

// blockSize is the native block size of the device
Georg