block: remove the nr_sects field in struct hd_struct
authorChristoph Hellwig <hch@lst.de>
Thu, 26 Nov 2020 17:43:37 +0000 (18:43 +0100)
committerJens Axboe <axboe@kernel.dk>
Tue, 1 Dec 2020 21:53:40 +0000 (14:53 -0700)
Now that the hd_struct always has a block device attached to it, there is
no need for having two size field that just get out of sync.

Additionally the field in hd_struct did not use proper serialization,
possibly allowing for torn writes.  By only using the block_device field
this problem also gets fixed.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Acked-by: Coly Li <colyli@suse.de> [bcache]
Acked-by: Chao Yu <yuchao0@huawei.com> [f2fs]
Signed-off-by: Jens Axboe <axboe@kernel.dk>
16 files changed:
block/bio.c
block/blk-core.c
block/blk.h
block/genhd.c
block/partitions/core.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/xen-blkback/common.h
drivers/md/bcache/super.c
drivers/s390/block/dasd_ioctl.c
drivers/target/target_core_pscsi.c
fs/block_dev.c
fs/f2fs/super.c
fs/pstore/blk.c
include/linux/genhd.h
kernel/trace/blktrace.c

index fa01bef35bb1fe77b26d797cfdb76e7e04082ac3..669bb47a31988e970760845688e7d9c9f07c8847 100644 (file)
@@ -613,8 +613,8 @@ void guard_bio_eod(struct bio *bio)
        rcu_read_lock();
        part = __disk_get_part(bio->bi_disk, bio->bi_partno);
        if (part)
-               maxsector = part_nr_sects_read(part);
-       else
+               maxsector = bdev_nr_sectors(part->bdev);
+       else    
                maxsector = get_capacity(bio->bi_disk);
        rcu_read_unlock();
 
