bdev: introduce APIs with block units
Add new versions of all of the I/O calls that take parameters in blocks instead of bytes. These are intended to replace the old APIs, but we'll keep them for now to preserve compatibility. Change-Id: I85ab665c653e8c697016c628837d49aa0c3bfcd0 Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-on: https://review.gerrithub.io/376255 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: John Kariuki <John.K.Kariuki@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
This commit is contained in:
parent
7394f69054
commit
e83f976743
@ -16,6 +16,13 @@ spdk_bdev_write_zeroes() was introduced as an alternative to spdk_bdev_unmap().
|
|||||||
It ensures that all unmapped blocks will be zeroed out. This function is
|
It ensures that all unmapped blocks will be zeroed out. This function is
|
||||||
currently only supported by NVMe block devices.
|
currently only supported by NVMe block devices.
|
||||||
|
|
||||||
|
New API functions that accept I/O parameters in units of blocks instead of bytes
|
||||||
|
have been added:
|
||||||
|
- spdk_bdev_read_blocks(), spdk_bdev_readv_blocks()
|
||||||
|
- spdk_bdev_write_blocks(), spdk_bdev_writev_blocks()
|
||||||
|
- spdk_bdev_write_zeroes_blocks()
|
||||||
|
- spdk_bdev_unmap_blocks()
|
||||||
|
|
||||||
### Linux AIO bdev
|
### Linux AIO bdev
|
||||||
|
|
||||||
The AIO bdev now allows the user to override the auto-detected block size.
|
The AIO bdev now allows the user to override the auto-detected block size.
|
||||||
|
@ -270,6 +270,25 @@ int spdk_bdev_read(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
void *buf, uint64_t offset, uint64_t nbytes,
|
void *buf, uint64_t offset, uint64_t nbytes,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a read request to the bdev on the given channel.
|
||||||
|
*
|
||||||
|
* \param desc Block device descriptor
|
||||||
|
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
|
||||||
|
* \param buf Data buffer to read into.
|
||||||
|
* \param offset_blocks The offset, in blocks, from the start of the block device.
|
||||||
|
* \param num_blocks The number of blocks to read.
|
||||||
|
* \param cb Called when the request is complete.
|
||||||
|
* \param cb_arg Argument passed to cb.
|
||||||
|
*
|
||||||
|
* \return 0 on success. On success, the callback will always
|
||||||
|
* be called (even if the request ultimately failed). Return
|
||||||
|
* negated errno on failure, in which case the callback will not be called.
|
||||||
|
*/
|
||||||
|
int spdk_bdev_read_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
void *buf, uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit a read request to the bdev on the given channel. This differs from
|
* Submit a read request to the bdev on the given channel. This differs from
|
||||||
* spdk_bdev_read by allowing the data buffer to be described in a scatter
|
* spdk_bdev_read by allowing the data buffer to be described in a scatter
|
||||||
@ -295,6 +314,31 @@ int spdk_bdev_readv(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
uint64_t offset, uint64_t nbytes,
|
uint64_t offset, uint64_t nbytes,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a read request to the bdev on the given channel. This differs from
|
||||||
|
* spdk_bdev_read by allowing the data buffer to be described in a scatter
|
||||||
|
* gather list. Some physical devices place memory alignment requirements on
|
||||||
|
* data and may not be able to directly transfer into the buffers provided. In
|
||||||
|
* this case, the request may fail.
|
||||||
|
*
|
||||||
|
* \param desc Block device descriptor
|
||||||
|
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
|
||||||
|
* \param iov A scatter gather list of buffers to be read into.
|
||||||
|
* \param iovcnt The number of elements in iov.
|
||||||
|
* \param offset_blocks The offset, in blocks, from the start of the block device.
|
||||||
|
* \param num_blocks The number of blocks to read.
|
||||||
|
* \param cb Called when the request is complete.
|
||||||
|
* \param cb_arg Argument passed to cb.
|
||||||
|
*
|
||||||
|
* \return 0 on success. On success, the callback will always
|
||||||
|
* be called (even if the request ultimately failed). Return
|
||||||
|
* negated errno on failure, in which case the callback will not be called.
|
||||||
|
*/
|
||||||
|
int spdk_bdev_readv_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
struct iovec *iov, int iovcnt,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit a write request to the bdev on the given channel.
|
* Submit a write request to the bdev on the given channel.
|
||||||
*
|
*
|
||||||
@ -314,6 +358,25 @@ int spdk_bdev_write(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
void *buf, uint64_t offset, uint64_t nbytes,
|
void *buf, uint64_t offset, uint64_t nbytes,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a write request to the bdev on the given channel.
|
||||||
|
*
|
||||||
|
* \param desc Block device descriptor
|
||||||
|
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
|
||||||
|
* \param buf Data buffer to written from.
|
||||||
|
* \param offset_blocks The offset, in blocks, from the start of the block device.
|
||||||
|
* \param num_blocks The number of blocks to write. buf must be greater than or equal to this size.
|
||||||
|
* \param cb Called when the request is complete.
|
||||||
|
* \param cb_arg Argument passed to cb.
|
||||||
|
*
|
||||||
|
* \return 0 on success. On success, the callback will always
|
||||||
|
* be called (even if the request ultimately failed). Return
|
||||||
|
* negated errno on failure, in which case the callback will not be called.
|
||||||
|
*/
|
||||||
|
int spdk_bdev_write_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
void *buf, uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit a write request to the bdev on the given channel. This differs from
|
* Submit a write request to the bdev on the given channel. This differs from
|
||||||
* spdk_bdev_write by allowing the data buffer to be described in a scatter
|
* spdk_bdev_write by allowing the data buffer to be described in a scatter
|
||||||
@ -339,6 +402,31 @@ int spdk_bdev_writev(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
uint64_t offset, uint64_t len,
|
uint64_t offset, uint64_t len,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a write request to the bdev on the given channel. This differs from
|
||||||
|
* spdk_bdev_write by allowing the data buffer to be described in a scatter
|
||||||
|
* gather list. Some physical devices place memory alignment requirements on
|
||||||
|
* data and may not be able to directly transfer out of the buffers provided. In
|
||||||
|
* this case, the request may fail.
|
||||||
|
*
|
||||||
|
* \param desc Block device descriptor
|
||||||
|
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
|
||||||
|
* \param iov A scatter gather list of buffers to be written from.
|
||||||
|
* \param iovcnt The number of elements in iov.
|
||||||
|
* \param offset_blocks The offset, in blocks, from the start of the block device.
|
||||||
|
* \param num_blocks The number of blocks to write. buf must be greater than or equal to this size.
|
||||||
|
* \param cb Called when the request is complete.
|
||||||
|
* \param cb_arg Argument passed to cb.
|
||||||
|
*
|
||||||
|
* \return 0 on success. On success, the callback will always
|
||||||
|
* be called (even if the request ultimately failed). Return
|
||||||
|
* negated errno on failure, in which case the callback will not be called.
|
||||||
|
*/
|
||||||
|
int spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
struct iovec *iov, int iovcnt,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit a write zeroes request to the bdev on the given channel. This command
|
* Submit a write zeroes request to the bdev on the given channel. This command
|
||||||
* ensures that all bytes in the specified range are set to 00h
|
* ensures that all bytes in the specified range are set to 00h
|
||||||
@ -358,6 +446,25 @@ int spdk_bdev_write_zeroes(struct spdk_bdev_desc *desc, struct spdk_io_channel *
|
|||||||
uint64_t offset, uint64_t len,
|
uint64_t offset, uint64_t len,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a write zeroes request to the bdev on the given channel. This command
|
||||||
|
* ensures that all bytes in the specified range are set to 00h
|
||||||
|
*
|
||||||
|
* \param desc Block device descriptor
|
||||||
|
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
|
||||||
|
* \param offset_blocks The offset, in blocks, from the start of the block device.
|
||||||
|
* \param num_blocks The number of blocks to zero.
|
||||||
|
* \param cb Called when the request is complete.
|
||||||
|
* \param cb_arg Argument passed to cb.
|
||||||
|
*
|
||||||
|
* \return 0 on success. On success, the callback will always
|
||||||
|
* be called (even if the request ultimately failed). Return
|
||||||
|
* negated errno on failure, in which case the callback will not be called.
|
||||||
|
*/
|
||||||
|
int spdk_bdev_write_zeroes_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit an unmap request to the block device. Unmap is sometimes also called trim or
|
* Submit an unmap request to the block device. Unmap is sometimes also called trim or
|
||||||
* deallocate. This notifies the device that the data in the blocks described is no
|
* deallocate. This notifies the device that the data in the blocks described is no
|
||||||
@ -378,6 +485,26 @@ int spdk_bdev_unmap(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
uint64_t offset, uint64_t nbytes,
|
uint64_t offset, uint64_t nbytes,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit an unmap request to the block device. Unmap is sometimes also called trim or
|
||||||
|
* deallocate. This notifies the device that the data in the blocks described is no
|
||||||
|
* longer valid. Reading blocks that have been unmapped results in indeterminate data.
|
||||||
|
*
|
||||||
|
* \param desc Block device descriptor
|
||||||
|
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
|
||||||
|
* \param offset_blocks The offset, in blocks, from the start of the block device.
|
||||||
|
* \param num_blocks The number of blocks to unmap.
|
||||||
|
* \param cb Called when the request is complete.
|
||||||
|
* \param cb_arg Argument passed to cb.
|
||||||
|
*
|
||||||
|
* \return 0 on success. On success, the callback will always
|
||||||
|
* be called (even if the request ultimately failed). Return
|
||||||
|
* negated errno on failure, in which case the callback will not be called.
|
||||||
|
*/
|
||||||
|
int spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit a flush request to the bdev on the given channel. For devices with volatile
|
* Submit a flush request to the bdev on the given channel. For devices with volatile
|
||||||
* caches, data is not guaranteed to be persistent until the completion of a flush
|
* caches, data is not guaranteed to be persistent until the completion of a flush
|
||||||
@ -398,6 +525,26 @@ int spdk_bdev_flush(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
uint64_t offset, uint64_t length,
|
uint64_t offset, uint64_t length,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit a flush request to the bdev on the given channel. For devices with volatile
|
||||||
|
* caches, data is not guaranteed to be persistent until the completion of a flush
|
||||||
|
* request. Call spdk_bdev_has_write_cache() to check if the bdev has a volatile cache.
|
||||||
|
*
|
||||||
|
* \param desc Block device descriptor
|
||||||
|
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
|
||||||
|
* \param offset_blocks The offset, in blocks, from the start of the block device.
|
||||||
|
* \param num_blocks The number of blocks.
|
||||||
|
* \param cb Called when the request is complete.
|
||||||
|
* \param cb_arg Argument passed to cb.
|
||||||
|
*
|
||||||
|
* \return 0 on success. On success, the callback will always
|
||||||
|
* be called (even if the request ultimately failed). Return
|
||||||
|
* negated errno on failure, in which case the callback will not be called.
|
||||||
|
*/
|
||||||
|
int spdk_bdev_flush_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit a reset request to the bdev on the given channel.
|
* Submit a reset request to the bdev on the given channel.
|
||||||
*
|
*
|
||||||
|
184
lib/bdev/bdev.c
184
lib/bdev/bdev.c
@ -780,27 +780,34 @@ spdk_bdev_has_write_cache(const struct spdk_bdev *bdev)
|
|||||||
return bdev->write_cache;
|
return bdev->write_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
/*
|
||||||
spdk_bdev_io_valid(struct spdk_bdev *bdev, uint64_t offset, uint64_t nbytes)
|
* Convert I/O offset and length from bytes to blocks.
|
||||||
|
*
|
||||||
|
* Returns zero on success or non-zero if the byte parameters aren't divisible by the block size.
|
||||||
|
*/
|
||||||
|
static uint64_t
|
||||||
|
spdk_bdev_bytes_to_blocks(struct spdk_bdev *bdev, uint64_t offset_bytes, uint64_t *offset_blocks,
|
||||||
|
uint64_t num_bytes, uint64_t *num_blocks)
|
||||||
{
|
{
|
||||||
/* Return failure if offset is not a multiple of bdev->blocklen */
|
uint32_t block_size = bdev->blocklen;
|
||||||
if (offset % bdev->blocklen) {
|
|
||||||
return false;
|
*offset_blocks = offset_bytes / block_size;
|
||||||
|
*num_blocks = num_bytes / block_size;
|
||||||
|
|
||||||
|
return (offset_bytes % block_size) | (num_bytes % block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return failure if nbytes is not a multiple of bdev->blocklen */
|
static bool
|
||||||
if (nbytes % bdev->blocklen) {
|
spdk_bdev_io_valid_blocks(struct spdk_bdev *bdev, uint64_t offset_blocks, uint64_t num_blocks)
|
||||||
return false;
|
{
|
||||||
}
|
/* Return failure if offset_blocks + num_blocks is less than offset_blocks; indicates there
|
||||||
|
|
||||||
/* Return failure if offset + nbytes is less than offset; indicates there
|
|
||||||
* has been an overflow and hence the offset has been wrapped around */
|
* has been an overflow and hence the offset has been wrapped around */
|
||||||
if (offset + nbytes < offset) {
|
if (offset_blocks + num_blocks < offset_blocks) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return failure if offset + nbytes exceeds the size of the bdev */
|
/* Return failure if offset_blocks + num_blocks exceeds the size of the bdev */
|
||||||
if (offset + nbytes > bdev->blockcnt * bdev->blocklen) {
|
if (offset_blocks + num_blocks > bdev->blockcnt) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,13 +818,27 @@ int
|
|||||||
spdk_bdev_read(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
spdk_bdev_read(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
void *buf, uint64_t offset, uint64_t nbytes,
|
void *buf, uint64_t offset, uint64_t nbytes,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
uint64_t offset_blocks, num_blocks;
|
||||||
|
|
||||||
|
if (spdk_bdev_bytes_to_blocks(desc->bdev, offset, &offset_blocks, nbytes, &num_blocks) != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spdk_bdev_read_blocks(desc, ch, buf, offset_blocks, num_blocks, cb, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_bdev_read_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
void *buf, uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
struct spdk_bdev *bdev = desc->bdev;
|
struct spdk_bdev *bdev = desc->bdev;
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!spdk_bdev_io_valid(bdev, offset, nbytes)) {
|
if (!spdk_bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -830,11 +851,11 @@ spdk_bdev_read(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
bdev_io->ch = channel;
|
bdev_io->ch = channel;
|
||||||
bdev_io->type = SPDK_BDEV_IO_TYPE_READ;
|
bdev_io->type = SPDK_BDEV_IO_TYPE_READ;
|
||||||
bdev_io->u.read.iov.iov_base = buf;
|
bdev_io->u.read.iov.iov_base = buf;
|
||||||
bdev_io->u.read.iov.iov_len = nbytes;
|
bdev_io->u.read.iov.iov_len = num_blocks * bdev->blocklen;
|
||||||
bdev_io->u.read.iovs = &bdev_io->u.read.iov;
|
bdev_io->u.read.iovs = &bdev_io->u.read.iov;
|
||||||
bdev_io->u.read.iovcnt = 1;
|
bdev_io->u.read.iovcnt = 1;
|
||||||
bdev_io->u.read.num_blocks = nbytes / bdev->blocklen;
|
bdev_io->u.read.num_blocks = num_blocks;
|
||||||
bdev_io->u.read.offset_blocks = offset / bdev->blocklen;
|
bdev_io->u.read.offset_blocks = offset_blocks;
|
||||||
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
||||||
|
|
||||||
rc = spdk_bdev_io_submit(bdev_io);
|
rc = spdk_bdev_io_submit(bdev_io);
|
||||||
@ -851,13 +872,27 @@ spdk_bdev_readv(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
struct iovec *iov, int iovcnt,
|
struct iovec *iov, int iovcnt,
|
||||||
uint64_t offset, uint64_t nbytes,
|
uint64_t offset, uint64_t nbytes,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
uint64_t offset_blocks, num_blocks;
|
||||||
|
|
||||||
|
if (spdk_bdev_bytes_to_blocks(desc->bdev, offset, &offset_blocks, nbytes, &num_blocks) != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spdk_bdev_readv_blocks(desc, ch, iov, iovcnt, offset_blocks, num_blocks, cb, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int spdk_bdev_readv_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
struct iovec *iov, int iovcnt,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
struct spdk_bdev *bdev = desc->bdev;
|
struct spdk_bdev *bdev = desc->bdev;
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!spdk_bdev_io_valid(bdev, offset, nbytes)) {
|
if (!spdk_bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,8 +906,8 @@ spdk_bdev_readv(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
bdev_io->type = SPDK_BDEV_IO_TYPE_READ;
|
bdev_io->type = SPDK_BDEV_IO_TYPE_READ;
|
||||||
bdev_io->u.read.iovs = iov;
|
bdev_io->u.read.iovs = iov;
|
||||||
bdev_io->u.read.iovcnt = iovcnt;
|
bdev_io->u.read.iovcnt = iovcnt;
|
||||||
bdev_io->u.read.num_blocks = nbytes / bdev->blocklen;
|
bdev_io->u.read.num_blocks = num_blocks;
|
||||||
bdev_io->u.read.offset_blocks = offset / bdev->blocklen;
|
bdev_io->u.read.offset_blocks = offset_blocks;
|
||||||
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
||||||
|
|
||||||
rc = spdk_bdev_io_submit(bdev_io);
|
rc = spdk_bdev_io_submit(bdev_io);
|
||||||
@ -888,6 +923,20 @@ int
|
|||||||
spdk_bdev_write(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
spdk_bdev_write(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
void *buf, uint64_t offset, uint64_t nbytes,
|
void *buf, uint64_t offset, uint64_t nbytes,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
uint64_t offset_blocks, num_blocks;
|
||||||
|
|
||||||
|
if (spdk_bdev_bytes_to_blocks(desc->bdev, offset, &offset_blocks, nbytes, &num_blocks) != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spdk_bdev_write_blocks(desc, ch, buf, offset_blocks, num_blocks, cb, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_bdev_write_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
void *buf, uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
struct spdk_bdev *bdev = desc->bdev;
|
struct spdk_bdev *bdev = desc->bdev;
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
@ -898,7 +947,7 @@ spdk_bdev_write(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spdk_bdev_io_valid(bdev, offset, nbytes)) {
|
if (!spdk_bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,11 +960,11 @@ spdk_bdev_write(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
bdev_io->ch = channel;
|
bdev_io->ch = channel;
|
||||||
bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE;
|
bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE;
|
||||||
bdev_io->u.write.iov.iov_base = buf;
|
bdev_io->u.write.iov.iov_base = buf;
|
||||||
bdev_io->u.write.iov.iov_len = nbytes;
|
bdev_io->u.write.iov.iov_len = num_blocks * bdev->blocklen;
|
||||||
bdev_io->u.write.iovs = &bdev_io->u.write.iov;
|
bdev_io->u.write.iovs = &bdev_io->u.write.iov;
|
||||||
bdev_io->u.write.iovcnt = 1;
|
bdev_io->u.write.iovcnt = 1;
|
||||||
bdev_io->u.write.num_blocks = nbytes / bdev->blocklen;
|
bdev_io->u.write.num_blocks = num_blocks;
|
||||||
bdev_io->u.write.offset_blocks = offset / bdev->blocklen;
|
bdev_io->u.write.offset_blocks = offset_blocks;
|
||||||
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
||||||
|
|
||||||
rc = spdk_bdev_io_submit(bdev_io);
|
rc = spdk_bdev_io_submit(bdev_io);
|
||||||
@ -932,6 +981,21 @@ spdk_bdev_writev(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
struct iovec *iov, int iovcnt,
|
struct iovec *iov, int iovcnt,
|
||||||
uint64_t offset, uint64_t len,
|
uint64_t offset, uint64_t len,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
uint64_t offset_blocks, num_blocks;
|
||||||
|
|
||||||
|
if (spdk_bdev_bytes_to_blocks(desc->bdev, offset, &offset_blocks, len, &num_blocks) != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spdk_bdev_writev_blocks(desc, ch, iov, iovcnt, offset_blocks, num_blocks, cb, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
struct iovec *iov, int iovcnt,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
struct spdk_bdev *bdev = desc->bdev;
|
struct spdk_bdev *bdev = desc->bdev;
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
@ -942,7 +1006,7 @@ spdk_bdev_writev(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spdk_bdev_io_valid(bdev, offset, len)) {
|
if (!spdk_bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -956,8 +1020,8 @@ spdk_bdev_writev(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE;
|
bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE;
|
||||||
bdev_io->u.write.iovs = iov;
|
bdev_io->u.write.iovs = iov;
|
||||||
bdev_io->u.write.iovcnt = iovcnt;
|
bdev_io->u.write.iovcnt = iovcnt;
|
||||||
bdev_io->u.write.num_blocks = len / bdev->blocklen;
|
bdev_io->u.write.num_blocks = num_blocks;
|
||||||
bdev_io->u.write.offset_blocks = offset / bdev->blocklen;
|
bdev_io->u.write.offset_blocks = offset_blocks;
|
||||||
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
||||||
|
|
||||||
rc = spdk_bdev_io_submit(bdev_io);
|
rc = spdk_bdev_io_submit(bdev_io);
|
||||||
@ -973,13 +1037,27 @@ int
|
|||||||
spdk_bdev_write_zeroes(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
spdk_bdev_write_zeroes(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
uint64_t offset, uint64_t len,
|
uint64_t offset, uint64_t len,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
uint64_t offset_blocks, num_blocks;
|
||||||
|
|
||||||
|
if (spdk_bdev_bytes_to_blocks(desc->bdev, offset, &offset_blocks, len, &num_blocks) != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spdk_bdev_write_zeroes_blocks(desc, ch, offset_blocks, num_blocks, cb, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_bdev_write_zeroes_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct spdk_bdev *bdev = desc->bdev;
|
struct spdk_bdev *bdev = desc->bdev;
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
|
||||||
|
|
||||||
if (!spdk_bdev_io_valid(bdev, offset, len)) {
|
if (!spdk_bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -990,8 +1068,8 @@ spdk_bdev_write_zeroes(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bdev_io->ch = channel;
|
bdev_io->ch = channel;
|
||||||
bdev_io->u.write.num_blocks = len / bdev->blocklen;
|
bdev_io->u.write.num_blocks = num_blocks;
|
||||||
bdev_io->u.write.offset_blocks = offset / bdev->blocklen;
|
bdev_io->u.write.offset_blocks = offset_blocks;
|
||||||
bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE_ZEROES;
|
bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE_ZEROES;
|
||||||
|
|
||||||
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
||||||
@ -1009,6 +1087,20 @@ int
|
|||||||
spdk_bdev_unmap(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
spdk_bdev_unmap(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
uint64_t offset, uint64_t nbytes,
|
uint64_t offset, uint64_t nbytes,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
uint64_t offset_blocks, num_blocks;
|
||||||
|
|
||||||
|
if (spdk_bdev_bytes_to_blocks(desc->bdev, offset, &offset_blocks, nbytes, &num_blocks) != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spdk_bdev_unmap_blocks(desc, ch, offset_blocks, num_blocks, cb, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
struct spdk_bdev *bdev = desc->bdev;
|
struct spdk_bdev *bdev = desc->bdev;
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
@ -1019,11 +1111,11 @@ spdk_bdev_unmap(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spdk_bdev_io_valid(bdev, offset, nbytes)) {
|
if (!spdk_bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes == 0) {
|
if (num_blocks == 0) {
|
||||||
SPDK_ERRLOG("Can't unmap 0 bytes\n");
|
SPDK_ERRLOG("Can't unmap 0 bytes\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1036,8 +1128,8 @@ spdk_bdev_unmap(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
|
|
||||||
bdev_io->ch = channel;
|
bdev_io->ch = channel;
|
||||||
bdev_io->type = SPDK_BDEV_IO_TYPE_UNMAP;
|
bdev_io->type = SPDK_BDEV_IO_TYPE_UNMAP;
|
||||||
bdev_io->u.unmap.offset_blocks = offset / bdev->blocklen;
|
bdev_io->u.unmap.offset_blocks = offset_blocks;
|
||||||
bdev_io->u.unmap.num_blocks = nbytes / bdev->blocklen;
|
bdev_io->u.unmap.num_blocks = num_blocks;
|
||||||
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
||||||
|
|
||||||
rc = spdk_bdev_io_submit(bdev_io);
|
rc = spdk_bdev_io_submit(bdev_io);
|
||||||
@ -1053,6 +1145,20 @@ int
|
|||||||
spdk_bdev_flush(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
spdk_bdev_flush(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
uint64_t offset, uint64_t length,
|
uint64_t offset, uint64_t length,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
uint64_t offset_blocks, num_blocks;
|
||||||
|
|
||||||
|
if (spdk_bdev_bytes_to_blocks(desc->bdev, offset, &offset_blocks, length, &num_blocks) != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spdk_bdev_flush_blocks(desc, ch, offset_blocks, num_blocks, cb, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_bdev_flush_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
||||||
|
uint64_t offset_blocks, uint64_t num_blocks,
|
||||||
|
spdk_bdev_io_completion_cb cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
struct spdk_bdev *bdev = desc->bdev;
|
struct spdk_bdev *bdev = desc->bdev;
|
||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
@ -1063,6 +1169,10 @@ spdk_bdev_flush(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!spdk_bdev_io_valid_blocks(bdev, offset_blocks, num_blocks)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
bdev_io = spdk_bdev_get_io();
|
bdev_io = spdk_bdev_get_io();
|
||||||
if (!bdev_io) {
|
if (!bdev_io) {
|
||||||
SPDK_ERRLOG("bdev_io memory allocation failed duing flush\n");
|
SPDK_ERRLOG("bdev_io memory allocation failed duing flush\n");
|
||||||
@ -1071,8 +1181,8 @@ spdk_bdev_flush(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
|
|||||||
|
|
||||||
bdev_io->ch = channel;
|
bdev_io->ch = channel;
|
||||||
bdev_io->type = SPDK_BDEV_IO_TYPE_FLUSH;
|
bdev_io->type = SPDK_BDEV_IO_TYPE_FLUSH;
|
||||||
bdev_io->u.flush.offset_blocks = offset / bdev->blocklen;
|
bdev_io->u.flush.offset_blocks = offset_blocks;
|
||||||
bdev_io->u.flush.num_blocks = length / bdev->blocklen;
|
bdev_io->u.flush.num_blocks = num_blocks;
|
||||||
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
|
||||||
|
|
||||||
rc = spdk_bdev_io_submit(bdev_io);
|
rc = spdk_bdev_io_submit(bdev_io);
|
||||||
|
@ -302,6 +302,30 @@ open_write_test(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bytes_to_blocks_test(void)
|
||||||
|
{
|
||||||
|
struct spdk_bdev bdev;
|
||||||
|
uint64_t offset_blocks, num_blocks;
|
||||||
|
|
||||||
|
memset(&bdev, 0, sizeof(bdev));
|
||||||
|
|
||||||
|
bdev.blocklen = 512;
|
||||||
|
|
||||||
|
/* All parameters valid */
|
||||||
|
offset_blocks = 0;
|
||||||
|
num_blocks = 0;
|
||||||
|
CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 1024, &num_blocks) == 0);
|
||||||
|
CU_ASSERT(offset_blocks == 1);
|
||||||
|
CU_ASSERT(num_blocks == 2);
|
||||||
|
|
||||||
|
/* Offset not a block multiple */
|
||||||
|
CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 3, &offset_blocks, 512, &num_blocks) != 0);
|
||||||
|
|
||||||
|
/* Length not a block multiple */
|
||||||
|
CU_ASSERT(spdk_bdev_bytes_to_blocks(&bdev, 512, &offset_blocks, 3, &num_blocks) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
io_valid_test(void)
|
io_valid_test(void)
|
||||||
{
|
{
|
||||||
@ -313,25 +337,19 @@ io_valid_test(void)
|
|||||||
bdev.blockcnt = 100;
|
bdev.blockcnt = 100;
|
||||||
|
|
||||||
/* All parameters valid */
|
/* All parameters valid */
|
||||||
CU_ASSERT(spdk_bdev_io_valid(&bdev, 512, 1024) == true);
|
CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 1, 2) == true);
|
||||||
|
|
||||||
/* Offset not a block multiple */
|
|
||||||
CU_ASSERT(spdk_bdev_io_valid(&bdev, 3, 512) == false);
|
|
||||||
|
|
||||||
/* Length not a block multiple */
|
|
||||||
CU_ASSERT(spdk_bdev_io_valid(&bdev, 512, 3) == false);
|
|
||||||
|
|
||||||
/* Last valid block */
|
/* Last valid block */
|
||||||
CU_ASSERT(spdk_bdev_io_valid(&bdev, 50688, 512) == true);
|
CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 1) == true);
|
||||||
|
|
||||||
/* Offset past end of bdev */
|
/* Offset past end of bdev */
|
||||||
CU_ASSERT(spdk_bdev_io_valid(&bdev, 51200, 512) == false);
|
CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 100, 1) == false);
|
||||||
|
|
||||||
/* Offset + length past end of bdev */
|
/* Offset + length past end of bdev */
|
||||||
CU_ASSERT(spdk_bdev_io_valid(&bdev, 50688, 1024) == false);
|
CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 99, 2) == false);
|
||||||
|
|
||||||
/* Offset near end of uint64_t range (2^64 - 512) */
|
/* Offset near end of uint64_t range (2^64 - 1) */
|
||||||
CU_ASSERT(spdk_bdev_io_valid(&bdev, 18446744073709551104ULL, 512) == false);
|
CU_ASSERT(spdk_bdev_io_valid_blocks(&bdev, 18446744073709551615ULL, 1) == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -351,6 +369,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
CU_add_test(suite, "bytes_to_blocks_test", bytes_to_blocks_test) == NULL ||
|
||||||
CU_add_test(suite, "io_valid", io_valid_test) == NULL ||
|
CU_add_test(suite, "io_valid", io_valid_test) == NULL ||
|
||||||
CU_add_test(suite, "open_write", open_write_test) == NULL
|
CU_add_test(suite, "open_write", open_write_test) == NULL
|
||||||
) {
|
) {
|
||||||
|
Loading…
Reference in New Issue
Block a user