Reputation: 6883
I am trying to write a device driver for a network attached hard disk. and I am wondering what is the proper way to lock/unlock the requests queue and where?
To clarify:
blk_init_queue
and passed to that function the request handler function and a lock (i.e. semaphore) that I created.My request handler function looks like this:
struct request *req;
int ret;
while ((req = blk_fetch_request(q)) != NULL) {
ret = rb_transfer(req);
}
My rb_transfer
starts a new kernel thread to handle the request.
Once the request is handled and the data transfer is done, blk_end_request_cur
is called on that request.
Now, my question is how to protect access to the request queue in the loop above? and in the driver in general?
I tried something like this:
struct request *req;
int ret;
while ((req = blk_fetch_request(q)) != NULL) {
spin_lock(&lock);
ret = rb_transfer(req);
spin_unlock(&lock);
}
But this failed and caused a kernel lock up.
Any other ideas?
Upvotes: 3
Views: 842
Reputation: 1261
The request_fn
that you pass to blk_init_queue
is called by holding the spinlock
passed as the second argument and interrupts disabled. Hence, you can safely assume that no parallel threads are running that are executing this request_fn
. However, if you create a parallel thread that processes this request, then synchronizing access to the requests in those threads are entirely your responsibility.
The request_fn
is called by __blk_run_queue_uncond
which is inturn called by functions __blk_run_queue
and blk_execute_rq_nowait
. If you search for functions calling __blk_run_queue
in the linux kernel, you can see that all of them do so by holding the q->queue_lock
which is the spinlock passed to function blk_init_queue
.
Upvotes: 3