libzbc is a user library providing functions for manipulating ZBC and ZAC disks. libzbc command implementation is compliant with the latest published versions of the ZBC and ZAC standards defined by INCITS technical committees T10 and T13 (respectively).
In addition to supporting ZBC and ZAC disks, libzbc also implements an emulation mode allowing the library to imitate the behavior of a host managed zoned disk using a regular file or a standard block device as the backing store.
The libzbc project was formerly hosted on GitHub as part of the HGST organization. libzbc repository has since then moved to the Western Digital Corporation organization on GitHub.
libzbc also provides a test suite allowing to test the conformance of disks and HBAs to the ZBC and ZAC standards. In order to make the test suite available, libzbc needs to be configured using --with-test option prior to building and installing the library. The usage of this test suite is described in more details here.
libzbc provides a unified application programming interface (API) that is independent of the zone model and interface of the disk being used. Internally, four different types of device drivers are used to handle device interface dependent commands.
- ZAC ATA Driver This driver is used to handle direct delivery of ATA commands to ZAC disks through the SCSI generic driver (direct device access interface).
- ZBC SCSI Driver This driver primarily handles SCSI commands directed at ZBC SCSI disks, but can also be used to control ZAC ATA disks if a functional SCSI to ATA (SAT) command translation layer is functional in the command path. SAT may be provided either by the kernel libata subsystem for ATA disks connected to SATA adapters or by a SAS host bus adapter (HBA) for SATA disks connected to such adapter.
- Zoned Block Device Driver This driver uses the kernel ZBD interface to control both ZBC and ZAC disks. This driver is only available if the kernel zoned block device support is present and enabled.
- File Emulation Driver This driver implements emulation of a host managed ZBC disk using a regular file or regular block device as backend storage. This driver is intended for development only. A more advanced ZBC disk emulation solution is provided by the tcmu-runner project.
The figure below shows this structure.
libzbc provides functions for discovering the zone configuration of a zoned device and for accessing the device. Accesses to the device may result in changes to the condition, attributes or state of device zones (such as write pointer location in sequential zones). These changes are not internally tracked by libzbc. That is, libzbc is stateless.
The functions provided to obtain the device zone information only make a "snapshot" of the zone condition and state when executed. It is the responsibility of applications to implement tracking of the device zone changes such as the increasing write pointer position of a sequential zone after the completion of write requests to the zone.
All libzbc functions, since version 5.0.0, use a 512 bytes sector unit for reporting zone information and as the sector addressing unit for device accesses regardless of the actual device logical block size. This unification in the unit used by all functions can simplify application development by hiding potential differences in logical block sizes between devices. However, application programmers must be careful to always implement accesses (read or write) to the device aligned to the device logical block size. Furthermore, on host managed zoned devices, write operations to sequential zones must be aligned to the device physical block size.
The main functions provided by libzbc are as follows.
|zbc_open()||Open a zoned device|
|zbc_close()||Close a zoned device|
|zbc_get_device_info()||Get device information|
|zbc_report_nr_zones()||Get the number of zones|
|zbc_report_zones()||Get zone information|
|zbc_list_zones()||Get zone information|
|zbc_zone_operation()||Execute a zone operation|
|zbc_open_zone()||Explicitly open a zone|
|zbc_close_zone()||Close an open zone|
|zbc_finish_zone()||Finish a zone|
|zbc_reset_zone()||Reset a zone write pointer|
|zbc_pread()||Read data from a zone|
|zbc_pwrite()||Write data to a zone|
|zbc_flush()||Flush data to disk|
More detailed information about these functions usage and behavior can be found
in the comments of libzbc header file. This header file is by default
libzbc does not implement any mutual exclusion mechanism for multi-thread or multi-process applications. This implies that it is the responsibility of application to synchronize the execution of conflicting operations targeting the same zone. A typical example of such case is concurrent write operations to the same zone by multiple threads which may result in write errors without write ordering control by the application.
The following functions are also provided by libzbc to facilitate application development and tests.
|zbc_set_log_level()||Set log level of the library functions|
|zbc_device_is_zoned()||Test if a device is a zoned block device|
|zbc_print_device_info()||Print to a file (stream) a device information|
|zbc_device_type_str()||Get a string description of a device type|
|zbc_device_model_str()||Get a string description of a device model|
|zbc_zone_type_str()||Get a string description of a zone type|
|zbc_zone_condition_str()||Get a string description of a zone condition|
|zbc_errno()||Return sense key and sense code of the last command executed|
|zbc_sk_str()||Get a string description of a sense key|
|zbc_asc_ascq_str()||Get a string description of a sense code|
All functions will behave in the same manner regardless of the type of disk
being used. The only exception to this principle is the
inability to report detailed error information when the zoned block device
driver is used. The reason for this is that the kernel I/O stack does not have
the ability to propagate up to the application the detailed information provided
in command sense data with failed commands.
libzbc also provides several command line applications to manipulate zoned disks by calling the library functions. The list of applications provided is shown in the table below.
|gzbc||gzbc provides a graphical user interface showing zone information of a zoned device|
|zbc_info||Get information on a disk|
|zbc_report_zones||List the zones of a device|
|zbc_reset_zone||Reset the write pointer of sequential zones|
|zbc_open_zone||Explicitly open a sequential write zone|
|zbc_close_zone||Close an open sequential write zone|
|zbc_finish_zone||Transition a sequential write zone to the full condition|
|zbc_read_zone||Read a zone sectors|
|zbc_write_zone||Write a zone sectors|
The following tools are also provided to create and modify the regular file or regular block device used as backend storage with libzbc emulation mode.
|zbc_set_zones||Initialize (format) a regular file or regular disk to be used with libzbc emulation mode|
|zbc_set_write_ptr||Change the write pointer position of the sequential zones of an emulated disk (intended for testing purposes only as this is not a valid operation for physical ZBC devices|
All utilities output a help message when executed without any argument.
zbc_info displays information about a disk, including regular block devices.
zbc_report_zones illustrates the use of libzbc zone reporting functions zbc_report_zones(), zbc_report_nr_zones() and zbc_list_zones().
The output of zbc_report_zones can also be limited using the option
(reporting options) for filtering the zones reported, or the option
limit the output to the number of zones that would be reported.
zbc_write_zone sequentially writes data to a zone. If the zone is a sequential zone, the write pointer position advances until the zone is full. By default, zbc_write_zone will write the entire zone. For instance, using the disk used in the previous example, the first sequential write zone (zone number 524) can be written with 512 KB writes until full with the following command.
The written zone can then be reset using zbc_reset_zone.
All sequential write zones of a device can be reset using the option
gzbc provides a graphical user interface showing the zone configuration and state of a zoned device. gzbc also displays the write status (write pointer position) of zones graphically using color coding (red for written sectors and green for unwritten sectors). Some operations on zones can also be executed directly from the interface (reset zone write pointer, open zone, close zone, etc).
libzbc emulation mode requires a regular file or a regular block device as backend storage. The size of the file or the capacity of the block device used will be used as the emulated device capacity.
For example, the following commands will create a 10GB file name
that can be used for an emulated disk.
This file can now be initialized to be used with libzbc emulation mode.
The file can now be used with libzbc library functions and tools similarly to any physical zoned block device.