Skip to content

Commit

Permalink
ublk: move zone report data out of request pdu
Browse files Browse the repository at this point in the history
[ Upstream commit 9327b51 ]

ublk zoned takes 16 bytes in each request pdu just for handling REPORT_ZONE
operation, this way does waste memory since request pdu is allocated
statically.

Store the transient zone report data into one global xarray, and remove
it after the report zone request is completed. This way is reasonable
since report zone is run in slow code path.

Fixes: 29802d7 ("ublk: enable zoned storage support")
Cc: Damien Le Moal <[email protected]>
Cc: Andreas Hindborg <[email protected]>
Signed-off-by: Ming Lei <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jens Axboe <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
Ming Lei authored and gregkh committed Oct 4, 2024
1 parent 0ceb2f2 commit 75a5e59
Showing 1 changed file with 46 additions and 16 deletions.
62 changes: 46 additions & 16 deletions drivers/block/ublk_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ struct ublk_rq_data {
struct llist_node node;

struct kref ref;
__u64 sector;
__u32 operation;
__u32 nr_zones;
};

struct ublk_uring_cmd_pdu {
Expand Down Expand Up @@ -215,6 +212,33 @@ static inline bool ublk_queue_is_zoned(struct ublk_queue *ubq)

#ifdef CONFIG_BLK_DEV_ZONED

struct ublk_zoned_report_desc {
__u64 sector;
__u32 operation;
__u32 nr_zones;
};

static DEFINE_XARRAY(ublk_zoned_report_descs);

static int ublk_zoned_insert_report_desc(const struct request *req,
struct ublk_zoned_report_desc *desc)
{
return xa_insert(&ublk_zoned_report_descs, (unsigned long)req,
desc, GFP_KERNEL);
}

static struct ublk_zoned_report_desc *ublk_zoned_erase_report_desc(
const struct request *req)
{
return xa_erase(&ublk_zoned_report_descs, (unsigned long)req);
}

static struct ublk_zoned_report_desc *ublk_zoned_get_report_desc(
const struct request *req)
{
return xa_load(&ublk_zoned_report_descs, (unsigned long)req);
}

static int ublk_get_nr_zones(const struct ublk_device *ub)
{
const struct ublk_param_basic *p = &ub->params.basic;
Expand Down Expand Up @@ -321,7 +345,7 @@ static int ublk_report_zones(struct gendisk *disk, sector_t sector,
unsigned int zones_in_request =
min_t(unsigned int, remaining_zones, max_zones_per_request);
struct request *req;
struct ublk_rq_data *pdu;
struct ublk_zoned_report_desc desc;
blk_status_t status;

memset(buffer, 0, buffer_length);
Expand All @@ -332,20 +356,23 @@ static int ublk_report_zones(struct gendisk *disk, sector_t sector,
goto out;
}

pdu = blk_mq_rq_to_pdu(req);
pdu->operation = UBLK_IO_OP_REPORT_ZONES;
pdu->sector = sector;
pdu->nr_zones = zones_in_request;
desc.operation = UBLK_IO_OP_REPORT_ZONES;
desc.sector = sector;
desc.nr_zones = zones_in_request;
ret = ublk_zoned_insert_report_desc(req, &desc);
if (ret)
goto free_req;

ret = blk_rq_map_kern(disk->queue, req, buffer, buffer_length,
GFP_KERNEL);
if (ret) {
blk_mq_free_request(req);
goto out;
}
if (ret)
goto erase_desc;

status = blk_execute_rq(req, 0);
ret = blk_status_to_errno(status);
erase_desc:
ublk_zoned_erase_report_desc(req);
free_req:
blk_mq_free_request(req);
if (ret)
goto out;
Expand Down Expand Up @@ -379,7 +406,7 @@ static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq,
{
struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
struct ublk_io *io = &ubq->ios[req->tag];
struct ublk_rq_data *pdu = blk_mq_rq_to_pdu(req);
struct ublk_zoned_report_desc *desc;
u32 ublk_op;

switch (req_op(req)) {
Expand All @@ -402,12 +429,15 @@ static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq,
ublk_op = UBLK_IO_OP_ZONE_RESET_ALL;
break;
case REQ_OP_DRV_IN:
ublk_op = pdu->operation;
desc = ublk_zoned_get_report_desc(req);
if (!desc)
return BLK_STS_IOERR;
ublk_op = desc->operation;
switch (ublk_op) {
case UBLK_IO_OP_REPORT_ZONES:
iod->op_flags = ublk_op | ublk_req_build_flags(req);
iod->nr_zones = pdu->nr_zones;
iod->start_sector = pdu->sector;
iod->nr_zones = desc->nr_zones;
iod->start_sector = desc->sector;
return BLK_STS_OK;
default:
return BLK_STS_IOERR;
Expand Down

0 comments on commit 75a5e59

Please sign in to comment.