Skip to content

Commit

Permalink
wip: ublk zoned
Browse files Browse the repository at this point in the history
  • Loading branch information
metaspace committed Nov 16, 2022
1 parent d6dd72f commit bc93bbe
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 12 deletions.
21 changes: 21 additions & 0 deletions include/ublk_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#define UBLK_CMD_STOP_DEV 0x07
#define UBLK_CMD_SET_PARAMS 0x08
#define UBLK_CMD_GET_PARAMS 0x09
#define UBLK_CMD_REPORT_ZONES_FETCH 10
#define UBLK_CMD_REPORT_ZONES_COMMIT_FETCH 11

/*
* IO commands, issued by ublk server, and handled by ublk driver.
Expand Down Expand Up @@ -74,6 +76,11 @@
*/
#define UBLK_F_NEED_GET_DATA (1UL << 2)

/*
* Enable zoned device support
*/
#define UBLK_F_ZONED (1ULL << 3)

/* device state */
#define UBLK_S_DEV_DEAD 0
#define UBLK_S_DEV_LIVE 1
Expand Down Expand Up @@ -123,6 +130,12 @@ struct ublksrv_ctrl_dev_info {
#define UBLK_IO_OP_DISCARD 3
#define UBLK_IO_OP_WRITE_SAME 4
#define UBLK_IO_OP_WRITE_ZEROES 5
#define UBLK_IO_OP_ZONE_OPEN 10
#define UBLK_IO_OP_ZONE_CLOSE 11
#define UBLK_IO_OP_ZONE_FINISH 12
#define UBLK_IO_OP_ZONE_APPEND 13
#define UBLK_IO_OP_ZONE_RESET 15
/* TODO: Add reset_all command */

#define UBLK_IO_F_FAILFAST_DEV (1U << 8)
#define UBLK_IO_F_FAILFAST_TRANSPORT (1U << 9)
Expand Down Expand Up @@ -208,6 +221,12 @@ struct ublk_param_discard {
__u16 reserved0;
};

struct ublk_param_zoned {
__u64 max_open_zones;
__u64 max_active_zones;
__u64 max_append_size;
};

struct ublk_params {
/*
* Total length of parameters, userspace has to set 'len' for both
Expand All @@ -218,10 +237,12 @@ struct ublk_params {
__u32 len;
#define UBLK_PARAM_TYPE_BASIC (1 << 0)
#define UBLK_PARAM_TYPE_DISCARD (1 << 1)
#define UBLK_PARAM_TYPE_ZONED (1 << 2)
__u32 types; /* types of parameter included */

struct ublk_param_basic basic;
struct ublk_param_discard discard;
struct ublk_param_zoned zoned;
};

#endif
15 changes: 15 additions & 0 deletions include/ublksrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <sys/uio.h>
#include <sys/eventfd.h>
#include <linux/fs.h>
#include <linux/blkzoned.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
Expand Down Expand Up @@ -114,6 +115,7 @@ struct ublksrv_ctrl_dev {

cpu_set_t *queues_cpuset;

uint64_t zone_size_sectors;
unsigned long reserved[4];
};

Expand Down Expand Up @@ -294,6 +296,9 @@ struct ublksrv_tgt_type {

void *(*alloc_io_buf)(struct ublksrv_queue *q, int tag, int size);
void (*free_io_buf)(struct ublksrv_queue *q, void *buf, int tag);
void (*report_zone)(struct ublksrv_dev *dev,
uint64_t offset_sectors,
struct blk_zone *zone_info);

int type;
unsigned ublk_flags; //flags required for ublk driver
Expand Down Expand Up @@ -367,6 +372,16 @@ extern struct ublksrv_dev *ublksrv_dev_init(const struct ublksrv_ctrl_dev *
ctrl_dev);
extern void ublksrv_dev_deinit(struct ublksrv_dev *dev);

extern int ublksrv_ctrl_report_zones_commit_and_fetch(
const struct ublksrv_ctrl_dev *ctrl_dev,
struct io_uring *ring,
struct blk_zone *zone_info,
uint64_t *cqe_data);
extern int ublksrv_ctrl_report_zones_fetch(
const struct ublksrv_ctrl_dev *ctrl_dev,
struct io_uring *ring,
uint64_t *cqe_data);

/* target json has to include the following key/value */
#define UBLKSRV_TGT_NAME_MAX_LEN 32
struct ublksrv_tgt_base_json {
Expand Down
53 changes: 47 additions & 6 deletions lib/ublksrv_cmd.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT or LGPL-2.1-only

#include <config.h>
#include <stdint.h>
#include <linux/blkzoned.h>

#include "ublksrv_priv.h"

Expand Down Expand Up @@ -51,39 +53,51 @@ static inline void ublksrv_ctrl_init_cmd(struct ublksrv_ctrl_dev *dev,
dev->dev_info.dev_id, data->cmd_op, cmd);
}

static int __ublksrv_ctrl_cmd(struct ublksrv_ctrl_dev *dev,
struct ublksrv_ctrl_cmd_data *data)
static int __ublksrv_ctrl_cmd_with_ring(struct ublksrv_ctrl_dev *dev,
struct io_uring *ring, struct ublksrv_ctrl_cmd_data *data,
uint64_t *cqe_data)
{
struct io_uring_sqe *sqe;
struct io_uring_cqe *cqe;
int ret = -EINVAL;

sqe = io_uring_get_sqe(&dev->ring);
sqe = io_uring_get_sqe(ring);
if (!sqe) {
fprintf(stderr, "can't get sqe ret %d\n", ret);
return ret;
}

ublksrv_ctrl_init_cmd(dev, sqe, data);

ret = io_uring_submit(&dev->ring);
ret = io_uring_submit(ring);
if (ret < 0) {
fprintf(stderr, "uring submit ret %d\n", ret);
return ret;
}

ret = io_uring_wait_cqe(&dev->ring, &cqe);
ret = io_uring_wait_cqe(ring, &cqe);
if (ret < 0) {
fprintf(stderr, "wait cqe: %s\n", strerror(-ret));
return ret;
}
io_uring_cqe_seen(&dev->ring, cqe);

if (cqe_data) {
*cqe_data = cqe->big_cqe[0];
}

io_uring_cqe_seen(ring, cqe);

ublksrv_printf(stdout, "dev %d, ctrl cqe res %d, user_data %llx\n",
dev->dev_info.dev_id, cqe->res, cqe->user_data);
return cqe->res;
}

static int __ublksrv_ctrl_cmd(struct ublksrv_ctrl_dev *dev,
struct ublksrv_ctrl_cmd_data *data)
{
return __ublksrv_ctrl_cmd_with_ring(dev, &dev->ring, data, NULL);
}

void ublksrv_ctrl_deinit(struct ublksrv_ctrl_dev *dev)
{
close(dev->ring.ring_fd);
Expand Down Expand Up @@ -160,6 +174,33 @@ int ublksrv_ctrl_get_affinity(struct ublksrv_ctrl_dev *ctrl_dev)
return 0;
}

int ublksrv_ctrl_report_zones_fetch(const struct ublksrv_ctrl_dev *ctrl_dev,
struct io_uring *ring,
uint64_t *cqe_data) {

struct ublksrv_ctrl_cmd_data data = {
.cmd_op = UBLK_CMD_REPORT_ZONES_FETCH,
};

return __ublksrv_ctrl_cmd_with_ring(ctrl_dev, ring, &data, cqe_data);
}

int ublksrv_ctrl_report_zones_commit_and_fetch(
const struct ublksrv_ctrl_dev *ctrl_dev,
struct io_uring *ring,
struct blk_zone *zone_info,
uint64_t *cqe_data) {

struct ublksrv_ctrl_cmd_data data = {
.cmd_op = UBLK_CMD_REPORT_ZONES_COMMIT_FETCH,
.flags = CTRL_CMD_HAS_BUF,
.addr = (__u64)zone_info,
.len = sizeof(struct blk_zone),
};

return __ublksrv_ctrl_cmd_with_ring(ctrl_dev, ring, &data, cqe_data);
}

/*
* Start the ublksrv device:
*
Expand Down
8 changes: 7 additions & 1 deletion lib/ublksrv_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,14 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(struct ublk_param_discard,
max_write_zeroes_sectors,
max_discard_segments,
reserved0)

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(struct ublk_param_zoned,
max_open_zones,
max_active_zones,
max_append_size)

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(struct ublk_params,
len, types, basic, discard)
len, types, basic, discard, zoned)

int ublksrv_json_write_params(const struct ublk_params *p,
char *jbuf, int len)
Expand Down
104 changes: 104 additions & 0 deletions tgt_loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

#include <config.h>

#include <linux/blkzoned.h>
#include <poll.h>
#include <stdint.h>
#include <sys/epoll.h>
#include "ublksrv_aio.h"
#include "ublksrv_tgt.h"
Expand Down Expand Up @@ -37,6 +39,8 @@ static bool backing_supports_discard(char *name)
return false;
}

extern struct ublksrv_tgt_type loop_ctrl_tgt_type;

static int loop_init_tgt(struct ublksrv_dev *dev, int type, int argc, char
*argv[])
{
Expand Down Expand Up @@ -98,6 +102,30 @@ static int loop_init_tgt(struct ublksrv_dev *dev, int type, int argc, char
return -2;
}

if (dev->ctrl_dev->dev_info.flags & UBLK_F_ZONED) {
uint32_t zone_size;
if (ioctl(fd, BLKGETZONESZ, &zone_size)) {
syslog(LOG_ERR, "%s: BLKGETSONESZ ioctl failed for %s\n",
__func__, file);
return -1;
}

if (zone_size == 0) {
syslog(LOG_ERR, "%s: target %s is not zoned\n",
__func__, file);
return -1;
}

p.basic.chunk_sectors = zone_size;
p.types |= UBLK_PARAM_TYPE_ZONED;
/* TODO: lift these values from loop target */
p.zoned.max_open_zones = 14;
p.zoned.max_active_zones = 14;
// TODO: Dropping const qualifier
((struct ublksrv_ctrl_dev *)dev->ctrl_dev)->zone_size_sectors =
zone_size;
}

if (fstat(fd, &st) < 0)
return -2;

Expand Down Expand Up @@ -166,6 +194,10 @@ static int loop_init_tgt(struct ublksrv_dev *dev, int type, int argc, char
jbuf = ublksrv_tgt_realloc_json_buf(dev, &jbuf_size);
} while (ret < 0);

// TODO: Dropping const qualifier
((struct ublksrv_ctrl_dev *)dev->ctrl_dev)->tgt_ops =
&loop_ctrl_tgt_type;

return 0;
}