index 2db8bda43b6e6d8dd94d91526987b26e5954f290..988f45094a387ba374eddc858a1254a95d88f70d 100644 (file)
@@ -755,7 +755,7 @@ static inline int blk_partition_remap(struct bio *bio)
                goto out;
 
        if (bio_sectors(bio)) {
-               if (bio_check_eod(bio, part_nr_sects_read(p)))
+               if (bio_check_eod(bio, bdev_nr_sectors(p->bdev)))
                        goto out;
                bio->bi_iter.bi_sector += p->start_sect;
                trace_block_bio_remap(bio->bi_disk->queue, bio, part_devt(p),
index c4839abcfa27ebb69ca8e219a7c2c5f5beef6a9f..09cee7024fb43e814c7370ba861838b64ff44a09 100644 (file)
@@ -387,59 +387,6 @@ static inline void hd_free_part(struct hd_struct *part)
        percpu_ref_exit(&part->ref);
 }
 
-/*
- * Any access of part->nr_sects which is not protected by partition
- * bd_mutex or gendisk bdev bd_mutex, should be done using this
- * accessor function.
- *
- * Code written along the lines of i_size_read() and i_size_write().
- * CONFIG_PREEMPTION case optimizes the case of UP kernel with preemption
- * on.
- */
-static inline sector_t part_nr_sects_read(struct hd_struct *part)
-{
-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
-       sector_t nr_sects;
-       unsigned seq;
-       do {
-               seq = read_seqcount_begin(&part->nr_sects_seq);
-               nr_sects = part->nr_sects;
-       } while (read_seqcount_retry(&part->nr_sects_seq, seq));
-       return nr_sects;
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
-       sector_t nr_sects;
-
-       preempt_disable();
-       nr_sects = part->nr_sects;
-       preempt_enable();
-       return nr_sects;
-#else
-       return part->nr_sects;
-#endif
-}
-
-/*
- * Should be called with mutex lock held (typically bd_mutex) of partition
- * to provide mutual exlusion among writers otherwise seqcount might be
- * left in wrong state leaving the readers spinning infinitely.
- */
-static inline void part_nr_sects_write(struct hd_struct *part, sector_t size)
-{
-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
-       preempt_disable();
-       write_seqcount_begin(&part->nr_sects_seq);
-       part->nr_sects = size;
-       write_seqcount_end(&part->nr_sects_seq);
-       preempt_enable();
-#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPTION)
-       preempt_disable();
-       part->nr_sects = size;
-       preempt_enable();
-#else
-       part->nr_sects = size;
-#endif
-}
-
 int bio_add_hw_page(struct request_queue *q, struct bio *bio,
                struct page *page, unsigned int len, unsigned int offset,
                unsigned int max_sectors, bool *same_page);
index bf8fa82f135f4ec30f69cc5be472b6dfa7998f6c..c65f485b9db50d7b19243c73d3629e8575b4708f 100644 (file)
@@ -40,6 +40,16 @@ static void disk_add_events(struct gendisk *disk);
 static void disk_del_events(struct gendisk *disk);
 static void disk_release_events(struct gendisk *disk);
 
+void set_capacity(struct gendisk *disk, sector_t sectors)
+{
+       struct block_device *bdev = disk->part0.bdev;
+
+       spin_lock(&bdev->bd_size_lock);
+       i_size_write(bdev->bd_inode, (loff_t)sectors << SECTOR_SHIFT);
+       spin_unlock(&bdev->bd_size_lock);
+}
+EXPORT_SYMBOL(set_capacity);
+
 /*
  * Set disk capacity and notify if the size is not currently zero and will not
  * be set to zero.  Returns true if a uevent was sent, otherwise false.
@@ -47,18 +57,30 @@ static void disk_release_events(struct gendisk *disk);
 bool set_capacity_and_notify(struct gendisk *disk, sector_t size)
 {
        sector_t capacity = get_capacity(disk);
+       char *envp[] = { "RESIZE=1", NULL };
 
        set_capacity(disk, size);
-       revalidate_disk_size(disk, true);
 
-       if (capacity != size && capacity != 0 && size != 0) {
-               char *envp[] = { "RESIZE=1", NULL };
+       /*
+        * Only print a message and send a uevent if the gendisk is user visible
+        * and alive.  This avoids spamming the log and udev when setting the
+        * initial capacity during probing.
+        */
+       if (size == capacity ||
+           (disk->flags & (GENHD_FL_UP | GENHD_FL_HIDDEN)) != GENHD_FL_UP)
+               return false;
 
-               kobject_uevent_env(&disk_to_dev(disk)->kobj, KOBJ_CHANGE, envp);
-               return true;
-       }
+       pr_info("%s: detected capacity change from %lld to %lld\n",
+               disk->disk_name, size, capacity);
 
-       return false;
+       /*
+        * Historically we did not send a uevent for changes to/from an empty
+        * device.
+        */
+       if (!capacity || !size)
+               return false;
+       kobject_uevent_env(&disk_to_dev(disk)->kobj, KOBJ_CHANGE, envp);
+       return true;
 }
 EXPORT_SYMBOL_GPL(set_capacity_and_notify);
 
@@ -247,7 +269,7 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)
                part = rcu_dereference(ptbl->part[piter->idx]);
                if (!part)
                        continue;
-               if (!part_nr_sects_read(part) &&
+               if (!bdev_nr_sectors(part->bdev) &&
                    !(piter->flags & DISK_PITER_INCL_EMPTY) &&
                    !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 &&
                      piter->idx == 0))
