Commit 2e60e022 authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

block: clean up request completion API

Request completion has gone through several changes and became a bit
messy over the time.  Clean it up.

1. end_that_request_data() is a thin wrapper around
   end_that_request_data_first() which checks whether bio is NULL
   before doing anything and handles bidi completion.
   blk_update_request() is a thin wrapper around
   end_that_request_data() which clears nr_sectors on the last
   iteration but doesn't use the bidi completion.

   Clean it up by moving the initial bio NULL check and nr_sectors
   clearing on the last iteration into end_that_request_data() and
   renaming it to blk_update_request(), which makes blk_end_io() the
   only user of end_that_request_data().  Collapse
   end_that_request_data() into blk_end_io().

2. There are four visible completion variants - blk_end_request(),
   __blk_end_request(), blk_end_bidi_request() and end_request().
   blk_end_request() and blk_end_bidi_request() uses blk_end_request()
   as the backend but __blk_end_request() and end_request() use
   separate implementation in __blk_end_request() due to different
   locking rules.

   blk_end_bidi_request() is identical to blk_end_io().  Collapse
   blk_end_io() into blk_end_bidi_request(), separate out request
   update into internal helper blk_update_bidi_request() and add
   __blk_end_bidi_request().  Redefine [__]blk_end_request() as thin
   inline wrappers around [__]blk_end_bidi_request().

3. As the whole request issue/completion usages are about to be
   modified and audited, it's a good chance to convert completion
   functions return bool which better indicates the intended meaning
   of return values.

4. The function name end_that_request_last() is from the days when it
   was a public interface and slighly confusing.  Give it a proper
   internal name - blk_finish_request().

5. Add description explaning that blk_end_bidi_request() can be safely
   used for uni requests as suggested by Boaz Harrosh.

The only visible behavior change is from #1.  nr_sectors counts are
cleared after the final iteration no matter which function is used to
complete the request.  I couldn't find any place where the code
assumes those nr_sectors counters contain the values for the last
segment and this change is good as it makes the API much more
consistent as the end result is now same whether a request is
completed using [__]blk_end_request() alone or in combination with
blk_update_request().

API further cleaned up per Christoph's suggestion.

[ Impact: cleanup, rq->*nr_sectors always updated after req completion ]
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Reviewed-by: default avatarBoaz Harrosh <bharrosh@panasas.com>
Cc: Christoph Hellwig <hch@infradead.org>
parent 0b302d5a
This diff is collapsed.
...@@ -840,27 +840,97 @@ extern unsigned int blk_rq_bytes(struct request *rq); ...@@ -840,27 +840,97 @@ extern unsigned int blk_rq_bytes(struct request *rq);
extern unsigned int blk_rq_cur_bytes(struct request *rq); extern unsigned int blk_rq_cur_bytes(struct request *rq);
/* /*
* blk_end_request() and friends. * Request completion related functions.
* __blk_end_request() and end_request() must be called with *
* the request queue spinlock acquired. * blk_update_request() completes given number of bytes and updates
* the request without completing it.
*
* blk_end_request() and friends. __blk_end_request() and
* end_request() must be called with the request queue spinlock
* acquired.
* *
* Several drivers define their own end_request and call * Several drivers define their own end_request and call
* blk_end_request() for parts of the original function. * blk_end_request() for parts of the original function.
* This prevents code duplication in drivers. * This prevents code duplication in drivers.
*/ */
extern int blk_end_request(struct request *rq, int error, extern bool blk_update_request(struct request *rq, int error,
unsigned int nr_bytes);
extern int __blk_end_request(struct request *rq, int error,
unsigned int nr_bytes); unsigned int nr_bytes);
extern int blk_end_bidi_request(struct request *rq, int error, extern bool blk_end_bidi_request(struct request *rq, int error,
unsigned int nr_bytes, unsigned int bidi_bytes); unsigned int nr_bytes,
extern void end_request(struct request *, int); unsigned int bidi_bytes);
extern bool __blk_end_bidi_request(struct request *rq, int error,
unsigned int nr_bytes,
unsigned int bidi_bytes);
/**
* blk_end_request - 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
**/
static inline bool blk_end_request(struct request *rq, int error,
unsigned int nr_bytes)
{
return blk_end_bidi_request(rq, error, nr_bytes, 0);
}
/**
* __blk_end_request - 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:
* Must be called with queue lock held unlike blk_end_request().
*
* Return:
* %false - we are done with this request
* %true - still buffers pending for this request
**/
static inline bool __blk_end_request(struct request *rq, int error,
unsigned int nr_bytes)
{
return __blk_end_bidi_request(rq, error, nr_bytes, 0);
}
/**
* end_request - end I/O on the current segment of the request
* @rq: the request being processed
* @uptodate: error value or %0/%1 uptodate flag
*
* Description:
* Ends I/O on the current segment of a request. If that is the only
* remaining segment, the request is also completed and freed.
*
* This is a remnant of how older block drivers handled I/O completions.
* Modern drivers typically end I/O on the full request in one go, unless
* they have a residual value to account for. For that case this function
* isn't really useful, unless the residual just happens to be the
* full current segment. In other words, don't use this function in new
* code. Use blk_end_request() or __blk_end_request() to end a request.
**/
static inline void end_request(struct request *rq, int uptodate)
{
int error = 0;
if (uptodate <= 0)
error = uptodate ? uptodate : -EIO;
__blk_end_bidi_request(rq, error, rq->hard_cur_sectors << 9, 0);
}
extern void blk_complete_request(struct request *); extern void blk_complete_request(struct request *);
extern void __blk_complete_request(struct request *); extern void __blk_complete_request(struct request *);
extern void blk_abort_request(struct request *); extern void blk_abort_request(struct request *);
extern void blk_abort_queue(struct request_queue *); extern void blk_abort_queue(struct request_queue *);
extern void blk_update_request(struct request *rq, int error,
unsigned int nr_bytes);
/* /*
* Access functions for manipulating queue properties * Access functions for manipulating queue properties
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment