]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - block/blk-core.c
Merge tag 'audit-pr-20170907' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
[mirror_ubuntu-bionic-kernel.git] / block / blk-core.c
index dbecbf4a64e05b764a1ba0a3c4dfe8f01bc7aac1..d709c0e3a2ac012c989549bd32ff47306a2ff2a5 100644 (file)
@@ -280,7 +280,7 @@ EXPORT_SYMBOL(blk_start_queue_async);
 void blk_start_queue(struct request_queue *q)
 {
        lockdep_assert_held(q->queue_lock);
-       WARN_ON(!irqs_disabled());
+       WARN_ON(!in_interrupt() && !irqs_disabled());
        WARN_ON_ONCE(q->mq_ops);
 
        queue_flag_clear(QUEUE_FLAG_STOPPED, q);
@@ -1469,15 +1469,10 @@ static void add_acct_request(struct request_queue *q, struct request *rq,
        __elv_add_request(q, rq, where);
 }
 
-static void part_round_stats_single(int cpu, struct hd_struct *part,
-                                   unsigned long now)
+static void part_round_stats_single(struct request_queue *q, int cpu,
+                                   struct hd_struct *part, unsigned long now,
+                                   unsigned int inflight)
 {
-       int inflight;
-
-       if (now == part->stamp)
-               return;
-
-       inflight = part_in_flight(part);
        if (inflight) {
                __part_stat_add(cpu, part, time_in_queue,
                                inflight * (now - part->stamp));
@@ -1488,6 +1483,7 @@ static void part_round_stats_single(int cpu, struct hd_struct *part,
 
 /**
  * part_round_stats() - Round off the performance stats on a struct disk_stats.
+ * @q: target block queue
  * @cpu: cpu number for stats access
  * @part: target partition
  *
@@ -1502,13 +1498,31 @@ static void part_round_stats_single(int cpu, struct hd_struct *part,
  * /proc/diskstats.  This accounts immediately for all queue usage up to
  * the current jiffies and restarts the counters again.
  */
-void part_round_stats(int cpu, struct hd_struct *part)
+void part_round_stats(struct request_queue *q, int cpu, struct hd_struct *part)
 {
+       struct hd_struct *part2 = NULL;
        unsigned long now = jiffies;
+       unsigned int inflight[2];
+       int stats = 0;
+
+       if (part->stamp != now)
+               stats |= 1;
+
+       if (part->partno) {
+               part2 = &part_to_disk(part)->part0;
+               if (part2->stamp != now)
+                       stats |= 2;
+       }
 
-       if (part->partno)
-               part_round_stats_single(cpu, &part_to_disk(part)->part0, now);
-       part_round_stats_single(cpu, part, now);
+       if (!stats)
+               return;
+
+       part_in_flight(q, part, inflight);
+
+       if (stats & 2)
+               part_round_stats_single(q, cpu, part2, now, inflight[1]);
+       if (stats & 1)
+               part_round_stats_single(q, cpu, part, now, inflight[0]);
 }
 EXPORT_SYMBOL_GPL(part_round_stats);
 
@@ -1896,40 +1910,15 @@ out_unlock:
        return BLK_QC_T_NONE;
 }
 
-/*
- * If bio->bi_dev is a partition, remap the location
- */
-static inline void blk_partition_remap(struct bio *bio)
-{
-       struct block_device *bdev = bio->bi_bdev;
-
-       /*
-        * Zone reset does not include bi_size so bio_sectors() is always 0.
-        * Include a test for the reset op code and perform the remap if needed.
-        */
-       if (bdev != bdev->bd_contains &&
-           (bio_sectors(bio) || bio_op(bio) == REQ_OP_ZONE_RESET)) {
-               struct hd_struct *p = bdev->bd_part;
-
-               bio->bi_iter.bi_sector += p->start_sect;
-               bio->bi_bdev = bdev->bd_contains;
-
-               trace_block_bio_remap(bdev_get_queue(bio->bi_bdev), bio,
-                                     bdev->bd_dev,
-                                     bio->bi_iter.bi_sector - p->start_sect);
-       }
-}
-
 static void handle_bad_sector(struct bio *bio)
 {
        char b[BDEVNAME_SIZE];
 
        printk(KERN_INFO "attempt to access beyond end of device\n");
        printk(KERN_INFO "%s: rw=%d, want=%Lu, limit=%Lu\n",
-                       bdevname(bio->bi_bdev, b),
-                       bio->bi_opf,
+                       bio_devname(bio, b), bio->bi_opf,
                        (unsigned long long)bio_end_sector(bio),
-                       (long long)(i_size_read(bio->bi_bdev->bd_inode) >> 9));
+                       (long long)get_capacity(bio->bi_disk));
 }
 
 #ifdef CONFIG_FAIL_MAKE_REQUEST
@@ -1967,6 +1956,38 @@ static inline bool should_fail_request(struct hd_struct *part,
 
 #endif /* CONFIG_FAIL_MAKE_REQUEST */
 
+/*
+ * Remap block n of partition p to block n+start(p) of the disk.
+ */
+static inline int blk_partition_remap(struct bio *bio)
+{
+       struct hd_struct *p;
+       int ret = 0;
+
+       /*
+        * Zone reset does not include bi_size so bio_sectors() is always 0.
+        * Include a test for the reset op code and perform the remap if needed.
+        */
+       if (!bio->bi_partno ||
+           (!bio_sectors(bio) && bio_op(bio) != REQ_OP_ZONE_RESET))
+               return 0;
+
+       rcu_read_lock();
+       p = __disk_get_part(bio->bi_disk, bio->bi_partno);
+       if (likely(p && !should_fail_request(p, bio->bi_iter.bi_size))) {
+               bio->bi_iter.bi_sector += p->start_sect;
+               bio->bi_partno = 0;
+               trace_block_bio_remap(bio->bi_disk->queue, bio, part_devt(p),
+                               bio->bi_iter.bi_sector - p->start_sect);
+       } else {
+               printk("%s: fail for partition %d\n", __func__, bio->bi_partno);
+               ret = -EIO;
+       }
+       rcu_read_unlock();
+
+       return ret;
+}
+
 /*
  * Check whether this bio extends beyond the end of the device.
  */
@@ -1978,7 +1999,7 @@ static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors)
                return 0;
 
        /* Test device or partition size, when known. */
-       maxsector = i_size_read(bio->bi_bdev->bd_inode) >> 9;
+       maxsector = get_capacity(bio->bi_disk);
        if (maxsector) {
                sector_t sector = bio->bi_iter.bi_sector;
 
@@ -2003,20 +2024,18 @@ generic_make_request_checks(struct bio *bio)
        int nr_sectors = bio_sectors(bio);
        blk_status_t status = BLK_STS_IOERR;
        char b[BDEVNAME_SIZE];
-       struct hd_struct *part;
 
        might_sleep();
 
        if (bio_check_eod(bio, nr_sectors))
                goto end_io;
 
-       q = bdev_get_queue(bio->bi_bdev);
+       q = bio->bi_disk->queue;
        if (unlikely(!q)) {
                printk(KERN_ERR
                       "generic_make_request: Trying to access "
                        "nonexistent block-device %s (%Lu)\n",
-                       bdevname(bio->bi_bdev, b),
-                       (long long) bio->bi_iter.bi_sector);
+                       bio_devname(bio, b), (long long)bio->bi_iter.bi_sector);
                goto end_io;
        }
 
@@ -2028,17 +2047,11 @@ generic_make_request_checks(struct bio *bio)
        if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_rq_based(q))
                goto not_supported;
 
-       part = bio->bi_bdev->bd_part;
-       if (should_fail_request(part, bio->bi_iter.bi_size) ||
-           should_fail_request(&part_to_disk(part)->part0,
-                               bio->bi_iter.bi_size))
+       if (should_fail_request(&bio->bi_disk->part0, bio->bi_iter.bi_size))
                goto end_io;
 
-       /*
-        * If this device has partitions, remap block n
-        * of partition p to block n+start(p) of the disk.
-        */
-       blk_partition_remap(bio);
+       if (blk_partition_remap(bio))
+               goto end_io;
 
        if (bio_check_eod(bio, nr_sectors))
                goto end_io;
@@ -2067,16 +2080,16 @@ generic_make_request_checks(struct bio *bio)
                        goto not_supported;
                break;
        case REQ_OP_WRITE_SAME:
-               if (!bdev_write_same(bio->bi_bdev))
+               if (!q->limits.max_write_same_sectors)
                        goto not_supported;
                break;
        case REQ_OP_ZONE_REPORT:
        case REQ_OP_ZONE_RESET:
-               if (!bdev_is_zoned(bio->bi_bdev))
+               if (!blk_queue_is_zoned(q))
                        goto not_supported;
                break;
        case REQ_OP_WRITE_ZEROES:
-               if (!bdev_write_zeroes_sectors(bio->bi_bdev))
+               if (!q->limits.max_write_zeroes_sectors)
                        goto not_supported;
                break;
        default:
@@ -2183,7 +2196,7 @@ blk_qc_t generic_make_request(struct bio *bio)
        bio_list_init(&bio_list_on_stack[0]);
        current->bio_list = bio_list_on_stack;
        do {
-               struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+               struct request_queue *q = bio->bi_disk->queue;
 
                if (likely(blk_queue_enter(q, bio->bi_opf & REQ_NOWAIT) == 0)) {
                        struct bio_list lower, same;
@@ -2201,7 +2214,7 @@ blk_qc_t generic_make_request(struct bio *bio)
                        bio_list_init(&lower);
                        bio_list_init(&same);
                        while ((bio = bio_list_pop(&bio_list_on_stack[0])) != NULL)
-                               if (q == bdev_get_queue(bio->bi_bdev))
+                               if (q == bio->bi_disk->queue)
                                        bio_list_add(&same, bio);
                                else
                                        bio_list_add(&lower, bio);
@@ -2244,7 +2257,7 @@ blk_qc_t submit_bio(struct bio *bio)
                unsigned int count;
 
                if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME))
-                       count = bdev_logical_block_size(bio->bi_bdev) >> 9;
+                       count = queue_logical_block_size(bio->bi_disk->queue);
                else
                        count = bio_sectors(bio);
 
@@ -2261,8 +2274,7 @@ blk_qc_t submit_bio(struct bio *bio)
                        current->comm, task_pid_nr(current),
                                op_is_write(bio_op(bio)) ? "WRITE" : "READ",
                                (unsigned long long)bio->bi_iter.bi_sector,
-                               bdevname(bio->bi_bdev, b),
-                               count);
+                               bio_devname(bio, b), count);
                }
        }
 
