Inside iCloud Drive: Downloading

In the last episode, I worked through the sync-down from iCloud Drive to a client Mac (B) which occurs when another Mac (A) uploads a new document. At the end of that stage, iCloud Drive shows the new/changed items, but they have not yet been downloaded to Mac B. In this episode, I will work through what happens on Mac B when it decides to download those new/changed items. Elapsed times in seconds are continuous with those of the previous article.

These are summarised in an updated overview diagram.


macOS doesn’t automatically download all new or changed items from iCloud Drive, nor could it. Instead, it assesses whether there is sufficient purgeable storage on each Mac or device sharing that iCloud Drive. If you think about it, this is inevitable. You might have 200 GB of total space on iCloud Drive with 150 GB of files on it. One Mac, with ample free space on its startup volume, might keep a local copy of everything on iCloud Drive. Another Mac, perhaps a MacBook with an internal 256 GB SSD already containing 200 GB of local files, couldn’t store much of the contents of the iCloud Drive locally.

macOS must therefore enforce a quota for local iCloud Drive storage, which is marked as purgeable, so that its contents can be ‘returned’ to the cloud should local free space fall. In that case, all that is left in local storage are small stub files representing the complete files held in iCloud.

The decision to download is taken on the basis of a space quota, around 1% of total startup volume capacity. Provided that locally-stored items from iCloud Drive occupy less than the assigned quota, new items will also be downloaded into the local cache. This is marked by the announcement from CloudDocs:
04.871 CloudDocs [NOTICE] we will now download new documents automatically because the account contains less than 5.37 GB

That triggers bird to start a coord-write, or Write (Async) of the new items to their local URL. There is then a run of messages from cloudd referring to nw_resolver_host_resolve_callback, nw_endpoint_resolver_update, and similar, before:
04.894 bird apply-changes

The download sequence starts with an announcement from CloudDocs:
04.913 CloudDocs [NOTICE] downloading 1 documents in
following which bird writes messages of dl-content and client/fetch-records. CloudKit then starts the CKFetchRecordsOperation which forms the great majority of this sequence. This is echoed in cloudd with the message daemon/fetch-records.

The next step in the sequence is announced by CloudKit, running with the cloudd daemon, so the operation name starts with CKD for CloudKit Daemon:
04.927 CloudKit CKDGetRecordsURLRequest
following which cloudd writes url-request and c2-request-task. This phase takes longer, and the next milestone is another message from cloudd:
05.060 [cloudd] url-request-transmission
following which cloudd reports a series of state transitions.

Records are downloaded and decrypted, then cloudd announces it is ready to download the assets themselves:
05.312 [cloudd] daemon/download-assets

This is marked by CloudKit reporting the start of a CKDDownloadAssetsOperation. CloudKit then reports the MMCS options, cloudd records mmcs-get-items, and MMCS gets its options and becomes active in downloading the assets. That is recorded by cloudd with mmcs-get-container and mmcs-get-schedule, then CloudKit reports the asset has been downloaded, confirmed by MMCS:
06.213 CloudKit Downloaded asset
06.219 MMCS Chunk downloads complete. All done! (Get request 0x7fbdb1f07780)

That is echoed by cloudd with mmcs-get-complete, following which it enters another resolver sequence involving nw_resolver_host_resolve_callback, nw_endpoint_resolver_update, etc.

At 06.389, bird writes a series of three messages reporting apply-changes, coord-write and apply-changes, which is followed by MMCS communicating with AppleHttpServer in its last operations.

Once those are complete, the download sequence is ended with reports from CloudKit and CloudDocs:
06.559 CloudKit Finished operation CKDDownloadAssetsOperation
CloudKit Finished operation CKDFetchRecordsOperation
CloudKit Finished operation CKFetchRecordsOperation Download (opportunistic)
CloudDocs [NOTICE] finished downloading 1 documents (1.0 MB) in

At that stage, the new items are in local cached storage on Mac B, and would not require any further downloading unless their contents were to change.

This is summarised in the detailed diagram of this phase.


The brunt of the work in downloading is driven by bird and cloudd, with two periods during which MMCS is active. If either service were to become stuck, downloading would come to a halt. Although killing one or both and letting them restart might be a way of kickstarting the sequence again, there would be a significant risk that it would only exacerbate delays in downloading.

Valuable information for dealing with downloading problems should come in the first instance from Activity Monitor, looking specifically at bird and cloudd. If either looks as if it has come to a grinding halt, examining the log using Cirrus should give a good view of the situation, leading to a decision as to what is its best remedy.

Once downloading is complete, iCloud communications don’t fall silent. CloudDocs follows with a series of getAttributeValues for each of the top-level items in iCloud Drive, and a little later bird calls client/fetch-user-quota to check available space in iCloud storage.

In this particular case, having watched iCloud bring my test file onto Mac B’s local storage, I then dragged that file from iCloud Drive to a local folder in the Finder. As the file was already on my startup volume, it did not have to be downloaded, but bird initiated a sync-up and client/modify-records to record that the file had been removed from iCloud Drive. This resulted in CloudKit starting a CKModifyRecordsOperation.

When that was complete, iCloud pushed a message to Mac B to perform a sync-down to bring the two into complete synchrony.