Editor
90
edits
Line 98: | Line 98: | ||
|- | |- | ||
| Data block || Use dump_data to write the contents of the data block to a DATA/WRITE record in the send stream | | Data block || Use dump_data to write the contents of the data block to a DATA/WRITE record in the send stream | ||
|} | |||
Each of the dump_* functions listed above eventually calls into dump_bytes with its specially formatted payload for whichever record it is writing (FREE, FREEOBJECTS, OBJECT, etc). A list of all record types can be found in the type dmu_replay_record. | |||
So far we’ve covered the full stack trace from requesting a send using the zfs command line tool down to the dump_bytes function which does the actual write of ZFS send records from the kernel. However, ZFS send normally (though not necessarily) has a matching ZFS recv which takes the send stream and applies the changes defined by the contained records to some other ZFS dataset. How does that work? | |||
Similar to ZFS send, the most common interface to ZFS recv is through the zfs command line utility with the recv/receive subcommand. The core logic of ZFS receive is located in the kernel down a stack trace such as: zfs_do_receive => zfs_receive => zfs_receive_impl => zfs_receive_one => zfs_ioctl(ZFS_IOC_RECV) => zfs_ioc_recv. Of course, these intermediate functions are necessary to perform setup and error handling, but they aren’t particularly interesting for this overview of the core functionality of ZFS receive. (TODO: I’m kind of punting on this at the moment so I can focus on the interesting code in dmu_recv_begin, dmu_recv_stream, and dmu_recv_end but I should probably go back and mention some things about the functions that are higher in the stack. I’m also getting a little tired of writing so in general receive is probably going to need more fleshing out). | |||
The implementation of ZFS receive centers around three functions: dmu_recv_begin, dmu_recv_stream, and dmu_recv_end. dmu_recv_begin performs setup for receiving the stream’s records based on the information contained in the BEGIN record. This includes either creating a new ZFS dataset for the operations in the stream to be applied to, or creating a clone of an existing filessytem to apply those operations to (in the case of an incremental receive). This work is performed inside a DSL sync task. | |||
dmu_recv_stream performs the processing of the FREE, FREEOBJECTS, OBJECT, etc records that follow the BEGIN record. Using restore_read to read individual records, dmu_recv_stream loops until it reaches the END record or an error occurs. For each type of record it calls a different method which executes the operations on the dataset that receive has been provided. | |||
{| border="1" style="border-collapse:collapse; text-align: center" | |||
|- | |||
| '''Record Type''' || '''Method Called''' | |||
|- | |||
| OBJECT || restore_object | |||
|- | |||
| FREEOBJECTS || restore_freeobjects | |||
|- | |||
| WRITE || restore_write | |||
|- | |||
| WRITE_BYREF | restore_write_byref | |||
|- | |||
| FREE || restore_free | |||
|- | |||
| END || restore_end | |||
|- | |||
| SPILL || restore_spill | |||
|- | |||
| Anything else || Exit with EINVAL | |||
|} | |} |