From 092ebcedddd4e13243db4caa28106aaa2168239e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 6 Jan 2011 07:43:59 +0100 Subject: sbull: Use blk_fetch_request instead blk_peek_request to dequeue requests The block layer request API changes make a requirement for block drivers to dequeue requests before signal its completition. Commit 1dfd4ab138fc9f9cad869e6110022c7cfd5544d1 changed sbull to use the new block layer API. But the patch only renamed the functions while keeping the old driver semantics. It used blk_peek_request() that does the same that elv_next_request() did. Remove the request from the queue before is not only a recomendation but a true requirement. Attempting to complete a request that remains in the queue make the kernel oops. So the last commit introduced a Bug. This patch uses blk_fetch_request() instead of blk_peek_request(). blk_fetch_request() not only returns the request in the head of the queue but also removes the request from the queue so a latter signaling of the request completition doesn't hang the system. --- sbull/sbull.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sbull/sbull.c b/sbull/sbull.c index 8201f7d..0dc474e 100644 --- a/sbull/sbull.c +++ b/sbull/sbull.c @@ -104,11 +104,11 @@ static void sbull_request(struct request_queue *q) { struct request *req; - while ((req = blk_peek_request(q)) != NULL) { + while ((req = blk_fetch_request(q)) != NULL) { struct sbull_dev *dev = req->rq_disk->private_data; if (req->cmd_type != REQ_TYPE_FS) { printk (KERN_NOTICE "Skip non-fs request\n"); - blk_end_request(req, 0, blk_rq_cur_bytes(req)); + __blk_end_request_cur(req, -EIO); continue; } // printk (KERN_NOTICE "Req dev %d dir %ld sec %ld, nr %d f %lx\n", @@ -117,7 +117,7 @@ static void sbull_request(struct request_queue *q) // req->flags); sbull_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req)); - blk_end_request(req, 1, blk_rq_cur_bytes(req)); + __blk_end_request_cur(req, 0); } } @@ -168,17 +168,14 @@ static void sbull_full_request(struct request_queue *q) int sectors_xferred; struct sbull_dev *dev = q->queuedata; - while ((req = blk_peek_request(q)) != NULL) { + while ((req = blk_fetch_request(q)) != NULL) { if (req->cmd_type != REQ_TYPE_FS) { printk (KERN_NOTICE "Skip non-fs request\n"); - blk_end_request(req, 0, blk_rq_cur_bytes(req)); + __blk_end_request(req, -EIO, blk_rq_cur_bytes(req)); continue; } sectors_xferred = sbull_xfer_request(dev, req); - if (! __blk_end_request(req, 1, sectors_xferred)) { - blk_start_request(req); - __blk_end_request(req, 0, blk_rq_cur_bytes(req)); - } + __blk_end_request(req, 0, sectors_xferred); } } -- cgit v1.2.1-18-gbd029