* [RFC 5/9] blk: change funcs' prototype to expose the ref of timer
@ 2014-05-30 8:20 Liu Ping Fan
0 siblings, 0 replies; only message in thread
From: Liu Ping Fan @ 2014-05-30 8:20 UTC (permalink / raw)
To: linux-scsi
Cc: Adaptec OEM Raid Solutions, Jens Axboe, Paolo Bonzini,
Stefan Hajnoczi, Jeff Moyer
req->special is normally referred by both a timer and request_queue.
This patch focus on the timer's ref. It changes a group of func's
prototype, so the caller can inc/dec ref, in according to add/del a
timer.
Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
---
block/blk-core.c | 49 ++++++++++++++++++++++++++++++++++++++++---------
block/blk-timeout.c | 10 ++++++++--
block/blk.h | 2 +-
include/linux/blkdev.h | 4 +++-
4 files changed, 52 insertions(+), 13 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c
index b0261be..beaca2e 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1205,9 +1205,11 @@ EXPORT_SYMBOL(blk_make_request);
* more, when that condition happens we need to put the request back
* on the queue. Must be called with queue lock held.
*/
-void blk_requeue_request(struct request_queue *q, struct request *rq)
+bool blk_requeue_request(struct request_queue *q, struct request *rq)
{
- blk_delete_timer(rq);
+ bool ref;
+
+ ref = blk_delete_timer(rq);
blk_clear_rq_complete(rq);
trace_block_rq_requeue(q, rq);
@@ -1217,6 +1219,7 @@ void blk_requeue_request(struct request_queue *q, struct request *rq)
BUG_ON(blk_queued_rq(rq));
elv_requeue_request(q, rq);
+ return ref;
}
EXPORT_SYMBOL(blk_requeue_request);
@@ -2492,8 +2495,10 @@ EXPORT_SYMBOL_GPL(blk_unprep_request);
/*
* queue lock must be held
*/
-static void blk_finish_request(struct request *req, int error)
+static void blk_finish_request(struct request *req, int error, int *drop_ref)
{
+ bool ref;
+
if (blk_rq_tagged(req))
blk_queue_end_tag(req->q, req);
@@ -2502,7 +2507,11 @@ static void blk_finish_request(struct request *req, int error)
if (unlikely(laptop_mode) && req->cmd_type == REQ_TYPE_FS)
laptop_io_completion(&req->q->backing_dev_info);
- blk_delete_timer(req);
+ ref = blk_delete_timer(req);
+ if (likely(ref && drop_ref))
+ *drop_ref = 1;
+ else if (drop_ref)
+ *drop_ref = 0;
if (req->cmd_flags & REQ_DONTPREP)
blk_unprep_request(req);
@@ -2537,7 +2546,7 @@ static void blk_finish_request(struct request *req, int error)
* %true - still buffers pending for this request
**/
static bool blk_end_bidi_request(struct request *rq, int error,
- unsigned int nr_bytes, unsigned int bidi_bytes)
+ unsigned int nr_bytes, unsigned int bidi_bytes, int *drop_ref)
{
struct request_queue *q = rq->q;
unsigned long flags;
@@ -2546,7 +2555,7 @@ static bool blk_end_bidi_request(struct request *rq, int error,
return true;
spin_lock_irqsave(q->queue_lock, flags);
- blk_finish_request(rq, error);
+ blk_finish_request(rq, error, drop_ref);
spin_unlock_irqrestore(q->queue_lock, flags);
return false;
@@ -2573,7 +2582,7 @@ bool __blk_end_bidi_request(struct request *rq, int error,
if (blk_update_bidi_request(rq, error, nr_bytes, bidi_bytes))
return true;
- blk_finish_request(rq, error);
+ blk_finish_request(rq, error, NULL);
return false;
}
@@ -2594,11 +2603,32 @@ bool __blk_end_bidi_request(struct request *rq, int error,
**/
bool blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
{
- return blk_end_bidi_request(rq, error, nr_bytes, 0);
+ return blk_end_bidi_request(rq, error, nr_bytes, 0, NULL);
}
EXPORT_SYMBOL(blk_end_request);
/**
+ * blk_end_request_ref - Helper function for drivers to complete the request.
+ * @rq: the request being processed
+ * @error: %0 for success, < %0 for error
+ * @nr_bytes: number of bytes to complete
+ *
+ * Description:
+ * Ends I/O on a number of bytes attached to @rq.
+ * If @rq has leftover, sets it up for the next range of segments.
+ *
+ * Return:
+ * %false - we are done with this request
+ * %true - still buffers pending for this request
+ **/
+bool blk_end_request_ref(struct request *rq, int error, unsigned int nr_bytes,
+ int *drop_ref)
+{
+ return blk_end_bidi_request(rq, error, nr_bytes, 0, drop_ref);
+}
+EXPORT_SYMBOL(blk_end_request_ref);
+
+/**
* blk_end_request_all - Helper function for drives to finish the request.
* @rq: the request to finish
* @error: %0 for success, < %0 for error
@@ -2614,7 +2644,8 @@ void blk_end_request_all(struct request *rq, int error)
if (unlikely(blk_bidi_rq(rq)))
bidi_bytes = blk_rq_bytes(rq->next_rq);
- pending = blk_end_bidi_request(rq, error, blk_rq_bytes(rq), bidi_bytes);
+ pending = blk_end_bidi_request(rq, error, blk_rq_bytes(rq), bidi_bytes,
+ NULL);
BUG_ON(pending);
}
EXPORT_SYMBOL(blk_end_request_all);
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index d3067f0..839962b 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -74,10 +74,16 @@ ssize_t part_timeout_store(struct device *dev, struct device_attribute *attr,
* blk_delete_timer - Delete/cancel timer for a given function.
* @req: request that we are canceling timer for
*
+ * return: true, timeout_list is not empty
*/
-void blk_delete_timer(struct request *req)
+bool blk_delete_timer(struct request *req)
{
- list_del_init(&req->timeout_list);
+ bool ret;
+
+ ret = !list_empty(&req->timeout_list);
+ if (ret)
+ list_del_init(&req->timeout_list);
+ return ret;
}
static void blk_rq_timed_out(struct request *req)
diff --git a/block/blk.h b/block/blk.h
index a9cad62..9cd70b1 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -37,7 +37,7 @@ void blk_rq_timed_out_timer(unsigned long data);
void blk_rq_check_expired(struct request *rq, unsigned long *next_timeout,
unsigned int *next_set);
void __blk_add_timer(struct request *req, struct list_head *timeout_list);
-void blk_delete_timer(struct request *);
+bool blk_delete_timer(struct request *);
void blk_add_timer(struct request *);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 23deadb..7a2e79f 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -775,7 +775,7 @@ extern void __blk_put_request(struct request_queue *, struct request *);
extern struct request *blk_get_request(struct request_queue *, int, gfp_t);
extern struct request *blk_make_request(struct request_queue *, struct bio *,
gfp_t);
-extern void blk_requeue_request(struct request_queue *, struct request *);
+extern bool blk_requeue_request(struct request_queue *, struct request *);
extern void blk_add_request_payload(struct request *rq, struct page *page,
unsigned int len);
extern int blk_rq_check_limits(struct request_queue *q, struct request *rq);
@@ -934,6 +934,8 @@ extern struct request *blk_fetch_request(struct request_queue *q);
*/
extern bool blk_update_request(struct request *rq, int error,
unsigned int nr_bytes);
+extern bool blk_end_request_ref(struct request *rq, int error,
+ unsigned int nr_bytes, int *drop_ref);
extern bool blk_end_request(struct request *rq, int error,
unsigned int nr_bytes);
extern void blk_end_request_all(struct request *rq, int error);
--
1.8.1.4
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2014-05-30 8:17 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-30 8:20 [RFC 5/9] blk: change funcs' prototype to expose the ref of timer Liu Ping Fan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).