Expand Down Expand Up @@ -256,6 +288,37 @@ static co_io_job __loop_handle_io_async(struct ublksrv_queue *q,
struct io_uring_cqe *cqe;
int ret;

const struct ublksrv_io_desc *iod = ublksrv_get_iod(q, tag);
unsigned ublk_op = ublksrv_get_op(iod);
unsigned long ioctl_op = 0;

switch (ublk_op) {
case UBLK_IO_OP_ZONE_OPEN:
ioctl_op = BLKOPENZONE;
break;
case UBLK_IO_OP_ZONE_CLOSE:
ioctl_op = BLKCLOSEZONE;
break;
case UBLK_IO_OP_ZONE_FINISH:
ioctl_op = BLKFINISHZONE;
break;
case UBLK_IO_OP_ZONE_RESET:
ioctl_op = BLKRESETZONE;
break;
}

if (ioctl_op) {
struct blk_zone_range range = {
.sector = iod->start_sector,
.nr_sectors = q->dev->ctrl_dev->zone_size_sectors,
};

ret = ioctl(q->dev->tgt.fds[1], ioctl_op, &range);

ublksrv_complete_io(q, tag, ret);
co_return;
}

io->queued_tgt_io = 0;
again:
ret = loop_queue_tgt_io(q, io, tag);
Expand Down Expand Up @@ -310,6 +373,43 @@ static void loop_deinit_tgt(struct ublksrv_dev *dev)
free(dev->tgt.tgt_data);
}