@@ -2431,8 +2443,8 @@ void blk_account_io_done(struct request *req)
 
                part_stat_inc(cpu, part, ios[rw]);
                part_stat_add(cpu, part, ticks[rw], duration);
-               part_round_stats(cpu, part);
-               part_dec_in_flight(part, rw);
+               part_round_stats(req->q, cpu, part);
+               part_dec_in_flight(req->q, part, rw);
 
                hd_struct_put(part);
                part_stat_unlock();
@@ -2489,8 +2501,8 @@ void blk_account_io_start(struct request *rq, bool new_io)
                        part = &rq->rq_disk->part0;
                        hd_struct_get(part);
                }
-               part_round_stats(cpu, part);
-               part_inc_in_flight(part, rw);
+               part_round_stats(rq->q, cpu, part);
+               part_inc_in_flight(rq->q, part, rw);
                rq->part = part;
        }
 
@@ -2603,7 +2615,7 @@ struct request *blk_peek_request(struct request_queue *q)
 }
 EXPORT_SYMBOL(blk_peek_request);
 
-void blk_dequeue_request(struct request *rq)
+static void blk_dequeue_request(struct request *rq)
 {
        struct request_queue *q = rq->q;
 
@@ -2630,9 +2642,6 @@ void blk_dequeue_request(struct request *rq)
  * Description:
  *     Dequeue @req and start timeout timer on it.  This hands off the
  *     request to the driver.
- *
- *     Block internal functions which don't want to start timer should
- *     call blk_dequeue_request().
  */
 void blk_start_request(struct request *req)
 {
@@ -3035,8 +3044,8 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
        rq->__data_len = bio->bi_iter.bi_size;
        rq->bio = rq->biotail = bio;
 
-       if (bio->bi_bdev)
-               rq->rq_disk = bio->bi_bdev->bd_disk;
+       if (bio->bi_disk)
+               rq->rq_disk = bio->bi_disk;
 }
 
 #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE