On Sun, Nov 23, 2025 at 10:51:25PM +0000, Pavel Begunkov wrote:
Add blk-mq infrastructure to handle dmabuf tokens. There are two main
Please spell out infrastructure in the subject as well.
+struct dma_token *blkdev_dma_map(struct file *file,
struct dma_token_params *params)+{
- struct request_queue *q = bdev_get_queue(file_bdev(file));
- if (!(file->f_flags & O_DIRECT))
return ERR_PTR(-EINVAL);
Shouldn't the O_DIRECT check be in the caller?
+++ b/block/blk-mq-dma-token.c
Missing SPDX and Copyright statement.
@@ -0,0 +1,236 @@ +#include <linux/blk-mq-dma-token.h> +#include <linux/dma-resv.h>
+struct blk_mq_dma_fence {
- struct dma_fence base;
- spinlock_t lock;
+};
And a high-level comment explaining the fencing logic would be nice as well.
- struct blk_mq_dma_map *map = container_of(ref, struct blk_mq_dma_map, refs);
Overly long line.
+static struct blk_mq_dma_map *blk_mq_alloc_dma_mapping(struct blk_mq_dma_token *token)
Another one. Also kinda inconsistent between _map in the data structure and _mapping in the function name.
+static inline +struct blk_mq_dma_map *blk_mq_get_token_map(struct blk_mq_dma_token *token)
Really odd return value / scope formatting.
+{
- struct blk_mq_dma_map *map;
- guard(rcu)();
- map = rcu_dereference(token->map);
- if (unlikely(!map || !percpu_ref_tryget_live_rcu(&map->refs)))
return NULL;- return map;
Please use good old rcu_read_unlock to make this readable.
- guard(mutex)(&token->mapping_lock);
Same.
- map = blk_mq_get_token_map(token);
- if (map)
return map;- map = blk_mq_alloc_dma_mapping(token);
- if (IS_ERR(map))
return NULL;- dma_resv_lock(dmabuf->resv, NULL);
- ret = dma_resv_wait_timeout(dmabuf->resv, DMA_RESV_USAGE_BOOKKEEP,
true, MAX_SCHEDULE_TIMEOUT);- ret = ret ? ret : -ETIME;
if (!ret) ret = -ETIME;
+blk_status_t blk_rq_assign_dma_map(struct request *rq,
struct blk_mq_dma_token *token)+{
- struct blk_mq_dma_map *map;
- map = blk_mq_get_token_map(token);
- if (map)
goto complete;- if (rq->cmd_flags & REQ_NOWAIT)
return BLK_STS_AGAIN;- map = blk_mq_create_dma_map(token);
- if (IS_ERR(map))
return BLK_STS_RESOURCE;
Having a few comments, that say this is creating the map lazily would probably helper the reader. Also why not keep the !map case in the branch, as the map case should be the fast path and thus usually be straight line in the function?
+void blk_mq_dma_map_move_notify(struct blk_mq_dma_token *token) +{
- blk_mq_dma_map_remove(token);
+}
Is there a good reason for having this blk_mq_dma_map_move_notify wrapper?
- if (bio_flagged(bio, BIO_DMA_TOKEN)) {
struct blk_mq_dma_token *token;blk_status_t ret;token = dma_token_to_blk_mq(bio->dma_token);ret = blk_rq_assign_dma_map(rq, token);if (ret) {if (ret == BLK_STS_AGAIN) {bio_wouldblock_error(bio);} else {bio->bi_status = BLK_STS_RESOURCE;bio_endio(bio);}goto queue_exit;}- }
Any reason to not just keep the dma_token_to_blk_mq? Also why is this overriding non-BLK_STS_AGAIN errors with BLK_STS_RESOURCE?
(I really wish we could make all BLK_STS_AGAIN errors be quiet without the explicit setting of BIO_QUIET, which is a bit annoying, but that's not for this patch).
+static inline +struct blk_mq_dma_token *dma_token_to_blk_mq(struct dma_token *token)
More odd formatting.