static void loop_report_zone(struct ublksrv_dev *dev, uint64_t offset_sectors,
struct blk_zone *zone_info)
{
struct {
struct blk_zone_report report;
struct blk_zone zone;
} request = {
.report = {
.sector = offset_sectors,
.nr_zones = 1,
},
};

if (ioctl(dev->tgt.fds[1], BLKREPORTZONE, &request)) {
syslog(LOG_ERR, "%s: BLKREPORTZONE failed\n", __func__);
// TODO: Report error
return;
}

if (request.report.nr_zones == 0) {
/* Reporting zero length zone to indicate end */
memset(zone_info, 0, sizeof(*zone_info));
return;
}

if (request.report.nr_zones > 1) {
syslog(LOG_ERR,
"%s: BLKREPORTZONE reported wrong number of "
"zones: %d\n",
__func__, request.report.nr_zones);
// TODO: Report error
return;
}

memcpy(zone_info, &request.zone, sizeof(*zone_info));
}

struct ublksrv_tgt_type loop_tgt_type = {
.handle_io_async = loop_handle_io_async,
.tgt_io_done = loop_tgt_io_done,
Expand All @@ -320,6 +420,10 @@ struct ublksrv_tgt_type loop_tgt_type = {
.name = "loop",
};

struct ublksrv_tgt_type loop_ctrl_tgt_type = {
.report_zone = loop_report_zone,
};

static void tgt_loop_init() __attribute__((constructor));

static void tgt_loop_init(void)
Expand Down
Loading

0 comments on commit bc93bbe

Please sign in to comment.