bdev/aio: implement read-only
Support Aio bdev 'readonly' option in RPC call. The read-only flag can be dumped from the bdev info. Any writes on a read-only aio bdev will be fail. Signed-off-by: Yuhua <yuhua@smartx.com> Change-Id: I939f72479f8953a3678a8df3083ecce0f96844fb Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14955 Reviewed-by: GangCao <gang.cao@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot
This commit is contained in:
parent
0954302091
commit
4c6a2e3daa
@ -55,6 +55,7 @@ struct file_disk {
|
||||
int fd;
|
||||
TAILQ_ENTRY(file_disk) link;
|
||||
bool block_size_override;
|
||||
bool readonly;
|
||||
};
|
||||
|
||||
/* For user space reaping of completions */
|
||||
@ -99,11 +100,12 @@ static int
|
||||
bdev_aio_open(struct file_disk *disk)
|
||||
{
|
||||
int fd;
|
||||
int io_flag = disk->readonly ? O_RDONLY : O_RDWR;
|
||||
|
||||
fd = open(disk->filename, O_RDWR | O_DIRECT);
|
||||
fd = open(disk->filename, io_flag | O_DIRECT);
|
||||
if (fd < 0) {
|
||||
/* Try without O_DIRECT for non-disk files */
|
||||
fd = open(disk->filename, O_RDWR);
|
||||
fd = open(disk->filename, io_flag);
|
||||
if (fd < 0) {
|
||||
SPDK_ERRLOG("open() failed (file:%s), errno %d: %s\n",
|
||||
disk->filename, errno, spdk_strerror(errno));
|
||||
@ -227,7 +229,6 @@ bdev_aio_destruct_cb(void *io_device)
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("bdev_aio_close() failed\n");
|
||||
}
|
||||
|
||||
aio_free_disk(fdisk);
|
||||
}
|
||||
|
||||
@ -474,15 +475,25 @@ bdev_aio_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
|
||||
static int
|
||||
_bdev_aio_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
|
||||
{
|
||||
struct file_disk *fdisk = (struct file_disk *)bdev_io->bdev->ctxt;
|
||||
|
||||
switch (bdev_io->type) {
|
||||
/* Read and write operations must be performed on buffers aligned to
|
||||
* bdev->required_alignment. If user specified unaligned buffers,
|
||||
* get the aligned buffer from the pool by calling spdk_bdev_io_get_buf. */
|
||||
case SPDK_BDEV_IO_TYPE_READ:
|
||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||
spdk_bdev_io_get_buf(bdev_io, bdev_aio_get_buf_cb,
|
||||
bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
|
||||
return 0;
|
||||
case SPDK_BDEV_IO_TYPE_WRITE:
|
||||
if (fdisk->readonly) {
|
||||
spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
||||
} else {
|
||||
spdk_bdev_io_get_buf(bdev_io, bdev_aio_get_buf_cb,
|
||||
bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case SPDK_BDEV_IO_TYPE_FLUSH:
|
||||
bdev_aio_flush((struct file_disk *)bdev_io->bdev->ctxt,
|
||||
(struct bdev_aio_task *)bdev_io->driver_ctx);
|
||||
@ -567,6 +578,10 @@ bdev_aio_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
|
||||
|
||||
spdk_json_write_named_string(w, "filename", fdisk->filename);
|
||||
|
||||
spdk_json_write_named_bool(w, "block_size_override", fdisk->block_size_override);
|
||||
|
||||
spdk_json_write_named_bool(w, "readonly", fdisk->readonly);
|
||||
|
||||
spdk_json_write_object_end(w);
|
||||
|
||||
return 0;
|
||||
@ -587,6 +602,7 @@ bdev_aio_write_json_config(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w
|
||||
spdk_json_write_named_uint32(w, "block_size", bdev->blocklen);
|
||||
}
|
||||
spdk_json_write_named_string(w, "filename", fdisk->filename);
|
||||
spdk_json_write_named_bool(w, "readonly", fdisk->readonly);
|
||||
spdk_json_write_object_end(w);
|
||||
|
||||
spdk_json_write_object_end(w);
|
||||
@ -685,7 +701,7 @@ bdev_aio_group_destroy_cb(void *io_device, void *ctx_buf)
|
||||
}
|
||||
|
||||
int
|
||||
create_aio_bdev(const char *name, const char *filename, uint32_t block_size)
|
||||
create_aio_bdev(const char *name, const char *filename, uint32_t block_size, bool readonly)
|
||||
{
|
||||
struct file_disk *fdisk;
|
||||
uint32_t detected_block_size;
|
||||
@ -697,6 +713,7 @@ create_aio_bdev(const char *name, const char *filename, uint32_t block_size)
|
||||
SPDK_ERRLOG("Unable to allocate enough memory for aio backend\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
fdisk->readonly = readonly;
|
||||
|
||||
fdisk->filename = strdup(filename);
|
||||
if (!fdisk->filename) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
typedef void (*delete_aio_bdev_complete)(void *cb_arg, int bdeverrno);
|
||||
|
||||
int create_aio_bdev(const char *name, const char *filename, uint32_t block_size);
|
||||
int create_aio_bdev(const char *name, const char *filename, uint32_t block_size, bool readonly);
|
||||
|
||||
int bdev_aio_rescan(const char *name);
|
||||
void bdev_aio_delete(const char *name, delete_aio_bdev_complete cb_fn, void *cb_arg);
|
||||
|
@ -13,6 +13,7 @@ struct rpc_construct_aio {
|
||||
char *name;
|
||||
char *filename;
|
||||
uint32_t block_size;
|
||||
bool readonly;
|
||||
};
|
||||
|
||||
struct rpc_construct_aio_ctx {
|
||||
@ -32,6 +33,7 @@ static const struct spdk_json_object_decoder rpc_construct_aio_decoders[] = {
|
||||
{"name", offsetof(struct rpc_construct_aio, name), spdk_json_decode_string},
|
||||
{"filename", offsetof(struct rpc_construct_aio, filename), spdk_json_decode_string},
|
||||
{"block_size", offsetof(struct rpc_construct_aio, block_size), spdk_json_decode_uint32, true},
|
||||
{"readonly", offsetof(struct rpc_construct_aio, readonly), spdk_json_decode_bool, true},
|
||||
};
|
||||
|
||||
static void
|
||||
@ -71,7 +73,7 @@ rpc_bdev_aio_create(struct spdk_jsonrpc_request *request,
|
||||
}
|
||||
|
||||
ctx->request = request;
|
||||
rc = create_aio_bdev(ctx->req.name, ctx->req.filename, ctx->req.block_size);
|
||||
rc = create_aio_bdev(ctx->req.name, ctx->req.filename, ctx->req.block_size, ctx->req.readonly);
|
||||
if (rc) {
|
||||
spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
|
||||
free_rpc_construct_aio(ctx);
|
||||
|
@ -370,13 +370,14 @@ def bdev_raid_delete(client, name):
|
||||
return client.call('bdev_raid_delete', params)
|
||||
|
||||
|
||||
def bdev_aio_create(client, filename, name, block_size=None):
|
||||
def bdev_aio_create(client, filename, name, block_size=None, readonly=False):
|
||||
"""Construct a Linux AIO block device.
|
||||
|
||||
Args:
|
||||
filename: path to device or file (ex: /dev/sda)
|
||||
name: name of block device
|
||||
block_size: block size of device (optional; autodetected if omitted)
|
||||
readonly: set aio bdev as read-only
|
||||
|
||||
Returns:
|
||||
Name of created block device.
|
||||
@ -387,6 +388,9 @@ def bdev_aio_create(client, filename, name, block_size=None):
|
||||
if block_size:
|
||||
params['block_size'] = block_size
|
||||
|
||||
if readonly:
|
||||
params['readonly'] = readonly
|
||||
|
||||
return client.call('bdev_aio_create', params)
|
||||
|
||||
|
||||
|
@ -424,12 +424,14 @@ if __name__ == "__main__":
|
||||
print_json(rpc.bdev.bdev_aio_create(args.client,
|
||||
filename=args.filename,
|
||||
name=args.name,
|
||||
block_size=args.block_size))
|
||||
block_size=args.block_size,
|
||||
readonly=args.readonly))
|
||||
|
||||
p = subparsers.add_parser('bdev_aio_create', help='Add a bdev with aio backend')
|
||||
p.add_argument('filename', help='Path to device or file (ex: /dev/sda)')
|
||||
p.add_argument('name', help='Block device name')
|
||||
p.add_argument('block_size', help='Block size for this bdev', type=int, nargs='?')
|
||||
p.add_argument("-r", "--readonly", action='store_true', help='Set this bdev as read-only')
|
||||
p.set_defaults(func=bdev_aio_create)
|
||||
|
||||
def bdev_aio_rescan(args):
|
||||
|
Loading…
Reference in New Issue
Block a user