Back to home page

LXR

 
 

    


0001 /*
0002  * Functions related to setting various queue properties from drivers
0003  */
0004 #include <linux/kernel.h>
0005 #include <linux/module.h>
0006 #include <linux/bio.h>
0007 #include <linux/blkdev.h>
0008 #include <linux/blk-mq.h>
0009 #include <linux/sched/sysctl.h>
0010 
0011 #include "blk.h"
0012 
0013 /*
0014  * for max sense size
0015  */
0016 #include <scsi/scsi_cmnd.h>
0017 
0018 /**
0019  * blk_end_sync_rq - executes a completion event on a request
0020  * @rq: request to complete
0021  * @error: end I/O status of the request
0022  */
0023 static void blk_end_sync_rq(struct request *rq, int error)
0024 {
0025     struct completion *waiting = rq->end_io_data;
0026 
0027     rq->end_io_data = NULL;
0028 
0029     /*
0030      * complete last, if this is a stack request the process (and thus
0031      * the rq pointer) could be invalid right after this complete()
0032      */
0033     complete(waiting);
0034 }
0035 
0036 /**
0037  * blk_execute_rq_nowait - insert a request into queue for execution
0038  * @q:      queue to insert the request in
0039  * @bd_disk:    matching gendisk
0040  * @rq:     request to insert
0041  * @at_head:    insert request at head or tail of queue
0042  * @done:   I/O completion handler
0043  *
0044  * Description:
0045  *    Insert a fully prepared request at the back of the I/O scheduler queue
0046  *    for execution.  Don't wait for completion.
0047  *
0048  * Note:
0049  *    This function will invoke @done directly if the queue is dead.
0050  */
0051 void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
0052                struct request *rq, int at_head,
0053                rq_end_io_fn *done)
0054 {
0055     int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
0056 
0057     WARN_ON(irqs_disabled());
0058     WARN_ON(rq->cmd_type == REQ_TYPE_FS);
0059 
0060     rq->rq_disk = bd_disk;
0061     rq->end_io = done;
0062 
0063     /*
0064      * don't check dying flag for MQ because the request won't
0065      * be reused after dying flag is set
0066      */
0067     if (q->mq_ops) {
0068         blk_mq_insert_request(rq, at_head, true, false);
0069         return;
0070     }
0071 
0072     spin_lock_irq(q->queue_lock);
0073 
0074     if (unlikely(blk_queue_dying(q))) {
0075         rq->rq_flags |= RQF_QUIET;
0076         rq->errors = -ENXIO;
0077         __blk_end_request_all(rq, rq->errors);
0078         spin_unlock_irq(q->queue_lock);
0079         return;
0080     }
0081 
0082     __elv_add_request(q, rq, where);
0083     __blk_run_queue(q);
0084     spin_unlock_irq(q->queue_lock);
0085 }
0086 EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
0087 
0088 /**
0089  * blk_execute_rq - insert a request into queue for execution
0090  * @q:      queue to insert the request in
0091  * @bd_disk:    matching gendisk
0092  * @rq:     request to insert
0093  * @at_head:    insert request at head or tail of queue
0094  *
0095  * Description:
0096  *    Insert a fully prepared request at the back of the I/O scheduler queue
0097  *    for execution and wait for completion.
0098  */
0099 int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
0100            struct request *rq, int at_head)
0101 {
0102     DECLARE_COMPLETION_ONSTACK(wait);
0103     char sense[SCSI_SENSE_BUFFERSIZE];
0104     int err = 0;
0105     unsigned long hang_check;
0106 
0107     if (!rq->sense) {
0108         memset(sense, 0, sizeof(sense));
0109         rq->sense = sense;
0110         rq->sense_len = 0;
0111     }
0112 
0113     rq->end_io_data = &wait;
0114     blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
0115 
0116     /* Prevent hang_check timer from firing at us during very long I/O */
0117     hang_check = sysctl_hung_task_timeout_secs;
0118     if (hang_check)
0119         while (!wait_for_completion_io_timeout(&wait, hang_check * (HZ/2)));
0120     else
0121         wait_for_completion_io(&wait);
0122 
0123     if (rq->errors)
0124         err = -EIO;
0125 
0126     if (rq->sense == sense) {
0127         rq->sense = NULL;
0128         rq->sense_len = 0;
0129     }
0130 
0131     return err;
0132 }
0133 EXPORT_SYMBOL(blk_execute_rq);