Commit 4c6a2e3d authored by Yuhua's avatar Yuhua Committed by Tomasz Zawadzki
Browse files

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: default avatarYuhua <yuhua@smartx.com>
Change-Id: I939f72479f8953a3678a8df3083ecce0f96844fb
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14955


Reviewed-by: default avatarGangCao <gang.cao@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
parent 09543020
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -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:
		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) {
+1 −1
Original line number Diff line number Diff line
@@ -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);
+3 −1
Original line number Diff line number Diff line
@@ -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);
+5 −1
Original line number Diff line number Diff line
@@ -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)


+3 −1
Original line number Diff line number Diff line
@@ -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):