On 12/17/2016 01:12 AM, Jens Axboe wrote: > +static bool dd_put_request(struct request *rq) > +{ > + /* > + * If it's a real request, we just have to free it. For a shadow > + * request, we should only free it if we haven't started it. A > + * started request is mapped to a real one, and the real one will > + * free it. We can get here with request merges, since we then > + * free the request before we start/issue it. > + */ > + if (!blk_mq_sched_rq_is_shadow(rq)) > + return false; > + > + if (!(rq->rq_flags & RQF_STARTED)) { > + struct request_queue *q = rq->q; > + struct deadline_data *dd = q->elevator->elevator_data; > + > + /* > + * IO completion would normally do this, but if we merge > + * and free before we issue the request, drop both the > + * tag and queue ref > + */ > + blk_mq_sched_free_shadow_request(dd->tags, rq); > + blk_queue_exit(q); > + } > + > + return true; > +} Hello Jens, Since this patch is the first patch that introduces a call to blk_queue_exit() from a module other than the block layer core, shouldn't this patch export the blk_queue_exit() function? An attempt to build mq-deadline as a module resulted in the following: ERROR: "blk_queue_exit" [block/mq-deadline.ko] undefined! make[1]: *** [scripts/Makefile.modpost:91: __modpost] Error 1 make: *** [Makefile:1198: modules] Error 2 Execution failed: make all Bart.��.n��������+%������w��{.n�����{����n�r������&��z�ޗ�zf���h���~����������_��+v���)ߣ