summaryrefslogtreecommitdiff
path: root/drivers/block/ublk_drv.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2022-07-21 16:09:15 +0300
committerJens Axboe <axboe@kernel.dk>2022-07-21 19:52:12 +0300
commitc50061f0f1a90df72aaa87eb17c459fa77952ad1 (patch)
tree976daac12b9be21dc97e368f9a284c559e1028bf /drivers/block/ublk_drv.c
parentcfee7e4de2870017a4cbfdcf2d17329cc025b742 (diff)
downloadlinux-c50061f0f1a90df72aaa87eb17c459fa77952ad1.tar.xz
ublk: rewrite ublk_ctrl_get_queue_affinity to not rely on hctx->cpumask
Looking at the hctxs and cpumap is not safe without at very last a RCU reference. It also requires the queue to be set up before starting the device, which leads to rather awkward life time rules. Instead rewrite ublk_ctrl_get_queue_affinity to just build the cpumask directly from the mq_map in the tag set, similar to hctx->cpumask is built. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Ming Lei <ming.lei@redhat.com> Link: https://lore.kernel.org/r/20220721130916.1869719-8-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/ublk_drv.c')
-rw-r--r--drivers/block/ublk_drv.c55
1 files changed, 24 insertions, 31 deletions
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index b8ac7b508029..748247c0435b 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -1245,26 +1245,15 @@ out_unlock:
return ret;
}
-static struct blk_mq_hw_ctx *ublk_get_hw_queue(struct ublk_device *ub,
- unsigned int index)
-{
- struct blk_mq_hw_ctx *hctx;
- unsigned long i;
-
- queue_for_each_hw_ctx(ub->ub_queue, hctx, i)
- if (hctx->queue_num == index)
- return hctx;
- return NULL;
-}
-
static int ublk_ctrl_get_queue_affinity(struct io_uring_cmd *cmd)
{
struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd;
void __user *argp = (void __user *)(unsigned long)header->addr;
- struct blk_mq_hw_ctx *hctx;
struct ublk_device *ub;
+ cpumask_var_t cpumask;
unsigned long queue;
unsigned int retlen;
+ unsigned int i;
int ret = -EINVAL;
if (header->len * BITS_PER_BYTE < nr_cpu_ids)
@@ -1276,30 +1265,34 @@ static int ublk_ctrl_get_queue_affinity(struct io_uring_cmd *cmd)
ub = ublk_get_device_from_id(header->dev_id);
if (!ub)
- goto out;
+ return -EINVAL;
queue = header->data[0];
if (queue >= ub->dev_info.nr_hw_queues)
- goto out;
- hctx = ublk_get_hw_queue(ub, queue);
- if (!hctx)
- goto out;
+ goto out_put_device;
- retlen = min_t(unsigned short, header->len, cpumask_size());
- if (copy_to_user(argp, hctx->cpumask, retlen)) {
- ret = -EFAULT;
- goto out;
- }
- if (retlen != header->len) {
- if (clear_user(argp + retlen, header->len - retlen)) {
- ret = -EFAULT;
- goto out;
- }
+ ret = -ENOMEM;
+ if (!zalloc_cpumask_var(&cpumask, GFP_KERNEL))
+ goto out_put_device;
+
+ for_each_possible_cpu(i) {
+ if (ub->tag_set.map[HCTX_TYPE_DEFAULT].mq_map[i] == queue)
+ cpumask_set_cpu(i, cpumask);
}
+
+ ret = -EFAULT;
+ retlen = min_t(unsigned short, header->len, cpumask_size());
+ if (copy_to_user(argp, cpumask, retlen))
+ goto out_free_cpumask;
+ if (retlen != header->len &&
+ clear_user(argp + retlen, header->len - retlen))
+ goto out_free_cpumask;
+
ret = 0;
- out:
- if (ub)
- ublk_put_device(ub);
+out_free_cpumask:
+ free_cpumask_var(cpumask);
+out_put_device:
+ ublk_put_device(ub);
return ret;
}