DCMD_CAM_DATA_SET_MGNT
Send trim or discard instructions to flash storage devices
Synopsis:
#include <sys/dcmd_cam.h>
#define DCMD_CAM_DATA_SET_MGNT __DIOT(_DCMD_CAM, 26, struct _data_set_mgnt)
Arguments to devctl():
Argument | Value |
---|---|
filedes | A file descriptor obtained by opening the device. |
dcmd | DCMD_CAM_DATA_SET_MGNT |
dev_data_ptr | A pointer to a _data_set_mgnt structure followed
by one or more _data_set_mgnt_range structure entries.
|
n_bytes | Number of bytes represented by sizeof(struct _data_set_mgnt)
plus all _data_set_mgnt_range structure entries.
|
dev_info_ptr | NULL |
Description:
This command sends a non-secure TRIM or DISCARD request to a targeted flash storage device (e.g., NVME, UFS, eMMC). These operations tell the device that specific logical block address (LBA) ranges are no longer needed but may be reused at a later time.
Before using this command, determine the set of LBAs to trim. The devctl() function accepts a list of ranges within a single command.
When trimming blocks in a filesystem, use DCMD_FSYS_MAP_OFFSET to map the file's logical offset to its disk location; then send the request to the underlying device instead of the filesystem.
fs-qnx6
). Doing
so may result in data loss and filesystem corruption. The Power-Safe filesystem issues safe
TRIM/DISCARD operations internally.
Input:
One _data_set_mgnt
structure, followed by a list of _data_set_mgnt_range
structures. These structures define the LBA ranges to trim.
typedef struct _data_set_mgnt {
#define DSM_OPT_TRIM 1
#define DSM_OPT_DISCARD 2
_Uint32t opt;
_Uint32t nranges;
_Uint32t rsvd[4];
/* DATA_SET_MGNT_RANGE ranges[ ]; variable length ranges */
} DATA_SET_MGNT;
typedef struct _data_set_mgnt_range {
_Uint64t lba;
_Uint32t nlba;
_Uint32t rsvd;
} DATA_SET_MGNT_RANGE;
The input members for _data_set_mgnt
include:
- opt
- The type of operation (TRIM or DISCARD).
- nranges
- The number of
_data_set_mgnt_range
entries. This must match the number of_data_set_mgnt_range
structures that follow the_data_set_mgnt
header. To ensure compatibility across different servers, each devctl() call should include no more than 128 ranges. - rsvd
- Reserved. Set this field to zero.
The input members for _data_set_mgnt_range
include:
- lba
- Logical block address.
- nlba
- The number of logical blocks to process.
- rsvd
- Reserved. Set this field to zero.
Output:
None.
Returns:
- EOK
- Success.
- ENOTTY
- Unknown command.
- ENXIO
- One or more ranges are beyond the end of the device.
- ENOTBLK
- The filedes argument doesn't point to a block device.
- ENODEV
- The device doesn't support TRIM or DISCARD operations.
Example:
#include <sys/stat.h>
#include <devctl.h>
#include <sys/dcmd_cam.h>
struct trim_data {
DATA_SET_MGNT header;
DATA_SET_MGNT_RANGE ranges[8]; /* space for up to 8 ranges in one devctl() call */
};
int trim_blks (int fd) {
struct stat sbuf;
struct trim_data trim_cmd;
memset(&trim_cmd, 0, sizeof(trim_cmd));
/* Trim the first 100 disk blocks and the last 100 disk blks */
trim_cmd.ranges[0].lba = 0;
trim_cmd.ranges[0].nlba = 100;
/* Determine the start of the last 100 blocks */
trim_cmd.ranges[1].lba = start_of_last_100;
trim_cmd.ranges[1].nlba = 100;
trim_cmd.header.opt = DSM_OPT_TRIM;
trim_cmd.header.nranges = 2;
size_t command_size = sizeof(trim_cmd.header) + (sizeof(trim_cmd.ranges[0]) * trim_cmd.header.nranges);
int error = devctl(fd, DCMD_DATA_SET_MGNT, &trim_cmd, command_size, NULL);
}
See also:
devctl() in the QNX OS C Library Reference