[Bluetooth] Restrict well known PSM to privileged users
[pandora-kernel.git] / block / ll_rw_blk.c
index 4337979..fb67897 100644 (file)
@@ -2359,18 +2359,10 @@ static int __blk_rq_map_user(request_queue_t *q, struct request *rq,
         */
        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 (!ll_back_merge_fn(q, rq, bio)) {
                ret = -EINVAL;
-               spin_unlock_irq(q->queue_lock);
                goto unmap_bio;
        } else {
                rq->biotail->bi_next = bio;
@@ -2378,7 +2370,6 @@ static int __blk_rq_map_user(request_queue_t *q, struct request *rq,
 
                rq->data_len += bio->bi_size;
        }
-       spin_unlock_irq(q->queue_lock);
 
        return bio->bi_size;
 
@@ -2414,6 +2405,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))
@@ -2440,6 +2432,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;
        }
@@ -2447,7 +2441,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;
 }
 
@@ -2459,6 +2453,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
@@ -2504,27 +2499,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);