]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - block/ll_rw_blk.c
bsg: minor cleanups
[linux-2.6-omap-h63xx.git] / block / ll_rw_blk.c
index 79807dbc306e58b063464a716c8ace72fb110f10..3795e0708a229b9641d2c70354b81e641dc3853b 100644 (file)
@@ -340,6 +340,15 @@ unsigned blk_ordered_req_seq(struct request *rq)
        if (rq == &q->post_flush_rq)
                return QUEUE_ORDSEQ_POSTFLUSH;
 
+       /*
+        * !fs requests don't need to follow barrier ordering.  Always
+        * put them at the front.  This fixes the following deadlock.
+        *
+        * http://thread.gmane.org/gmane.linux.kernel/537473
+        */
+       if (!blk_fs_request(rq))
+               return QUEUE_ORDSEQ_DRAIN;
+
        if ((rq->cmd_flags & REQ_ORDERED_COLOR) ==
            (q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR))
                return QUEUE_ORDSEQ_DRAIN;
@@ -518,8 +527,6 @@ int blk_do_ordered(request_queue_t *q, struct request **rqp)
 static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
 {
        request_queue_t *q = bio->bi_private;
-       struct bio_vec *bvec;
-       int i;
 
        /*
         * This is dry run, restore bio_sector and size.  We'll finish
@@ -531,13 +538,6 @@ static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
        if (bio->bi_size)
                return 1;
 
-       /* Rewind bvec's */
-       bio->bi_idx = 0;
-       bio_for_each_segment(bvec, bio, i) {
-               bvec->bv_len += bvec->bv_offset;
-               bvec->bv_offset = 0;
-       }
-
        /* Reset bio */
        set_bit(BIO_UPTODATE, &bio->bi_flags);
        bio->bi_size = q->bi_size;
@@ -1221,7 +1221,7 @@ void blk_recount_segments(request_queue_t *q, struct bio *bio)
                 * considered part of another segment, since that might
                 * change with the bounce page.
                 */
-               high = page_to_pfn(bv->bv_page) >= q->bounce_pfn;
+               high = page_to_pfn(bv->bv_page) > q->bounce_pfn;
                if (high || highprv)
                        goto new_hw_segment;
                if (cluster) {
@@ -1264,7 +1264,7 @@ new_hw_segment:
        bio->bi_hw_segments = nr_hw_segs;
        bio->bi_flags |= (1 << BIO_SEG_VALID);
 }
-
+EXPORT_SYMBOL(blk_recount_segments);
 
 static int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
                                   struct bio *nxt)
@@ -1295,9 +1295,9 @@ static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
        if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID)))
                blk_recount_segments(q, nxt);
        if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) ||
-           BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size))
+           BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size))
                return 0;
-       if (bio->bi_size + nxt->bi_size > q->max_segment_size)
+       if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size)
                return 0;
 
        return 1;
@@ -1405,8 +1405,7 @@ static inline int ll_new_hw_segment(request_queue_t *q,
        return 1;
 }
 
-static int ll_back_merge_fn(request_queue_t *q, struct request *req, 
-                           struct bio *bio)
+int ll_back_merge_fn(request_queue_t *q, struct request *req, struct bio *bio)
 {
        unsigned short max_sectors;
        int len;
@@ -1442,6 +1441,7 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req,
 
        return ll_new_hw_segment(q, req, bio);
 }
+EXPORT_SYMBOL(ll_back_merge_fn);
 
 static int ll_front_merge_fn(request_queue_t *q, struct request *req, 
                             struct bio *bio)
@@ -1704,7 +1704,7 @@ EXPORT_SYMBOL(blk_stop_queue);
  *     on a queue, such as calling the unplug function after a timeout.
  *     A block device may call blk_sync_queue to ensure that any
  *     such activity is cancelled, thus allowing it to release resources
- *     the the callbacks might use. The caller must already have made sure
+ *     that the callbacks might use. The caller must already have made sure
  *     that its ->make_request_fn will not re-add plugging prior to calling
  *     this function.
  *
@@ -1712,7 +1712,6 @@ EXPORT_SYMBOL(blk_stop_queue);
 void blk_sync_queue(struct request_queue *q)
 {
        del_timer_sync(&q->unplug_timer);
-       kblockd_flush();
 }
 EXPORT_SYMBOL(blk_sync_queue);
 
@@ -1912,9 +1911,6 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
        }
 
        q->request_fn           = rfn;
-       q->back_merge_fn        = ll_back_merge_fn;
-       q->front_merge_fn       = ll_front_merge_fn;
-       q->merge_requests_fn    = ll_merge_requests_fn;
        q->prep_rq_fn           = NULL;
        q->unplug_fn            = generic_unplug_device;
        q->queue_flags          = (1 << QUEUE_FLAG_CLUSTER);
@@ -1928,6 +1924,8 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
        blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
        blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
 
+       q->sg_reserved_size = INT_MAX;
+
        /*
         * all done
         */
@@ -2350,40 +2348,29 @@ static int __blk_rq_map_user(request_queue_t *q, struct request *rq,
        else
                bio = bio_copy_user(q, uaddr, len, reading);
 
-       if (IS_ERR(bio)) {
+       if (IS_ERR(bio))
                return PTR_ERR(bio);
-       }
 
        orig_bio = bio;
        blk_queue_bounce(q, &bio);
+
        /*
         * We link the bounce buffer in and could have to traverse it
         * later so we have to get a ref to prevent it from being freed
         */
        bio_get(bio);
 
-       /*
-        * for most (all? don't know of any) queues we could
-        * skip grabbing the queue lock here. only drivers with
-        * funky private ->back_merge_fn() function could be
-        * problematic.
-        */
-       spin_lock_irq(q->queue_lock);
        if (!rq->bio)
                blk_rq_bio_prep(q, rq, bio);
-       else if (!q->back_merge_fn(q, rq, bio)) {
+       else if (!ll_back_merge_fn(q, rq, bio)) {
                ret = -EINVAL;
-               spin_unlock_irq(q->queue_lock);
                goto unmap_bio;
        } else {
                rq->biotail->bi_next = bio;
                rq->biotail = bio;
 
-               rq->nr_sectors += bio_sectors(bio);
-               rq->hard_nr_sectors = rq->nr_sectors;
                rq->data_len += bio->bi_size;
        }
-       spin_unlock_irq(q->queue_lock);
 
        return bio->bi_size;
 
@@ -2419,6 +2406,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
                    unsigned long len)
 {
        unsigned long bytes_read = 0;
+       struct bio *bio = NULL;
        int ret;
 
        if (len > (q->max_hw_sectors << 9))
@@ -2445,6 +2433,8 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
                ret = __blk_rq_map_user(q, rq, ubuf, map_len);
                if (ret < 0)
                        goto unmap_rq;
+               if (!bio)
+                       bio = rq->bio;
                bytes_read += ret;
                ubuf += ret;
        }
@@ -2452,7 +2442,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
        rq->buffer = rq->data = NULL;
        return 0;
 unmap_rq:
-       blk_rq_unmap_user(rq);
+       blk_rq_unmap_user(bio);
        return ret;
 }
 
@@ -2464,6 +2454,7 @@ EXPORT_SYMBOL(blk_rq_map_user);
  * @rq:                request to map data to
  * @iov:       pointer to the iovec
  * @iov_count: number of elements in the iovec
+ * @len:       I/O byte count
  *
  * Description:
  *    Data will be mapped directly for zero copy io, if possible. Otherwise
@@ -2509,27 +2500,33 @@ EXPORT_SYMBOL(blk_rq_map_user_iov);
 
 /**
  * blk_rq_unmap_user - unmap a request with user data
- * @rq:                rq to be unmapped
+ * @bio:              start of bio list
  *
  * Description:
- *    Unmap a rq previously mapped by blk_rq_map_user().
- *    rq->bio must be set to the original head of the request.
+ *    Unmap a rq previously mapped by blk_rq_map_user(). The caller must
+ *    supply the original rq->bio from the blk_rq_map_user() return, since
+ *    the io completion may have changed rq->bio.
  */
-int blk_rq_unmap_user(struct request *rq)
+int blk_rq_unmap_user(struct bio *bio)
 {
-       struct bio *bio, *mapped_bio;
+       struct bio *mapped_bio;
+       int ret = 0, ret2;
 
-       while ((bio = rq->bio)) {
-               if (bio_flagged(bio, BIO_BOUNCED))
+       while (bio) {
+               mapped_bio = bio;
+               if (unlikely(bio_flagged(bio, BIO_BOUNCED)))
                        mapped_bio = bio->bi_private;
-               else
-                       mapped_bio = bio;
 
-               __blk_rq_unmap_user(mapped_bio);
-               rq->bio = bio->bi_next;
-               bio_put(bio);
+               ret2 = __blk_rq_unmap_user(mapped_bio);
+               if (ret2 && !ret)
+                       ret = ret2;
+
+               mapped_bio = bio;
+               bio = bio->bi_next;
+               bio_put(mapped_bio);
        }
-       return 0;
+
+       return ret;
 }
 
 EXPORT_SYMBOL(blk_rq_unmap_user);
@@ -2560,6 +2557,7 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
                bio->bi_rw |= (1 << BIO_RW);
 
        blk_rq_bio_prep(q, rq, bio);
+       blk_queue_bounce(q, &rq->bio);
        rq->buffer = rq->data = NULL;
        return 0;
 }
@@ -2822,7 +2820,7 @@ static int attempt_merge(request_queue_t *q, struct request *req,
         * will have updated segment counts, update sector
         * counts here.
         */
-       if (!q->merge_requests_fn(q, req, next))
+       if (!ll_merge_requests_fn(q, req, next))
                return 0;
 
        /*
@@ -2939,7 +2937,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
                case ELEVATOR_BACK_MERGE:
                        BUG_ON(!rq_mergeable(req));
 
-                       if (!q->back_merge_fn(q, req, bio))
+                       if (!ll_back_merge_fn(q, req, bio))
                                break;
 
                        blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE);
@@ -2956,7 +2954,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
                case ELEVATOR_FRONT_MERGE:
                        BUG_ON(!rq_mergeable(req));
 
-                       if (!q->front_merge_fn(q, req, bio))
+                       if (!ll_front_merge_fn(q, req, bio))
                                break;
 
                        blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE);
@@ -3118,7 +3116,7 @@ static inline int should_fail_request(struct bio *bio)
  * bi_sector for remaps as it sees fit.  So the values of these fields
  * should NOT be depended on after the call to generic_make_request.
  */
-void generic_make_request(struct bio *bio)
+static inline void __generic_make_request(struct bio *bio)
 {
        request_queue_t *q;
        sector_t maxsector;
@@ -3217,6 +3215,57 @@ end_io:
        } while (ret);
 }
 
+/*
+ * We only want one ->make_request_fn to be active at a time,
+ * else stack usage with stacked devices could be a problem.
+ * So use current->bio_{list,tail} to keep a list of requests
+ * submited by a make_request_fn function.
+ * current->bio_tail is also used as a flag to say if
+ * generic_make_request is currently active in this task or not.
+ * If it is NULL, then no make_request is active.  If it is non-NULL,
+ * then a make_request is active, and new requests should be added
+ * at the tail
+ */
+void generic_make_request(struct bio *bio)
+{
+       if (current->bio_tail) {
+               /* make_request is active */
+               *(current->bio_tail) = bio;
+               bio->bi_next = NULL;
+               current->bio_tail = &bio->bi_next;
+               return;
+       }
+       /* following loop may be a bit non-obvious, and so deserves some
+        * explanation.
+        * Before entering the loop, bio->bi_next is NULL (as all callers
+        * ensure that) so we have a list with a single bio.
+        * We pretend that we have just taken it off a longer list, so
+        * we assign bio_list to the next (which is NULL) and bio_tail
+        * to &bio_list, thus initialising the bio_list of new bios to be
+        * added.  __generic_make_request may indeed add some more bios
+        * through a recursive call to generic_make_request.  If it
+        * did, we find a non-NULL value in bio_list and re-enter the loop
+        * from the top.  In this case we really did just take the bio
+        * of the top of the list (no pretending) and so fixup bio_list and
+        * bio_tail or bi_next, and call into __generic_make_request again.
+        *
+        * The loop was structured like this to make only one call to
+        * __generic_make_request (which is important as it is large and
+        * inlined) and to keep the structure simple.
+        */
+       BUG_ON(bio->bi_next);
+       do {
+               current->bio_list = bio->bi_next;
+               if (bio->bi_next == NULL)
+                       current->bio_tail = &current->bio_list;
+               else
+                       bio->bi_next = NULL;
+               __generic_make_request(bio);
+               bio = current->bio_list;
+       } while (bio);
+       current->bio_tail = NULL; /* deactivate */
+}
+
 EXPORT_SYMBOL(generic_make_request);
 
 /**
@@ -3509,7 +3558,7 @@ static int blk_cpu_notify(struct notifier_block *self, unsigned long action,
         * If a CPU goes away, splice its entries to the current CPU
         * and trigger a run of the softirq
         */
-       if (action == CPU_DEAD) {
+       if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
                int cpu = (unsigned long) hcpu;
 
                local_irq_disable();
@@ -3633,11 +3682,11 @@ int kblockd_schedule_work(struct work_struct *work)
 
 EXPORT_SYMBOL(kblockd_schedule_work);
 
-void kblockd_flush(void)
+void kblockd_flush_work(struct work_struct *work)
 {
-       flush_workqueue(kblockd_workqueue);
+       cancel_work_sync(work);
 }
-EXPORT_SYMBOL(kblockd_flush);
+EXPORT_SYMBOL(kblockd_flush_work);
 
 int __init blk_dev_init(void)
 {
@@ -3662,8 +3711,8 @@ int __init blk_dev_init(void)
        open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
        register_hotcpu_notifier(&blk_cpu_notifier);
 
-       blk_max_low_pfn = max_low_pfn;
-       blk_max_pfn = max_pfn;
+       blk_max_low_pfn = max_low_pfn - 1;
+       blk_max_pfn = max_pfn - 1;
 
        return 0;
 }
@@ -3745,6 +3794,7 @@ static struct io_context *current_io_context(gfp_t gfp_flags, int node)
                ret->nr_batch_requests = 0; /* because this is 0 */
                ret->aic = NULL;
                ret->cic_root.rb_node = NULL;
+               ret->ioc_data = NULL;
                /* make sure set_task_ioprio() sees the settings above */
                smp_wmb();
                tsk->io_context = ret;
@@ -3752,7 +3802,6 @@ static struct io_context *current_io_context(gfp_t gfp_flags, int node)
 
        return ret;
 }
-EXPORT_SYMBOL(current_io_context);
 
 /*
  * If the current task has no IO context then create one and initialise it.
@@ -4042,6 +4091,13 @@ int blk_register_queue(struct gendisk *disk)
                return ret;
        }
 
+       ret = bsg_register_disk(disk);
+       if (ret) {
+               elv_unregister_queue(q);
+               kobject_unregister(&q->kobj);
+               return ret;
+       }
+
        return 0;
 }
 
@@ -4050,6 +4106,7 @@ void blk_unregister_queue(struct gendisk *disk)
        request_queue_t *q = disk->queue;
 
        if (q && q->request_fn) {
+               bsg_unregister_disk(disk);
                elv_unregister_queue(q);
 
                kobject_uevent(&q->kobj, KOBJ_REMOVE);