mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
60da5bf47d
Pull block layer core updates from Jens Axboe: "Here are the core block IO bits for 3.8. The branch contains: - The final version of the surprise device removal fixups from Bart. - Don't hide EFI partitions under advanced partition types. It's fairly wide spread these days. This is especially dangerous for systems that have both msdos and efi partition tables, where you want to keep them in sync. - Cleanup of using -1 instead of the proper NUMA_NO_NODE - Export control of bdi flusher thread CPU mask and default to using the home node (if known) from Jeff. - Export unplug tracepoint for MD. - Core improvements from Shaohua. Reinstate the recursive merge, as the original bug has been fixed. Add plugging for discard and also fix a problem handling non pow-of-2 discard limits. There's a trivial merge in block/blk-exec.c due to a fix that went into 3.7-rc at a later point than -rc4 where this is based." * 'for-3.8/core' of git://git.kernel.dk/linux-block: block: export block_unplug tracepoint block: add plug for blkdev_issue_discard block: discard granularity might not be power of 2 deadline: Allow 0ms deadline latency, increase the read speed partitions: enable EFI/GPT support by default bsg: Remove unused function bsg_goose_queue() block: Make blk_cleanup_queue() wait until request_fn finished block: Avoid scheduling delayed work on a dead queue block: Avoid that request_fn is invoked on a dead queue block: Let blk_drain_queue() caller obtain the queue lock block: Rename queue dead flag bdi: add a user-tunable cpu_list for the bdi flusher threads block: use NUMA_NO_NODE instead of -1 block: recursive merge requests block CFQ: avoid moving request to different queue
132 lines
3.2 KiB
C
132 lines
3.2 KiB
C
/*
|
|
* Functions related to setting various queue properties from drivers
|
|
*/
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/bio.h>
|
|
#include <linux/blkdev.h>
|
|
|
|
#include "blk.h"
|
|
|
|
/*
|
|
* for max sense size
|
|
*/
|
|
#include <scsi/scsi_cmnd.h>
|
|
|
|
/**
|
|
* blk_end_sync_rq - executes a completion event on a request
|
|
* @rq: request to complete
|
|
* @error: end I/O status of the request
|
|
*/
|
|
static void blk_end_sync_rq(struct request *rq, int error)
|
|
{
|
|
struct completion *waiting = rq->end_io_data;
|
|
|
|
rq->end_io_data = NULL;
|
|
__blk_put_request(rq->q, rq);
|
|
|
|
/*
|
|
* complete last, if this is a stack request the process (and thus
|
|
* the rq pointer) could be invalid right after this complete()
|
|
*/
|
|
complete(waiting);
|
|
}
|
|
|
|
/**
|
|
* blk_execute_rq_nowait - insert a request into queue for execution
|
|
* @q: queue to insert the request in
|
|
* @bd_disk: matching gendisk
|
|
* @rq: request to insert
|
|
* @at_head: insert request at head or tail of queue
|
|
* @done: I/O completion handler
|
|
*
|
|
* Description:
|
|
* Insert a fully prepared request at the back of the I/O scheduler queue
|
|
* for execution. Don't wait for completion.
|
|
*
|
|
* Note:
|
|
* This function will invoke @done directly if the queue is dead.
|
|
*/
|
|
void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
|
|
struct request *rq, int at_head,
|
|
rq_end_io_fn *done)
|
|
{
|
|
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
|
|
bool is_pm_resume;
|
|
|
|
WARN_ON(irqs_disabled());
|
|
|
|
rq->rq_disk = bd_disk;
|
|
rq->end_io = done;
|
|
/*
|
|
* need to check this before __blk_run_queue(), because rq can
|
|
* be freed before that returns.
|
|
*/
|
|
is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
|
|
|
|
spin_lock_irq(q->queue_lock);
|
|
|
|
if (unlikely(blk_queue_dying(q))) {
|
|
rq->errors = -ENXIO;
|
|
if (rq->end_io)
|
|
rq->end_io(rq, rq->errors);
|
|
spin_unlock_irq(q->queue_lock);
|
|
return;
|
|
}
|
|
|
|
__elv_add_request(q, rq, where);
|
|
__blk_run_queue(q);
|
|
/* the queue is stopped so it won't be run */
|
|
if (is_pm_resume)
|
|
__blk_run_queue_uncond(q);
|
|
spin_unlock_irq(q->queue_lock);
|
|
}
|
|
EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
|
|
|
|
/**
|
|
* blk_execute_rq - insert a request into queue for execution
|
|
* @q: queue to insert the request in
|
|
* @bd_disk: matching gendisk
|
|
* @rq: request to insert
|
|
* @at_head: insert request at head or tail of queue
|
|
*
|
|
* Description:
|
|
* Insert a fully prepared request at the back of the I/O scheduler queue
|
|
* for execution and wait for completion.
|
|
*/
|
|
int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
|
|
struct request *rq, int at_head)
|
|
{
|
|
DECLARE_COMPLETION_ONSTACK(wait);
|
|
char sense[SCSI_SENSE_BUFFERSIZE];
|
|
int err = 0;
|
|
unsigned long hang_check;
|
|
|
|
/*
|
|
* we need an extra reference to the request, so we can look at
|
|
* it after io completion
|
|
*/
|
|
rq->ref_count++;
|
|
|
|
if (!rq->sense) {
|
|
memset(sense, 0, sizeof(sense));
|
|
rq->sense = sense;
|
|
rq->sense_len = 0;
|
|
}
|
|
|
|
rq->end_io_data = &wait;
|
|
blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
|
|
|
|
/* Prevent hang_check timer from firing at us during very long I/O */
|
|
hang_check = sysctl_hung_task_timeout_secs;
|
|
if (hang_check)
|
|
while (!wait_for_completion_timeout(&wait, hang_check * (HZ/2)));
|
|
else
|
|
wait_for_completion(&wait);
|
|
|
|
if (rq->errors)
|
|
err = -EIO;
|
|
|
|
return err;
|
|
}
|
|
EXPORT_SYMBOL(blk_execute_rq);
|