@@ -284,7 +306,7 @@ EXPORT_SYMBOL_GPL(disk_part_iter_exit);
 static inline int sector_in_part(struct hd_struct *part, sector_t sector)
 {
        return part->start_sect <= sector &&
-               sector < part->start_sect + part_nr_sects_read(part);
+               sector < part->start_sect + bdev_nr_sectors(part->bdev);
 }
 
 /**
@@ -986,8 +1008,8 @@ void __init printk_all_partitions(void)
 
                        printk("%s%s %10llu %s %s", is_part0 ? "" : "  ",
                               bdevt_str(part_devt(part), devt_buf),
-                              (unsigned long long)part_nr_sects_read(part) >> 1
-                              disk_name(disk, part->partno, name_buf),
+                              bdev_nr_sectors(part->bdev) >> 1,
+                              disk_name(disk, part->partno, name_buf),
                               part->info ? part->info->uuid : "");
                        if (is_part0) {
                                if (dev->parent && dev->parent->driver)
@@ -1079,7 +1101,7 @@ static int show_partition(struct seq_file *seqf, void *v)
        while ((part = disk_part_iter_next(&piter)))
                seq_printf(seqf, "%4d  %7d %10llu %s\n",
                           MAJOR(part_devt(part)), MINOR(part_devt(part)),
-                          (unsigned long long)part_nr_sects_read(part) >> 1,
+                          bdev_nr_sectors(part->bdev) >> 1,
                           disk_name(sgp, part->partno, buf));
        disk_part_iter_exit(&piter);
 
@@ -1161,8 +1183,7 @@ ssize_t part_size_show(struct device *dev,
 {
        struct hd_struct *p = dev_to_part(dev);
 
-       return sprintf(buf, "%llu\n",
-               (unsigned long long)part_nr_sects_read(p));
+       return sprintf(buf, "%llu\n", bdev_nr_sectors(p->bdev));
 }
 
 ssize_t part_stat_show(struct device *dev,
@@ -1618,16 +1639,6 @@ struct gendisk *__alloc_disk_node(int minors, int node_id)
        ptbl = rcu_dereference_protected(disk->part_tbl, 1);
        rcu_assign_pointer(ptbl->part[0], &disk->part0);
 
-       /*
-        * set_capacity() and get_capacity() currently don't use
-        * seqcounter to read/update the part0->nr_sects. Still init
-        * the counter as we can read the sectors in IO submission
-        * patch using seqence counters.
-        *
-        * TODO: Ideally set_capacity() and get_capacity() should be
-        * converted to make use of bd_mutex and sequence counters.
-        */
-       hd_sects_seq_init(&disk->part0);
        if (hd_ref_init(&disk->part0))
                goto out_free_bdstats;
 
index 696bd9ff63c64a381999179feb9c2c61769a141a..bcfa8215bd5ef3754041e1a62bb6a756ea5f0998 100644 (file)
@@ -85,6 +85,13 @@ static int (*check_part[])(struct parsed_partitions *) = {
        NULL
 };
 
+static void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors)
+{
+       spin_lock(&bdev->bd_size_lock);
+       i_size_write(bdev->bd_inode, (loff_t)sectors << SECTOR_SHIFT);
+       spin_unlock(&bdev->bd_size_lock);
+}
+
 static struct parsed_partitions *allocate_partitions(struct gendisk *hd)
 {
        struct parsed_partitions *state;
@@ -295,7 +302,7 @@ static void hd_struct_free_work(struct work_struct *work)
        put_device(disk_to_dev(disk));
 
        part->start_sect = 0;
-       part->nr_sects = 0;
+       bdev_set_nr_sectors(part->bdev, 0);
        part_stat_set_all(part, 0);
        put_device(part_to_dev(part));
 }
