Merge branch 'tip/perf/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/roste...
[deliverable/linux.git] / block / blk-core.c
index 3531d8e1da0485f3e8d3fc3757f32e2964b8fa41..ee1a1e7e63ccfc3e735566e3725febee1890bb2e 100644 (file)
@@ -608,6 +608,7 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn,
 
        q->request_fn           = rfn;
        q->prep_rq_fn           = NULL;
+       q->unprep_rq_fn         = NULL;
        q->unplug_fn            = generic_unplug_device;
        q->queue_flags          = QUEUE_FLAG_DEFAULT;
        q->queue_lock           = lock;
@@ -1513,7 +1514,10 @@ static inline void __generic_make_request(struct bio *bio)
                if (bio_check_eod(bio, nr_sectors))
                        goto end_io;
 
-               if ((bio->bi_rw & REQ_DISCARD) && !blk_queue_discard(q)) {
+               if ((bio->bi_rw & REQ_DISCARD) &&
+                   (!blk_queue_discard(q) ||
+                    ((bio->bi_rw & REQ_SECURE) &&
+                     !blk_queue_secdiscard(q)))) {
                        err = -EOPNOTSUPP;
                        goto end_io;
                }
@@ -1598,7 +1602,7 @@ void submit_bio(int rw, struct bio *bio)
         * If it's a regular read/write or a barrier with data attached,
         * go through the normal accounting stuff before submission.
         */
-       if (bio_has_data(bio) && !(rw & (1 << BIO_RW_DISCARD))) {
+       if (bio_has_data(bio) && !(rw & REQ_DISCARD)) {
                if (rw & WRITE) {
                        count_vm_events(PGPGOUT, count);
                } else {
@@ -1643,6 +1647,9 @@ EXPORT_SYMBOL(submit_bio);
  */
 int blk_rq_check_limits(struct request_queue *q, struct request *rq)
 {
+       if (rq->cmd_flags & REQ_DISCARD)
+               return 0;
+
        if (blk_rq_sectors(rq) > queue_max_sectors(q) ||
            blk_rq_bytes(rq) > queue_max_hw_sectors(q) << 9) {
                printk(KERN_ERR "%s: over max size limit.\n", __func__);
@@ -2133,6 +2140,26 @@ static bool blk_update_bidi_request(struct request *rq, int error,
        return false;
 }
 
+/**
+ * blk_unprep_request - unprepare a request
+ * @req:       the request
+ *
+ * This function makes a request ready for complete resubmission (or
+ * completion).  It happens only after all error handling is complete,
+ * so represents the appropriate moment to deallocate any resources
+ * that were allocated to the request in the prep_rq_fn.  The queue
+ * lock is held when calling this.
+ */
+void blk_unprep_request(struct request *req)
+{
+       struct request_queue *q = req->q;
+
+       req->cmd_flags &= ~REQ_DONTPREP;
+       if (q->unprep_rq_fn)
+               q->unprep_rq_fn(q, req);
+}
+EXPORT_SYMBOL_GPL(blk_unprep_request);
+
 /*
  * queue lock must be held
  */
@@ -2148,6 +2175,10 @@ static void blk_finish_request(struct request *req, int error)
 
        blk_delete_timer(req);
 
+       if (req->cmd_flags & REQ_DONTPREP)
+               blk_unprep_request(req);
+
+
        blk_account_io_done(req);
 
        if (req->end_io)
@@ -2467,6 +2498,8 @@ static void __blk_rq_prep_clone(struct request *dst, struct request *src)
 {
        dst->cpu = src->cpu;
        dst->cmd_flags = (rq_data_dir(src) | REQ_NOMERGE);
+       if (src->cmd_flags & REQ_DISCARD)
+               dst->cmd_flags |= REQ_DISCARD;
        dst->cmd_type = src->cmd_type;
        dst->__sector = blk_rq_pos(src);
        dst->__data_len = blk_rq_bytes(src);
This page took 0.032559 seconds and 5 git commands to generate.