bdev: add write_zeroes function

Add functionality to the bdev layer to handle the nvme write_zeroes
function.

Change-Id: I0dadad273b28c16db5a2275f7d8d57e98253a8d3
Signed-off-by: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/372171
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Seth Howell 2017-08-01 11:28:29 -07:00 committed by Daniel Verkamp
parent 0720ad357b
commit 670dc20f63
4 changed files with 64 additions and 0 deletions

View File

@ -6,10 +6,16 @@ An [fio](http://github.com/axboe/fio) plugin was added that can route
I/O to the bdev layer. See the [plugin documentation](https://github.com/spdk/spdk/blob/master/examples/bdev/fio_plugin/README.md) I/O to the bdev layer. See the [plugin documentation](https://github.com/spdk/spdk/blob/master/examples/bdev/fio_plugin/README.md)
for more information. for more information.
### Block Device Abstraction Layer (bdev)
spdk_bdev_unmap() was modified to take an offset and a length in bytes as spdk_bdev_unmap() was modified to take an offset and a length in bytes as
arguments instead of requiring the user to provide an array of SCSI arguments instead of requiring the user to provide an array of SCSI
unmap descriptors. This limits unmaps to a single contiguous range. unmap descriptors. This limits unmaps to a single contiguous range.
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
currently only supported by NVMe block devices.
### 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.

View File

@ -88,6 +88,7 @@ enum spdk_bdev_io_type {
SPDK_BDEV_IO_TYPE_RESET, SPDK_BDEV_IO_TYPE_RESET,
SPDK_BDEV_IO_TYPE_NVME_ADMIN, SPDK_BDEV_IO_TYPE_NVME_ADMIN,
SPDK_BDEV_IO_TYPE_NVME_IO, SPDK_BDEV_IO_TYPE_NVME_IO,
SPDK_BDEV_IO_TYPE_WRITE_ZEROES,
}; };
/** /**
@ -329,6 +330,25 @@ 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 zeroes request to the bdev on the given channel. This command
* ensures that all bytes in the specified range are set to 00h
*
* \param bdev Block device
* \param ch I/O channel. Obtained by calling spdk_bdev_get_io_channel().
* \param offset The offset, in bytes, from the start of the block device.
* \param nbytes The number of bytes 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(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
uint64_t offset, uint64_t len,
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

View File

@ -928,6 +928,42 @@ spdk_bdev_writev(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
return 0; return 0;
} }
int
spdk_bdev_write_zeroes(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
uint64_t offset, uint64_t len,
spdk_bdev_io_completion_cb cb, void *cb_arg)
{
int rc;
struct spdk_bdev *bdev = desc->bdev;
struct spdk_bdev_io *bdev_io;
struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
if (!spdk_bdev_io_valid(bdev, offset, len)) {
return -EINVAL;
}
bdev_io = spdk_bdev_get_io();
if (!bdev_io) {
SPDK_ERRLOG("bdev_io memory allocation failed duing write_zeroes\n");
return -ENOMEM;
}
bdev_io->ch = channel;
bdev_io->u.write.len = len;
bdev_io->u.write.offset = offset;
bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE_ZEROES;
spdk_bdev_io_init(bdev_io, bdev, cb_arg, cb);
rc = spdk_bdev_io_submit(bdev_io);
if (rc < 0) {
spdk_bdev_put_io(bdev_io);
return rc;
}
return 0;
}
int 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,

View File

@ -82,6 +82,8 @@ spdk_rpc_get_bdevs(struct spdk_jsonrpc_request *request,
spdk_json_write_bool(w, spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE)); spdk_json_write_bool(w, spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE));
spdk_json_write_name(w, "unmap"); spdk_json_write_name(w, "unmap");
spdk_json_write_bool(w, spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)); spdk_json_write_bool(w, spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP));
spdk_json_write_name(w, "write_zeroes");
spdk_json_write_bool(w, spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_WRITE_ZEROES));
spdk_json_write_name(w, "flush"); spdk_json_write_name(w, "flush");
spdk_json_write_bool(w, spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_FLUSH)); spdk_json_write_bool(w, spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_FLUSH));
spdk_json_write_name(w, "reset"); spdk_json_write_name(w, "reset");