Disk Arbitration

| No Comments

Disk Arbitration is what is used on the Mac to handle automatic mounting of volumes and various other disk related things. When you insert a disk, the kernel will instantiate drivers for it and notify the Disk Arbitration daemon. It will then ask filesystem plugins if they recognise the volume and if they do it will usually proceed to mount them.

Using Disk Arbitration, you can┬ásend requests to eject disks, mount and unmount volumes, rename volumes and you can claim a disk for exclusive use. For each of those operations you can also approve or reject requests that other applications make. It’s not actually enforced: you could still force a volume to be unmounted and claiming a disk for exclusive use doesn’t stop anyone else from using it (like advisory file locks). You can see some of these notifications flying around by using disktool with the undocumented -y flag. You can get more debug by hacking the com.apple.diskarbitration.plist file in /System/Library/LaunchDaemons and adding the -d flag to the argument list. You’ll then get /var/log/diskarbitrationd.log.

diskarbitrationd is the main daemon that’s responsible for all this stuff. The source code for it and related things can be found on the Open Source part of Apple’s site. To use Disk Arbitration from within your application, you need to link to the Disk Arbitration framework. It was a private framework in Panther (10.3) but was made public in Tiger (10.4). Things like Spotlight use it to know when to stop indexing a volume when you want to unmount a volume and you should use it too if you’re writing a similar application.

There are a couple of files that it looks at to tell it what to do. /etc/fstab is one of them. The shipped version (in Leopard) has some examples in the comments of /etc/fstab and the man page looks pretty good. By making the appropriate change to this file, you can, amongst other things, stop a volume from being automatically mounted. The other file it looks at is /var/db/volinfo.database. This text file stores the setting of the “Ignore ownership of this volume” flag that you see in Finder.

Disk Arbitration will also give you information about all the disks and volumes on the system. Here’s the kind of information it might have about your startup volume:

    DAAppearanceTime = 244372661.099552;
    DABusName = PMP;
    DABusPath = "IODeviceTree:/PCI0@0/SATA@1F,2/PRT2@2/PMP@0";
    DADeviceInternal = 1;
    DADeviceModel = "WDC WD1600JS-40NGB2                     ";
    DADevicePath = "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleAHCI/PRT2@2/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice";
    DADeviceProtocol = SATA;
    DADeviceRevision = "10.02E04";
    DADeviceUnit = 0;
    DAMediaBSDMajor = 14;
    DAMediaBSDMinor = 3;
    DAMediaBSDName = disk0s3;
    DAMediaBSDUnit = 0;
    DAMediaBlockSize = 512;
    DAMediaContent = "48465300-0000-11AA-AA11-00306543ECAC";
    DAMediaEjectable = 0;
    DAMediaIcon =     {
        CFBundleIdentifier = "com.apple.iokit.IOStorageFamily";
        IOBundleResourceFile = "Internal.icns";
    DAMediaKind = IOMedia;
    DAMediaLeaf = 1;
    DAMediaName = "Macintosh HD";
    DAMediaPath = "IODeviceTree:/PCI0@0/SATA@1F,2/PRT2@2/PMP@0/@0:3";
    DAMediaRemovable = 0;
    DAMediaSize = 138155196416;
    DAMediaUUID = <NSCFType: 0xd32f150>;
    DAMediaWhole = 0;
    DAMediaWritable = 1;
    DAVolumeKind = hfs;
    DAVolumeMountable = 1;
    DAVolumeName = "Macintosh HD";
    DAVolumeNetwork = 0;
    DAVolumePath = file://localhost/;
    DAVolumeUUID = <NSCFType: 0xd3316b0>;

That’s obviously for a specific partition on a disk. There’s another entry that represents the whole disk.

Something to note regarding disk/volume UUIDs: GUID partition schemes have a UUID that is used for the partition but in addition to that, there is a UUID that is stored as part of the file system (in the case of HFS+, it’s not actually a UUID but eight bytes that get turned into a UUID), so if you do end up using them, make sure you know which one you’re dealing with. The UUID reported by Disk Arbitration happens to be the file system UUID but the UUID property of IOMedia objects is from the partition table.

One thing that isn’t ideal is there’s no actual notification indicating when the system wants to eject a disk. You can use the eject approval notification, but then there’s no way to find out if the eject was ultimately approved. This would be a problem for, say, an indexing application, where it might want to release all resources for the disk (so that the eject will actually succeed) when an eject is requested. Spotlight probably uses the eject approval callback, but the only way it would be able to restart indexing on a volume that failed to eject, is by checking again after a certain amount of time (I don’t know if it does that).

Another problem I found recently is that bad clients can cause it to eat memory and this in turn can cause kernel memory leaks (of IOMedia objects). For example, on the currently shipping version of Leopard, the WindowServer process doesn’t appear to be properly processing Disk Arbitration notifications (probably because it uses a funny run loop) which is ultimately causing IOMedia objects to hang around in the kernel. It’s not a big deal but it does need fixing.

Oh, and one other thing, the system does not like it if Disk Arbitration crashes. Even though launchd will restart it, you still need to reboot as Finder and other processes don’t connect to the new version.

Leave a comment