@@ -412,11 +419,10 @@ static struct hd_struct *add_partition(struct gendisk *disk, int partno,
                goto out_free_stats;
        p->bdev = bdev;
 
-       hd_sects_seq_init(p);
        pdev = part_to_dev(p);
 
        p->start_sect = start;
-       p->nr_sects = len;
+       bdev_set_nr_sectors(bdev, len);
        p->partno = partno;
        p->policy = get_disk_ro(disk);
 
@@ -509,7 +515,7 @@ static bool partition_overlaps(struct gendisk *disk, sector_t start,
        disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY);
        while ((part = disk_part_iter_next(&piter))) {
                if (part->partno == skip_partno ||
-                   start >= part->start_sect + part->nr_sects ||
+                   start >= part->start_sect + bdev_nr_sectors(part->bdev) ||
                    start + length <= part->start_sect)
                        continue;
                overlap = true;
@@ -600,8 +606,7 @@ int bdev_resize_partition(struct block_device *bdev, int partno,
        if (partition_overlaps(bdev->bd_disk, start, length, partno))
                goto out_unlock;
 
-       part_nr_sects_write(part, length);
-       bd_set_nr_sectors(bdevp, length);
+       bdev_set_nr_sectors(bdevp, length);
 
        ret = 0;
 out_unlock:
index d643c67be6aceacea72de66df249b7a9011fa7ea..d2ce1ddc192d784f2f655cd32818faf2fd152ad7 100644 (file)
@@ -1241,7 +1241,6 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
        set_capacity(lo->lo_disk, 0);
        loop_sysfs_exit(lo);
        if (bdev) {
-               bd_set_nr_sectors(bdev, 0);
                /* let user-space know about this change */
                kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
        }
index 45b0423ef2c53dbd9dd307d7144c4a8c1417fa39..014683968ce1745520909a98eed8790730dd3dcc 100644 (file)
@@ -1132,7 +1132,7 @@ static void nbd_bdev_reset(struct block_device *bdev)
 {
        if (bdev->bd_openers > 1)
                return;
-       bd_set_nr_sectors(bdev, 0);
+       set_capacity(bdev->bd_disk, 0);
 }
 
 static void nbd_parse_flags(struct nbd_device *nbd)
index c6ea5d38c509a62788fd1dad811403ebb838eb31..0762db247b41b38b4060a5638978d89021652bb7 100644 (file)
@@ -358,9 +358,7 @@ struct pending_req {
 };
 
 
-#define vbd_sz(_v)     ((_v)->bdev->bd_part ? \
-                        (_v)->bdev->bd_part->nr_sects : \
-                         get_capacity((_v)->bdev->bd_disk))
+#define vbd_sz(_v)     bdev_nr_sectors((_v)->bdev)
 
 #define xen_blkif_get(_b) (atomic_inc(&(_b)->refcnt))
 #define xen_blkif_put(_b)                              \
index c55d3c58a7ef552347f8346aea4cd284f55093a9..04fa40868fbe10bb46431ae44228d5ea567c6f34 100644 (file)
@@ -1408,7 +1408,7 @@ static int cached_dev_init(struct cached_dev *dc, unsigned int block_size)
                        q->limits.raid_partial_stripes_expensive;
 
        ret = bcache_device_init(&dc->disk, block_size,
-                        dc->bdev->bd_part->nr_sects - dc->sb.data_offset,
+                        bdev_nr_sectors(dc->bdev) - dc->sb.data_offset,
                         dc->bdev, &bcache_cached_ops);
        if (ret)
                return ret;
index 3359559517bfcf5a072d60938bc1d63733b9a5f1..304eba1acf163c8a4986a9065525172fac6babc4 100644 (file)
@@ -54,8 +54,6 @@ dasd_ioctl_enable(struct block_device *bdev)
                return -ENODEV;
 
        dasd_enable_device(base);
-       /* Formatting the dasd device can change the capacity. */
-       bd_set_nr_sectors(bdev, get_capacity(base->block->gdp));
        dasd_put_device(base);
        return 0;
 }
@@ -88,7 +86,7 @@ dasd_ioctl_disable(struct block_device *bdev)
         * Set i_size to zero, since read, write, etc. check against this
         * value.
         */
-       bd_set_nr_sectors(bdev, 0);
+       set_capacity(bdev->bd_disk, 0);
        dasd_put_device(base);
        return 0;
 }
index 4e37fa9b409d52d6171ceec671af92e98f00e17f..7994f27e45271c486207e198dbba74fd6b2d9760 100644 (file)
@@ -1029,9 +1029,8 @@ static sector_t pscsi_get_blocks(struct se_device *dev)
 {
        struct pscsi_dev_virt *pdv = PSCSI_DEV(dev);
 
-       if (pdv->pdv_bd && pdv->pdv_bd->bd_part)
-               return pdv->pdv_bd->bd_part->nr_sects;
-
+       if (pdv->pdv_bd)
+               return bdev_nr_sectors(pdv->pdv_bd);
        return 0;
 }
 
index a5b6955a841f1892feeba195fe5e00dcdac97c8a..31ee5a857f7153132354817a921bfdf23afaf11d 100644 (file)
@@ -1208,70 +1208,6 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
 EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
 #endif
 
-/**
- * check_disk_size_change - checks for disk size change and adjusts bdev size.
- * @disk: struct gendisk to check
- * @bdev: struct bdev to adjust.
- * @verbose: if %true log a message about a size change if there is any
- *
- * This routine checks to see if the bdev size does not match the disk size
- * and adjusts it if it differs. When shrinking the bdev size, its all caches
- * are freed.
- */
-static void check_disk_size_change(struct gendisk *disk,
-               struct block_device *bdev, bool verbose)
-{
-       loff_t disk_size, bdev_size;
-
-       spin_lock(&bdev->bd_size_lock);
-       disk_size = (loff_t)get_capacity(disk) << 9;
-       bdev_size = i_size_read(bdev->bd_inode);
-       if (disk_size != bdev_size) {
-               if (verbose) {
-                       printk(KERN_INFO
-                              "%s: detected capacity change from %lld to %lld\n",
-                              disk->disk_name, bdev_size, disk_size);
-               }
-               i_size_write(bdev->bd_inode, disk_size);
-       }
-       spin_unlock(&bdev->bd_size_lock);
-}
-
-/**
- * revalidate_disk_size - checks for disk size change and adjusts bdev size.
- * @disk: struct gendisk to check
- * @verbose: if %true log a message about a size change if there is any
- *
- * This routine checks to see if the bdev size does not match the disk size
- * and adjusts it if it differs. When shrinking the bdev size, its all caches
- * are freed.
- */
-void revalidate_disk_size(struct gendisk *disk, bool verbose)
-{
-       struct block_device *bdev;
-
-       /*
-        * Hidden disks don't have associated bdev so there's no point in
-        * revalidating them.
-        */
-       if (disk->flags & GENHD_FL_HIDDEN)
-               return;
-
-       bdev = bdget_disk(disk, 0);
-       if (bdev) {
-               check_disk_size_change(disk, bdev, verbose);
-               bdput(bdev);
-       }
-}
-
-void bd_set_nr_sectors(struct block_device *bdev, sector_t sectors)
-{
-       spin_lock(&bdev->bd_size_lock);
-       i_size_write(bdev->bd_inode, (loff_t)sectors << SECTOR_SHIFT);
-       spin_unlock(&bdev->bd_size_lock);
-}
-EXPORT_SYMBOL(bd_set_nr_sectors);
-
 static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part);
 
 int bdev_disk_changed(struct block_device *bdev, bool invalidate)
@@ -1305,8 +1241,6 @@ rescan:
                        disk->fops->revalidate_disk(disk);
        }
 
-       check_disk_size_change(disk, bdev, !invalidate);
-
        if (get_capacity(disk)) {
                ret = blk_add_partitions(disk, bdev);
                if (ret == -EAGAIN)
@@ -1349,10 +1283,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode)
                        if (disk->fops->open)
                                ret = disk->fops->open(bdev, mode);
 
-                       if (!ret) {
-                               bd_set_nr_sectors(bdev, get_capacity(disk));
+                       if (!ret)
                                set_init_blocksize(bdev);
-                       }
 
                        /*
                         * If the device is invalidated, rescan partition
@@ -1381,13 +1313,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode)
 
                        bdev->bd_part = disk_get_part(disk, bdev->bd_partno);
                        if (!(disk->flags & GENHD_FL_UP) ||
-                           !bdev->bd_part || !bdev->bd_part->nr_sects) {
+                           !bdev->bd_part || !bdev_nr_sectors(bdev)) {
                                __blkdev_put(whole, mode, 1);
                                bdput(whole);
                                ret = -ENXIO;
                                goto out_clear;
                        }
-                       bd_set_nr_sectors(bdev, bdev->bd_part->nr_sects);
                        set_init_blocksize(bdev);
                }
 
index 00eff2f518079051d2cfef401e8d5267dbf43ab6..d4e7fab352bacb4101f6b7a83dc7d9ff5fada116 100644 (file)
@@ -3151,7 +3151,7 @@ static int f2fs_report_zone_cb(struct blk_zone *zone, unsigned int idx,
 static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
 {
        struct block_device *bdev = FDEV(devi).bdev;
-       sector_t nr_sectors = bdev->bd_part->nr_sects;
+       sector_t nr_sectors = bdev_nr_sectors(bdev);
        struct f2fs_report_zones_args rep_zone_arg;
        int ret;
 
index fcd5563dde063c62b16ebd68dcdea758f9d0ae88..777a26f7bbe2aac2db5cea4273b614f51ed9efe4 100644 (file)
@@ -245,7 +245,7 @@ static struct block_device *psblk_get_bdev(void *holder,
                        return bdev;
        }
 
-       nr_sects = part_nr_sects_read(bdev->bd_part);
+       nr_sects = bdev_nr_sectors(bdev);
        if (!nr_sects) {
                pr_err("not enough space for '%s'\n", blkdev);
                blkdev_put(bdev, mode);
index 6ba91ee54cb2f69b8b128eec900f0c7f8ce4e858..30d4785b7df8bb3feefbabdc22c0938cbe336bb8 100644 (file)
@@ -52,15 +52,6 @@ struct partition_meta_info {
 
 struct hd_struct {
        sector_t start_sect;
-       /*
-        * nr_sects is protected by sequence counter. One might extend a
-        * partition while IO is happening to it and update of nr_sects
-        * can be non-atomic on 32bit machines with 64bit sector_t.
-        */
-       sector_t nr_sects;
-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
-       seqcount_t nr_sects_seq;
-#endif
        unsigned long stamp;
        struct disk_stats __percpu *dkstats;
        struct percpu_ref ref;
@@ -254,13 +245,6 @@ static inline void disk_put_part(struct hd_struct *part)
                put_device(part_to_dev(part));
 }
 
-static inline void hd_sects_seq_init(struct hd_struct *p)
-{
-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
-       seqcount_init(&p->nr_sects_seq);
-#endif
-}
-
 /*
  * Smarter partition iterator without context limits.
  */
@@ -318,13 +302,15 @@ static inline sector_t get_start_sect(struct block_device *bdev)
 {
        return bdev->bd_part->start_sect;
 }
-static inline sector_t get_capacity(struct gendisk *disk)
+
+static inline sector_t bdev_nr_sectors(struct block_device *bdev)
 {
-       return disk->part0.nr_sects;
+       return i_size_read(bdev->bd_inode) >> 9;
 }
-static inline void set_capacity(struct gendisk *disk, sector_t size)
+
+static inline sector_t get_capacity(struct gendisk *disk)
 {
-       disk->part0.nr_sects = size;
+       return bdev_nr_sectors(disk->part0.bdev);
 }
 
 int bdev_disk_changed(struct block_device *bdev, bool invalidate);
@@ -358,10 +344,9 @@ int __register_blkdev(unsigned int major, const char *name,
        __register_blkdev(major, name, NULL)
 void unregister_blkdev(unsigned int major, const char *name);
 
-void revalidate_disk_size(struct gendisk *disk, bool verbose);
 bool bdev_check_media_change(struct block_device *bdev);
 int __invalidate_device(struct block_device *bdev, bool kill_dirty);
-void bd_set_nr_sectors(struct block_device *bdev, sector_t sectors);
+void set_capacity(struct gendisk *disk, sector_t size);
 
 /* for drivers/char/raw.c: */
 int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
index f1022945e3460b0bab7dfad8e2cba4333ffb7bc5..7076d588a50d699abbbaa3a1b2f43060f1b59ee5 100644 (file)
@@ -465,7 +465,7 @@ static void blk_trace_setup_lba(struct blk_trace *bt,
 
        if (part) {
                bt->start_lba = part->start_sect;
-               bt->end_lba = part->start_sect + part->nr_sects;
+               bt->end_lba = part->start_sect + bdev_nr_sectors(bdev);
        } else {
                bt->start_lba = 0;
                bt->end_lba = -1ULL;