.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * gendisk handling |
---|
3 | 4 | */ |
---|
4 | 5 | |
---|
5 | 6 | #include <linux/module.h> |
---|
| 7 | +#include <linux/ctype.h> |
---|
6 | 8 | #include <linux/fs.h> |
---|
7 | 9 | #include <linux/genhd.h> |
---|
8 | 10 | #include <linux/kdev_t.h> |
---|
.. | .. |
---|
25 | 27 | #include "blk.h" |
---|
26 | 28 | |
---|
27 | 29 | static DEFINE_MUTEX(block_class_lock); |
---|
28 | | -struct kobject *block_depr; |
---|
| 30 | +static struct kobject *block_depr; |
---|
29 | 31 | |
---|
30 | 32 | /* for extended dynamic devt allocation, currently only one major is used */ |
---|
31 | 33 | #define NR_EXT_DEVT (1 << MINORBITS) |
---|
.. | .. |
---|
36 | 38 | static DEFINE_SPINLOCK(ext_devt_lock); |
---|
37 | 39 | static DEFINE_IDR(ext_devt_idr); |
---|
38 | 40 | |
---|
39 | | -static const struct device_type disk_type; |
---|
40 | | - |
---|
41 | 41 | static void disk_check_events(struct disk_events *ev, |
---|
42 | 42 | unsigned int *clearing_ptr); |
---|
43 | 43 | static void disk_alloc_events(struct gendisk *disk); |
---|
.. | .. |
---|
45 | 45 | static void disk_del_events(struct gendisk *disk); |
---|
46 | 46 | static void disk_release_events(struct gendisk *disk); |
---|
47 | 47 | |
---|
48 | | -void part_inc_in_flight(struct request_queue *q, struct hd_struct *part, int rw) |
---|
| 48 | +/* |
---|
| 49 | + * Set disk capacity and notify if the size is not currently |
---|
| 50 | + * zero and will not be set to zero |
---|
| 51 | + */ |
---|
| 52 | +bool set_capacity_revalidate_and_notify(struct gendisk *disk, sector_t size, |
---|
| 53 | + bool update_bdev) |
---|
49 | 54 | { |
---|
50 | | - if (q->mq_ops) |
---|
51 | | - return; |
---|
| 55 | + sector_t capacity = get_capacity(disk); |
---|
52 | 56 | |
---|
53 | | - atomic_inc(&part->in_flight[rw]); |
---|
54 | | - if (part->partno) |
---|
55 | | - atomic_inc(&part_to_disk(part)->part0.in_flight[rw]); |
---|
56 | | -} |
---|
| 57 | + set_capacity(disk, size); |
---|
| 58 | + if (update_bdev) |
---|
| 59 | + revalidate_disk_size(disk, true); |
---|
57 | 60 | |
---|
58 | | -void part_dec_in_flight(struct request_queue *q, struct hd_struct *part, int rw) |
---|
59 | | -{ |
---|
60 | | - if (q->mq_ops) |
---|
61 | | - return; |
---|
| 61 | + if (capacity != size && capacity != 0 && size != 0) { |
---|
| 62 | + char *envp[] = { "RESIZE=1", NULL }; |
---|
62 | 63 | |
---|
63 | | - atomic_dec(&part->in_flight[rw]); |
---|
64 | | - if (part->partno) |
---|
65 | | - atomic_dec(&part_to_disk(part)->part0.in_flight[rw]); |
---|
66 | | -} |
---|
67 | | - |
---|
68 | | -void part_in_flight(struct request_queue *q, struct hd_struct *part, |
---|
69 | | - unsigned int inflight[2]) |
---|
70 | | -{ |
---|
71 | | - if (q->mq_ops) { |
---|
72 | | - blk_mq_in_flight(q, part, inflight); |
---|
73 | | - return; |
---|
| 64 | + kobject_uevent_env(&disk_to_dev(disk)->kobj, KOBJ_CHANGE, envp); |
---|
| 65 | + return true; |
---|
74 | 66 | } |
---|
75 | 67 | |
---|
76 | | - inflight[0] = atomic_read(&part->in_flight[0]) + |
---|
77 | | - atomic_read(&part->in_flight[1]); |
---|
78 | | - if (part->partno) { |
---|
79 | | - part = &part_to_disk(part)->part0; |
---|
80 | | - inflight[1] = atomic_read(&part->in_flight[0]) + |
---|
81 | | - atomic_read(&part->in_flight[1]); |
---|
| 68 | + return false; |
---|
| 69 | +} |
---|
| 70 | + |
---|
| 71 | +EXPORT_SYMBOL_GPL(set_capacity_revalidate_and_notify); |
---|
| 72 | + |
---|
| 73 | +/* |
---|
| 74 | + * Format the device name of the indicated disk into the supplied buffer and |
---|
| 75 | + * return a pointer to that same buffer for convenience. |
---|
| 76 | + */ |
---|
| 77 | +char *disk_name(struct gendisk *hd, int partno, char *buf) |
---|
| 78 | +{ |
---|
| 79 | + if (!partno) |
---|
| 80 | + snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name); |
---|
| 81 | + else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) |
---|
| 82 | + snprintf(buf, BDEVNAME_SIZE, "%sp%d", hd->disk_name, partno); |
---|
| 83 | + else |
---|
| 84 | + snprintf(buf, BDEVNAME_SIZE, "%s%d", hd->disk_name, partno); |
---|
| 85 | + |
---|
| 86 | + return buf; |
---|
| 87 | +} |
---|
| 88 | + |
---|
| 89 | +const char *bdevname(struct block_device *bdev, char *buf) |
---|
| 90 | +{ |
---|
| 91 | + return disk_name(bdev->bd_disk, bdev->bd_partno, buf); |
---|
| 92 | +} |
---|
| 93 | +EXPORT_SYMBOL(bdevname); |
---|
| 94 | + |
---|
| 95 | +static void part_stat_read_all(struct hd_struct *part, struct disk_stats *stat) |
---|
| 96 | +{ |
---|
| 97 | + int cpu; |
---|
| 98 | + |
---|
| 99 | + memset(stat, 0, sizeof(struct disk_stats)); |
---|
| 100 | + for_each_possible_cpu(cpu) { |
---|
| 101 | + struct disk_stats *ptr = per_cpu_ptr(part->dkstats, cpu); |
---|
| 102 | + int group; |
---|
| 103 | + |
---|
| 104 | + for (group = 0; group < NR_STAT_GROUPS; group++) { |
---|
| 105 | + stat->nsecs[group] += ptr->nsecs[group]; |
---|
| 106 | + stat->sectors[group] += ptr->sectors[group]; |
---|
| 107 | + stat->ios[group] += ptr->ios[group]; |
---|
| 108 | + stat->merges[group] += ptr->merges[group]; |
---|
| 109 | + } |
---|
| 110 | + |
---|
| 111 | + stat->io_ticks += ptr->io_ticks; |
---|
82 | 112 | } |
---|
83 | 113 | } |
---|
84 | 114 | |
---|
85 | | -void part_in_flight_rw(struct request_queue *q, struct hd_struct *part, |
---|
86 | | - unsigned int inflight[2]) |
---|
| 115 | +static unsigned int part_in_flight(struct hd_struct *part) |
---|
87 | 116 | { |
---|
88 | | - if (q->mq_ops) { |
---|
89 | | - blk_mq_in_flight_rw(q, part, inflight); |
---|
90 | | - return; |
---|
91 | | - } |
---|
| 117 | + unsigned int inflight = 0; |
---|
| 118 | + int cpu; |
---|
92 | 119 | |
---|
93 | | - inflight[0] = atomic_read(&part->in_flight[0]); |
---|
94 | | - inflight[1] = atomic_read(&part->in_flight[1]); |
---|
| 120 | + for_each_possible_cpu(cpu) { |
---|
| 121 | + inflight += part_stat_local_read_cpu(part, in_flight[0], cpu) + |
---|
| 122 | + part_stat_local_read_cpu(part, in_flight[1], cpu); |
---|
| 123 | + } |
---|
| 124 | + if ((int)inflight < 0) |
---|
| 125 | + inflight = 0; |
---|
| 126 | + |
---|
| 127 | + return inflight; |
---|
| 128 | +} |
---|
| 129 | + |
---|
| 130 | +static void part_in_flight_rw(struct hd_struct *part, unsigned int inflight[2]) |
---|
| 131 | +{ |
---|
| 132 | + int cpu; |
---|
| 133 | + |
---|
| 134 | + inflight[0] = 0; |
---|
| 135 | + inflight[1] = 0; |
---|
| 136 | + for_each_possible_cpu(cpu) { |
---|
| 137 | + inflight[0] += part_stat_local_read_cpu(part, in_flight[0], cpu); |
---|
| 138 | + inflight[1] += part_stat_local_read_cpu(part, in_flight[1], cpu); |
---|
| 139 | + } |
---|
| 140 | + if ((int)inflight[0] < 0) |
---|
| 141 | + inflight[0] = 0; |
---|
| 142 | + if ((int)inflight[1] < 0) |
---|
| 143 | + inflight[1] = 0; |
---|
95 | 144 | } |
---|
96 | 145 | |
---|
97 | 146 | struct hd_struct *__disk_get_part(struct gendisk *disk, int partno) |
---|
.. | .. |
---|
129 | 178 | |
---|
130 | 179 | return part; |
---|
131 | 180 | } |
---|
132 | | -EXPORT_SYMBOL_GPL(disk_get_part); |
---|
133 | 181 | |
---|
134 | 182 | /** |
---|
135 | 183 | * disk_part_iter_init - initialize partition iterator |
---|
.. | .. |
---|
260 | 308 | * primarily used for stats accounting. |
---|
261 | 309 | * |
---|
262 | 310 | * CONTEXT: |
---|
263 | | - * RCU read locked. The returned partition pointer is valid only |
---|
264 | | - * while preemption is disabled. |
---|
| 311 | + * RCU read locked. The returned partition pointer is always valid |
---|
| 312 | + * because its refcount is grabbed except for part0, which lifetime |
---|
| 313 | + * is same with the disk. |
---|
265 | 314 | * |
---|
266 | 315 | * RETURNS: |
---|
267 | 316 | * Found partition on success, part0 is returned if no partition matches |
---|
| 317 | + * or the matched partition is being deleted. |
---|
268 | 318 | */ |
---|
269 | 319 | struct hd_struct *disk_map_sector_rcu(struct gendisk *disk, sector_t sector) |
---|
270 | 320 | { |
---|
.. | .. |
---|
272 | 322 | struct hd_struct *part; |
---|
273 | 323 | int i; |
---|
274 | 324 | |
---|
| 325 | + rcu_read_lock(); |
---|
275 | 326 | ptbl = rcu_dereference(disk->part_tbl); |
---|
276 | 327 | |
---|
277 | 328 | part = rcu_dereference(ptbl->last_lookup); |
---|
278 | | - if (part && sector_in_part(part, sector)) |
---|
279 | | - return part; |
---|
| 329 | + if (part && sector_in_part(part, sector) && hd_struct_try_get(part)) |
---|
| 330 | + goto out_unlock; |
---|
280 | 331 | |
---|
281 | 332 | for (i = 1; i < ptbl->len; i++) { |
---|
282 | 333 | part = rcu_dereference(ptbl->part[i]); |
---|
283 | 334 | |
---|
284 | 335 | if (part && sector_in_part(part, sector)) { |
---|
| 336 | + /* |
---|
| 337 | + * only live partition can be cached for lookup, |
---|
| 338 | + * so use-after-free on cached & deleting partition |
---|
| 339 | + * can be avoided |
---|
| 340 | + */ |
---|
| 341 | + if (!hd_struct_try_get(part)) |
---|
| 342 | + break; |
---|
285 | 343 | rcu_assign_pointer(ptbl->last_lookup, part); |
---|
286 | | - return part; |
---|
| 344 | + goto out_unlock; |
---|
287 | 345 | } |
---|
288 | 346 | } |
---|
289 | | - return &disk->part0; |
---|
| 347 | + |
---|
| 348 | + part = &disk->part0; |
---|
| 349 | +out_unlock: |
---|
| 350 | + rcu_read_unlock(); |
---|
| 351 | + return part; |
---|
290 | 352 | } |
---|
291 | | -EXPORT_SYMBOL_GPL(disk_map_sector_rcu); |
---|
| 353 | + |
---|
| 354 | +/** |
---|
| 355 | + * disk_has_partitions |
---|
| 356 | + * @disk: gendisk of interest |
---|
| 357 | + * |
---|
| 358 | + * Walk through the partition table and check if valid partition exists. |
---|
| 359 | + * |
---|
| 360 | + * CONTEXT: |
---|
| 361 | + * Don't care. |
---|
| 362 | + * |
---|
| 363 | + * RETURNS: |
---|
| 364 | + * True if the gendisk has at least one valid non-zero size partition. |
---|
| 365 | + * Otherwise false. |
---|
| 366 | + */ |
---|
| 367 | +bool disk_has_partitions(struct gendisk *disk) |
---|
| 368 | +{ |
---|
| 369 | + struct disk_part_tbl *ptbl; |
---|
| 370 | + int i; |
---|
| 371 | + bool ret = false; |
---|
| 372 | + |
---|
| 373 | + rcu_read_lock(); |
---|
| 374 | + ptbl = rcu_dereference(disk->part_tbl); |
---|
| 375 | + |
---|
| 376 | + /* Iterate partitions skipping the whole device at index 0 */ |
---|
| 377 | + for (i = 1; i < ptbl->len; i++) { |
---|
| 378 | + if (rcu_dereference(ptbl->part[i])) { |
---|
| 379 | + ret = true; |
---|
| 380 | + break; |
---|
| 381 | + } |
---|
| 382 | + } |
---|
| 383 | + |
---|
| 384 | + rcu_read_unlock(); |
---|
| 385 | + |
---|
| 386 | + return ret; |
---|
| 387 | +} |
---|
| 388 | +EXPORT_SYMBOL_GPL(disk_has_partitions); |
---|
292 | 389 | |
---|
293 | 390 | /* |
---|
294 | 391 | * Can be deleted altogether. Later. |
---|
.. | .. |
---|
355 | 452 | } |
---|
356 | 453 | |
---|
357 | 454 | if (index == 0) { |
---|
358 | | - printk("register_blkdev: failed to get major for %s\n", |
---|
359 | | - name); |
---|
| 455 | + printk("%s: failed to get major for %s\n", |
---|
| 456 | + __func__, name); |
---|
360 | 457 | ret = -EBUSY; |
---|
361 | 458 | goto out; |
---|
362 | 459 | } |
---|
.. | .. |
---|
365 | 462 | } |
---|
366 | 463 | |
---|
367 | 464 | if (major >= BLKDEV_MAJOR_MAX) { |
---|
368 | | - pr_err("register_blkdev: major requested (%u) is greater than the maximum (%u) for %s\n", |
---|
369 | | - major, BLKDEV_MAJOR_MAX-1, name); |
---|
| 465 | + pr_err("%s: major requested (%u) is greater than the maximum (%u) for %s\n", |
---|
| 466 | + __func__, major, BLKDEV_MAJOR_MAX-1, name); |
---|
370 | 467 | |
---|
371 | 468 | ret = -EINVAL; |
---|
372 | 469 | goto out; |
---|
.. | .. |
---|
521 | 618 | } |
---|
522 | 619 | } |
---|
523 | 620 | |
---|
524 | | -/** |
---|
525 | | - * We invalidate devt by assigning NULL pointer for devt in idr. |
---|
| 621 | +/* |
---|
| 622 | + * We invalidate devt by assigning NULL pointer for devt in idr. |
---|
526 | 623 | */ |
---|
527 | 624 | void blk_invalidate_devt(dev_t devt) |
---|
528 | 625 | { |
---|
.. | .. |
---|
582 | 679 | return 0; |
---|
583 | 680 | } |
---|
584 | 681 | |
---|
585 | | -static void register_disk(struct device *parent, struct gendisk *disk) |
---|
| 682 | +static void disk_scan_partitions(struct gendisk *disk) |
---|
| 683 | +{ |
---|
| 684 | + struct block_device *bdev; |
---|
| 685 | + |
---|
| 686 | + if (!get_capacity(disk) || !disk_part_scan_enabled(disk)) |
---|
| 687 | + return; |
---|
| 688 | + |
---|
| 689 | + set_bit(GD_NEED_PART_SCAN, &disk->state); |
---|
| 690 | + bdev = blkdev_get_by_dev(disk_devt(disk), FMODE_READ, NULL); |
---|
| 691 | + if (!IS_ERR(bdev)) |
---|
| 692 | + blkdev_put(bdev, FMODE_READ); |
---|
| 693 | +} |
---|
| 694 | + |
---|
| 695 | +static void register_disk(struct device *parent, struct gendisk *disk, |
---|
| 696 | + const struct attribute_group **groups) |
---|
586 | 697 | { |
---|
587 | 698 | struct device *ddev = disk_to_dev(disk); |
---|
588 | | - struct block_device *bdev; |
---|
589 | 699 | struct disk_part_iter piter; |
---|
590 | 700 | struct hd_struct *part; |
---|
591 | 701 | int err; |
---|
.. | .. |
---|
597 | 707 | /* delay uevents, until we scanned partition table */ |
---|
598 | 708 | dev_set_uevent_suppress(ddev, 1); |
---|
599 | 709 | |
---|
| 710 | + if (groups) { |
---|
| 711 | + WARN_ON(ddev->groups); |
---|
| 712 | + ddev->groups = groups; |
---|
| 713 | + } |
---|
600 | 714 | if (device_add(ddev)) |
---|
601 | 715 | return; |
---|
602 | 716 | if (!sysfs_deprecated) { |
---|
.. | .. |
---|
621 | 735 | if (disk->flags & GENHD_FL_HIDDEN) |
---|
622 | 736 | return; |
---|
623 | 737 | |
---|
624 | | - /* No minors to use for partitions */ |
---|
625 | | - if (!disk_part_scan_enabled(disk)) |
---|
626 | | - goto exit; |
---|
| 738 | + disk_scan_partitions(disk); |
---|
627 | 739 | |
---|
628 | | - /* No such device (e.g., media were just removed) */ |
---|
629 | | - if (!get_capacity(disk)) |
---|
630 | | - goto exit; |
---|
631 | | - |
---|
632 | | - bdev = bdget_disk(disk, 0); |
---|
633 | | - if (!bdev) |
---|
634 | | - goto exit; |
---|
635 | | - |
---|
636 | | - bdev->bd_invalidated = 1; |
---|
637 | | - err = blkdev_get(bdev, FMODE_READ, NULL); |
---|
638 | | - if (err < 0) |
---|
639 | | - goto exit; |
---|
640 | | - blkdev_put(bdev, FMODE_READ); |
---|
641 | | - |
---|
642 | | -exit: |
---|
643 | 740 | /* announce disk after possible partitions are created */ |
---|
644 | 741 | dev_set_uevent_suppress(ddev, 0); |
---|
645 | 742 | kobject_uevent(&ddev->kobj, KOBJ_ADD); |
---|
.. | .. |
---|
662 | 759 | * __device_add_disk - add disk information to kernel list |
---|
663 | 760 | * @parent: parent device for the disk |
---|
664 | 761 | * @disk: per-device partitioning information |
---|
| 762 | + * @groups: Additional per-device sysfs groups |
---|
665 | 763 | * @register_queue: register the queue if set to true |
---|
666 | 764 | * |
---|
667 | 765 | * This function registers the partitioning information in @disk |
---|
.. | .. |
---|
670 | 768 | * FIXME: error handling |
---|
671 | 769 | */ |
---|
672 | 770 | static void __device_add_disk(struct device *parent, struct gendisk *disk, |
---|
| 771 | + const struct attribute_group **groups, |
---|
673 | 772 | bool register_queue) |
---|
674 | 773 | { |
---|
675 | 774 | dev_t devt; |
---|
676 | 775 | int retval; |
---|
| 776 | + |
---|
| 777 | + /* |
---|
| 778 | + * The disk queue should now be all set with enough information about |
---|
| 779 | + * the device for the elevator code to pick an adequate default |
---|
| 780 | + * elevator if one is needed, that is, for devices requesting queue |
---|
| 781 | + * registration. |
---|
| 782 | + */ |
---|
| 783 | + if (register_queue) |
---|
| 784 | + elevator_init_mq(disk->queue); |
---|
677 | 785 | |
---|
678 | 786 | /* minors == 0 indicates to use ext devt from part0 and should |
---|
679 | 787 | * be accompanied with EXT_DEVT flag. Make sure all |
---|
.. | .. |
---|
703 | 811 | disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; |
---|
704 | 812 | disk->flags |= GENHD_FL_NO_PART_SCAN; |
---|
705 | 813 | } else { |
---|
| 814 | + struct backing_dev_info *bdi = disk->queue->backing_dev_info; |
---|
| 815 | + struct device *dev = disk_to_dev(disk); |
---|
706 | 816 | int ret; |
---|
707 | 817 | |
---|
708 | 818 | /* Register BDI before referencing it from bdev */ |
---|
709 | | - disk_to_dev(disk)->devt = devt; |
---|
710 | | - ret = bdi_register_owner(disk->queue->backing_dev_info, |
---|
711 | | - disk_to_dev(disk)); |
---|
| 819 | + dev->devt = devt; |
---|
| 820 | + ret = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt)); |
---|
712 | 821 | WARN_ON(ret); |
---|
| 822 | + bdi_set_owner(bdi, dev); |
---|
713 | 823 | blk_register_region(disk_devt(disk), disk->minors, NULL, |
---|
714 | 824 | exact_match, exact_lock, disk); |
---|
715 | 825 | } |
---|
716 | | - register_disk(parent, disk); |
---|
| 826 | + register_disk(parent, disk, groups); |
---|
717 | 827 | if (register_queue) |
---|
718 | 828 | blk_register_queue(disk); |
---|
719 | 829 | |
---|
.. | .. |
---|
727 | 837 | blk_integrity_add(disk); |
---|
728 | 838 | } |
---|
729 | 839 | |
---|
730 | | -void device_add_disk(struct device *parent, struct gendisk *disk) |
---|
| 840 | +void device_add_disk(struct device *parent, struct gendisk *disk, |
---|
| 841 | + const struct attribute_group **groups) |
---|
| 842 | + |
---|
731 | 843 | { |
---|
732 | | - __device_add_disk(parent, disk, true); |
---|
| 844 | + __device_add_disk(parent, disk, groups, true); |
---|
733 | 845 | } |
---|
734 | 846 | EXPORT_SYMBOL(device_add_disk); |
---|
735 | 847 | |
---|
736 | 848 | void device_add_disk_no_queue_reg(struct device *parent, struct gendisk *disk) |
---|
737 | 849 | { |
---|
738 | | - __device_add_disk(parent, disk, false); |
---|
| 850 | + __device_add_disk(parent, disk, NULL, false); |
---|
739 | 851 | } |
---|
740 | 852 | EXPORT_SYMBOL(device_add_disk_no_queue_reg); |
---|
741 | 853 | |
---|
| 854 | +static void invalidate_partition(struct gendisk *disk, int partno) |
---|
| 855 | +{ |
---|
| 856 | + struct block_device *bdev; |
---|
| 857 | + |
---|
| 858 | + bdev = bdget_disk(disk, partno); |
---|
| 859 | + if (!bdev) |
---|
| 860 | + return; |
---|
| 861 | + |
---|
| 862 | + fsync_bdev(bdev); |
---|
| 863 | + __invalidate_device(bdev, true); |
---|
| 864 | + |
---|
| 865 | + /* |
---|
| 866 | + * Unhash the bdev inode for this device so that it gets evicted as soon |
---|
| 867 | + * as last inode reference is dropped. |
---|
| 868 | + */ |
---|
| 869 | + remove_inode_hash(bdev->bd_inode); |
---|
| 870 | + bdput(bdev); |
---|
| 871 | +} |
---|
| 872 | + |
---|
| 873 | +/** |
---|
| 874 | + * del_gendisk - remove the gendisk |
---|
| 875 | + * @disk: the struct gendisk to remove |
---|
| 876 | + * |
---|
| 877 | + * Removes the gendisk and all its associated resources. This deletes the |
---|
| 878 | + * partitions associated with the gendisk, and unregisters the associated |
---|
| 879 | + * request_queue. |
---|
| 880 | + * |
---|
| 881 | + * This is the counter to the respective __device_add_disk() call. |
---|
| 882 | + * |
---|
| 883 | + * The final removal of the struct gendisk happens when its refcount reaches 0 |
---|
| 884 | + * with put_disk(), which should be called after del_gendisk(), if |
---|
| 885 | + * __device_add_disk() was used. |
---|
| 886 | + * |
---|
| 887 | + * Drivers exist which depend on the release of the gendisk to be synchronous, |
---|
| 888 | + * it should not be deferred. |
---|
| 889 | + * |
---|
| 890 | + * Context: can sleep |
---|
| 891 | + */ |
---|
742 | 892 | void del_gendisk(struct gendisk *disk) |
---|
743 | 893 | { |
---|
744 | 894 | struct disk_part_iter piter; |
---|
745 | 895 | struct hd_struct *part; |
---|
| 896 | + |
---|
| 897 | + might_sleep(); |
---|
746 | 898 | |
---|
747 | 899 | blk_integrity_del(disk); |
---|
748 | 900 | disk_del_events(disk); |
---|
.. | .. |
---|
757 | 909 | DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE); |
---|
758 | 910 | while ((part = disk_part_iter_next(&piter))) { |
---|
759 | 911 | invalidate_partition(disk, part->partno); |
---|
760 | | - bdev_unhash_inode(part_devt(part)); |
---|
761 | | - delete_partition(disk, part->partno); |
---|
| 912 | + delete_partition(part); |
---|
762 | 913 | } |
---|
763 | 914 | disk_part_iter_exit(&piter); |
---|
764 | 915 | |
---|
765 | 916 | invalidate_partition(disk, 0); |
---|
766 | | - bdev_unhash_inode(disk_devt(disk)); |
---|
767 | 917 | set_capacity(disk, 0); |
---|
768 | 918 | disk->flags &= ~GENHD_FL_UP; |
---|
769 | 919 | up_write(&disk->lookup_sem); |
---|
.. | .. |
---|
836 | 986 | * |
---|
837 | 987 | * This function gets the structure containing partitioning |
---|
838 | 988 | * information for the given device @devt. |
---|
| 989 | + * |
---|
| 990 | + * Context: can sleep |
---|
839 | 991 | */ |
---|
840 | 992 | struct gendisk *get_gendisk(dev_t devt, int *partno) |
---|
841 | 993 | { |
---|
842 | 994 | struct gendisk *disk = NULL; |
---|
| 995 | + |
---|
| 996 | + might_sleep(); |
---|
843 | 997 | |
---|
844 | 998 | if (MAJOR(devt) != BLOCK_EXT_MAJOR) { |
---|
845 | 999 | struct kobject *kobj; |
---|
.. | .. |
---|
877 | 1031 | } |
---|
878 | 1032 | return disk; |
---|
879 | 1033 | } |
---|
880 | | -EXPORT_SYMBOL(get_gendisk); |
---|
881 | 1034 | |
---|
882 | 1035 | /** |
---|
883 | 1036 | * bdget_disk - do bdget() by gendisk and partition number |
---|
.. | .. |
---|
899 | 1052 | |
---|
900 | 1053 | part = disk_get_part(disk, partno); |
---|
901 | 1054 | if (part) |
---|
902 | | - bdev = bdget(part_devt(part)); |
---|
| 1055 | + bdev = bdget_part(part); |
---|
903 | 1056 | disk_put_part(part); |
---|
904 | 1057 | |
---|
905 | 1058 | return bdev; |
---|
.. | .. |
---|
1123 | 1276 | return sprintf(buf, "%d\n", get_disk_ro(disk) ? 1 : 0); |
---|
1124 | 1277 | } |
---|
1125 | 1278 | |
---|
| 1279 | +ssize_t part_size_show(struct device *dev, |
---|
| 1280 | + struct device_attribute *attr, char *buf) |
---|
| 1281 | +{ |
---|
| 1282 | + struct hd_struct *p = dev_to_part(dev); |
---|
| 1283 | + |
---|
| 1284 | + return sprintf(buf, "%llu\n", |
---|
| 1285 | + (unsigned long long)part_nr_sects_read(p)); |
---|
| 1286 | +} |
---|
| 1287 | + |
---|
| 1288 | +ssize_t part_stat_show(struct device *dev, |
---|
| 1289 | + struct device_attribute *attr, char *buf) |
---|
| 1290 | +{ |
---|
| 1291 | + struct hd_struct *p = dev_to_part(dev); |
---|
| 1292 | + struct request_queue *q = part_to_disk(p)->queue; |
---|
| 1293 | + struct disk_stats stat; |
---|
| 1294 | + unsigned int inflight; |
---|
| 1295 | + |
---|
| 1296 | + part_stat_read_all(p, &stat); |
---|
| 1297 | + if (queue_is_mq(q)) |
---|
| 1298 | + inflight = blk_mq_in_flight(q, p); |
---|
| 1299 | + else |
---|
| 1300 | + inflight = part_in_flight(p); |
---|
| 1301 | + |
---|
| 1302 | + return sprintf(buf, |
---|
| 1303 | + "%8lu %8lu %8llu %8u " |
---|
| 1304 | + "%8lu %8lu %8llu %8u " |
---|
| 1305 | + "%8u %8u %8u " |
---|
| 1306 | + "%8lu %8lu %8llu %8u " |
---|
| 1307 | + "%8lu %8u" |
---|
| 1308 | + "\n", |
---|
| 1309 | + stat.ios[STAT_READ], |
---|
| 1310 | + stat.merges[STAT_READ], |
---|
| 1311 | + (unsigned long long)stat.sectors[STAT_READ], |
---|
| 1312 | + (unsigned int)div_u64(stat.nsecs[STAT_READ], NSEC_PER_MSEC), |
---|
| 1313 | + stat.ios[STAT_WRITE], |
---|
| 1314 | + stat.merges[STAT_WRITE], |
---|
| 1315 | + (unsigned long long)stat.sectors[STAT_WRITE], |
---|
| 1316 | + (unsigned int)div_u64(stat.nsecs[STAT_WRITE], NSEC_PER_MSEC), |
---|
| 1317 | + inflight, |
---|
| 1318 | + jiffies_to_msecs(stat.io_ticks), |
---|
| 1319 | + (unsigned int)div_u64(stat.nsecs[STAT_READ] + |
---|
| 1320 | + stat.nsecs[STAT_WRITE] + |
---|
| 1321 | + stat.nsecs[STAT_DISCARD] + |
---|
| 1322 | + stat.nsecs[STAT_FLUSH], |
---|
| 1323 | + NSEC_PER_MSEC), |
---|
| 1324 | + stat.ios[STAT_DISCARD], |
---|
| 1325 | + stat.merges[STAT_DISCARD], |
---|
| 1326 | + (unsigned long long)stat.sectors[STAT_DISCARD], |
---|
| 1327 | + (unsigned int)div_u64(stat.nsecs[STAT_DISCARD], NSEC_PER_MSEC), |
---|
| 1328 | + stat.ios[STAT_FLUSH], |
---|
| 1329 | + (unsigned int)div_u64(stat.nsecs[STAT_FLUSH], NSEC_PER_MSEC)); |
---|
| 1330 | +} |
---|
| 1331 | + |
---|
| 1332 | +ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr, |
---|
| 1333 | + char *buf) |
---|
| 1334 | +{ |
---|
| 1335 | + struct hd_struct *p = dev_to_part(dev); |
---|
| 1336 | + struct request_queue *q = part_to_disk(p)->queue; |
---|
| 1337 | + unsigned int inflight[2]; |
---|
| 1338 | + |
---|
| 1339 | + if (queue_is_mq(q)) |
---|
| 1340 | + blk_mq_in_flight_rw(q, p, inflight); |
---|
| 1341 | + else |
---|
| 1342 | + part_in_flight_rw(p, inflight); |
---|
| 1343 | + |
---|
| 1344 | + return sprintf(buf, "%8u %8u\n", inflight[0], inflight[1]); |
---|
| 1345 | +} |
---|
| 1346 | + |
---|
1126 | 1347 | static ssize_t disk_capability_show(struct device *dev, |
---|
1127 | 1348 | struct device_attribute *attr, char *buf) |
---|
1128 | 1349 | { |
---|
.. | .. |
---|
1161 | 1382 | static DEVICE_ATTR(stat, 0444, part_stat_show, NULL); |
---|
1162 | 1383 | static DEVICE_ATTR(inflight, 0444, part_inflight_show, NULL); |
---|
1163 | 1384 | static DEVICE_ATTR(badblocks, 0644, disk_badblocks_show, disk_badblocks_store); |
---|
| 1385 | + |
---|
1164 | 1386 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
---|
| 1387 | +ssize_t part_fail_show(struct device *dev, |
---|
| 1388 | + struct device_attribute *attr, char *buf) |
---|
| 1389 | +{ |
---|
| 1390 | + struct hd_struct *p = dev_to_part(dev); |
---|
| 1391 | + |
---|
| 1392 | + return sprintf(buf, "%d\n", p->make_it_fail); |
---|
| 1393 | +} |
---|
| 1394 | + |
---|
| 1395 | +ssize_t part_fail_store(struct device *dev, |
---|
| 1396 | + struct device_attribute *attr, |
---|
| 1397 | + const char *buf, size_t count) |
---|
| 1398 | +{ |
---|
| 1399 | + struct hd_struct *p = dev_to_part(dev); |
---|
| 1400 | + int i; |
---|
| 1401 | + |
---|
| 1402 | + if (count > 0 && sscanf(buf, "%d", &i) > 0) |
---|
| 1403 | + p->make_it_fail = (i == 0) ? 0 : 1; |
---|
| 1404 | + |
---|
| 1405 | + return count; |
---|
| 1406 | +} |
---|
| 1407 | + |
---|
1165 | 1408 | static struct device_attribute dev_attr_fail = |
---|
1166 | 1409 | __ATTR(make-it-fail, 0644, part_fail_show, part_fail_store); |
---|
1167 | | -#endif |
---|
| 1410 | +#endif /* CONFIG_FAIL_MAKE_REQUEST */ |
---|
| 1411 | + |
---|
1168 | 1412 | #ifdef CONFIG_FAIL_IO_TIMEOUT |
---|
1169 | 1413 | static struct device_attribute dev_attr_fail_timeout = |
---|
1170 | 1414 | __ATTR(io-timeout-fail, 0644, part_timeout_show, part_timeout_store); |
---|
.. | .. |
---|
1259 | 1503 | struct disk_part_tbl *new_ptbl; |
---|
1260 | 1504 | int len = old_ptbl ? old_ptbl->len : 0; |
---|
1261 | 1505 | int i, target; |
---|
1262 | | - size_t size; |
---|
1263 | 1506 | |
---|
1264 | 1507 | /* |
---|
1265 | 1508 | * check for int overflow, since we can get here from blkpg_ioctl() |
---|
.. | .. |
---|
1276 | 1519 | if (target <= len) |
---|
1277 | 1520 | return 0; |
---|
1278 | 1521 | |
---|
1279 | | - size = sizeof(*new_ptbl) + target * sizeof(new_ptbl->part[0]); |
---|
1280 | | - new_ptbl = kzalloc_node(size, GFP_KERNEL, disk->node_id); |
---|
| 1522 | + new_ptbl = kzalloc_node(struct_size(new_ptbl, part, target), GFP_KERNEL, |
---|
| 1523 | + disk->node_id); |
---|
1281 | 1524 | if (!new_ptbl) |
---|
1282 | 1525 | return -ENOMEM; |
---|
1283 | 1526 | |
---|
.. | .. |
---|
1290 | 1533 | return 0; |
---|
1291 | 1534 | } |
---|
1292 | 1535 | |
---|
| 1536 | +/** |
---|
| 1537 | + * disk_release - releases all allocated resources of the gendisk |
---|
| 1538 | + * @dev: the device representing this disk |
---|
| 1539 | + * |
---|
| 1540 | + * This function releases all allocated resources of the gendisk. |
---|
| 1541 | + * |
---|
| 1542 | + * The struct gendisk refcount is incremented with get_gendisk() or |
---|
| 1543 | + * get_disk_and_module(), and its refcount is decremented with |
---|
| 1544 | + * put_disk_and_module() or put_disk(). Once the refcount reaches 0 this |
---|
| 1545 | + * function is called. |
---|
| 1546 | + * |
---|
| 1547 | + * Drivers which used __device_add_disk() have a gendisk with a request_queue |
---|
| 1548 | + * assigned. Since the request_queue sits on top of the gendisk for these |
---|
| 1549 | + * drivers we also call blk_put_queue() for them, and we expect the |
---|
| 1550 | + * request_queue refcount to reach 0 at this point, and so the request_queue |
---|
| 1551 | + * will also be freed prior to the disk. |
---|
| 1552 | + * |
---|
| 1553 | + * Context: can sleep |
---|
| 1554 | + */ |
---|
1293 | 1555 | static void disk_release(struct device *dev) |
---|
1294 | 1556 | { |
---|
1295 | 1557 | struct gendisk *disk = dev_to_disk(dev); |
---|
| 1558 | + |
---|
| 1559 | + might_sleep(); |
---|
1296 | 1560 | |
---|
1297 | 1561 | blk_free_devt(dev->devt); |
---|
1298 | 1562 | disk_release_events(disk); |
---|
.. | .. |
---|
1312 | 1576 | { |
---|
1313 | 1577 | struct gendisk *disk = dev_to_disk(dev); |
---|
1314 | 1578 | |
---|
1315 | | - if (disk->devnode) |
---|
1316 | | - return disk->devnode(disk, mode); |
---|
| 1579 | + if (disk->fops->devnode) |
---|
| 1580 | + return disk->fops->devnode(disk, mode); |
---|
1317 | 1581 | return NULL; |
---|
1318 | 1582 | } |
---|
1319 | 1583 | |
---|
1320 | | -static const struct device_type disk_type = { |
---|
| 1584 | +const struct device_type disk_type = { |
---|
1321 | 1585 | .name = "disk", |
---|
1322 | 1586 | .groups = disk_attr_groups, |
---|
1323 | 1587 | .release = disk_release, |
---|
.. | .. |
---|
1338 | 1602 | struct disk_part_iter piter; |
---|
1339 | 1603 | struct hd_struct *hd; |
---|
1340 | 1604 | char buf[BDEVNAME_SIZE]; |
---|
1341 | | - unsigned int inflight[2]; |
---|
1342 | | - int cpu; |
---|
| 1605 | + unsigned int inflight; |
---|
| 1606 | + struct disk_stats stat; |
---|
1343 | 1607 | |
---|
1344 | 1608 | /* |
---|
1345 | 1609 | if (&disk_to_dev(gp)->kobj.entry == block_class.devices.next) |
---|
.. | .. |
---|
1351 | 1615 | |
---|
1352 | 1616 | disk_part_iter_init(&piter, gp, DISK_PITER_INCL_EMPTY_PART0); |
---|
1353 | 1617 | while ((hd = disk_part_iter_next(&piter))) { |
---|
1354 | | - cpu = part_stat_lock(); |
---|
1355 | | - part_round_stats(gp->queue, cpu, hd); |
---|
1356 | | - part_stat_unlock(); |
---|
1357 | | - part_in_flight(gp->queue, hd, inflight); |
---|
| 1618 | + part_stat_read_all(hd, &stat); |
---|
| 1619 | + if (queue_is_mq(gp->queue)) |
---|
| 1620 | + inflight = blk_mq_in_flight(gp->queue, hd); |
---|
| 1621 | + else |
---|
| 1622 | + inflight = part_in_flight(hd); |
---|
| 1623 | + |
---|
1358 | 1624 | seq_printf(seqf, "%4d %7d %s " |
---|
1359 | 1625 | "%lu %lu %lu %u " |
---|
1360 | 1626 | "%lu %lu %lu %u " |
---|
1361 | 1627 | "%u %u %u " |
---|
1362 | | - "%lu %lu %lu %u\n", |
---|
| 1628 | + "%lu %lu %lu %u " |
---|
| 1629 | + "%lu %u" |
---|
| 1630 | + "\n", |
---|
1363 | 1631 | MAJOR(part_devt(hd)), MINOR(part_devt(hd)), |
---|
1364 | 1632 | disk_name(gp, hd->partno, buf), |
---|
1365 | | - part_stat_read(hd, ios[STAT_READ]), |
---|
1366 | | - part_stat_read(hd, merges[STAT_READ]), |
---|
1367 | | - part_stat_read(hd, sectors[STAT_READ]), |
---|
1368 | | - (unsigned int)part_stat_read_msecs(hd, STAT_READ), |
---|
1369 | | - part_stat_read(hd, ios[STAT_WRITE]), |
---|
1370 | | - part_stat_read(hd, merges[STAT_WRITE]), |
---|
1371 | | - part_stat_read(hd, sectors[STAT_WRITE]), |
---|
1372 | | - (unsigned int)part_stat_read_msecs(hd, STAT_WRITE), |
---|
1373 | | - inflight[0], |
---|
1374 | | - jiffies_to_msecs(part_stat_read(hd, io_ticks)), |
---|
1375 | | - jiffies_to_msecs(part_stat_read(hd, time_in_queue)), |
---|
1376 | | - part_stat_read(hd, ios[STAT_DISCARD]), |
---|
1377 | | - part_stat_read(hd, merges[STAT_DISCARD]), |
---|
1378 | | - part_stat_read(hd, sectors[STAT_DISCARD]), |
---|
1379 | | - (unsigned int)part_stat_read_msecs(hd, STAT_DISCARD) |
---|
| 1633 | + stat.ios[STAT_READ], |
---|
| 1634 | + stat.merges[STAT_READ], |
---|
| 1635 | + stat.sectors[STAT_READ], |
---|
| 1636 | + (unsigned int)div_u64(stat.nsecs[STAT_READ], |
---|
| 1637 | + NSEC_PER_MSEC), |
---|
| 1638 | + stat.ios[STAT_WRITE], |
---|
| 1639 | + stat.merges[STAT_WRITE], |
---|
| 1640 | + stat.sectors[STAT_WRITE], |
---|
| 1641 | + (unsigned int)div_u64(stat.nsecs[STAT_WRITE], |
---|
| 1642 | + NSEC_PER_MSEC), |
---|
| 1643 | + inflight, |
---|
| 1644 | + jiffies_to_msecs(stat.io_ticks), |
---|
| 1645 | + (unsigned int)div_u64(stat.nsecs[STAT_READ] + |
---|
| 1646 | + stat.nsecs[STAT_WRITE] + |
---|
| 1647 | + stat.nsecs[STAT_DISCARD] + |
---|
| 1648 | + stat.nsecs[STAT_FLUSH], |
---|
| 1649 | + NSEC_PER_MSEC), |
---|
| 1650 | + stat.ios[STAT_DISCARD], |
---|
| 1651 | + stat.merges[STAT_DISCARD], |
---|
| 1652 | + stat.sectors[STAT_DISCARD], |
---|
| 1653 | + (unsigned int)div_u64(stat.nsecs[STAT_DISCARD], |
---|
| 1654 | + NSEC_PER_MSEC), |
---|
| 1655 | + stat.ios[STAT_FLUSH], |
---|
| 1656 | + (unsigned int)div_u64(stat.nsecs[STAT_FLUSH], |
---|
| 1657 | + NSEC_PER_MSEC) |
---|
1380 | 1658 | ); |
---|
1381 | 1659 | } |
---|
1382 | 1660 | disk_part_iter_exit(&piter); |
---|
.. | .. |
---|
1433 | 1711 | class_dev_iter_exit(&iter); |
---|
1434 | 1712 | return devt; |
---|
1435 | 1713 | } |
---|
1436 | | -EXPORT_SYMBOL(blk_lookup_devt); |
---|
1437 | 1714 | |
---|
1438 | 1715 | struct gendisk *__alloc_disk_node(int minors, int node_id) |
---|
1439 | 1716 | { |
---|
.. | .. |
---|
1448 | 1725 | } |
---|
1449 | 1726 | |
---|
1450 | 1727 | disk = kzalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id); |
---|
1451 | | - if (disk) { |
---|
1452 | | - if (!init_part_stats(&disk->part0)) { |
---|
1453 | | - kfree(disk); |
---|
1454 | | - return NULL; |
---|
1455 | | - } |
---|
1456 | | - init_rwsem(&disk->lookup_sem); |
---|
1457 | | - disk->node_id = node_id; |
---|
1458 | | - if (disk_expand_part_tbl(disk, 0)) { |
---|
1459 | | - free_part_stats(&disk->part0); |
---|
1460 | | - kfree(disk); |
---|
1461 | | - return NULL; |
---|
1462 | | - } |
---|
1463 | | - ptbl = rcu_dereference_protected(disk->part_tbl, 1); |
---|
1464 | | - rcu_assign_pointer(ptbl->part[0], &disk->part0); |
---|
| 1728 | + if (!disk) |
---|
| 1729 | + return NULL; |
---|
1465 | 1730 | |
---|
1466 | | - /* |
---|
1467 | | - * set_capacity() and get_capacity() currently don't use |
---|
1468 | | - * seqcounter to read/update the part0->nr_sects. Still init |
---|
1469 | | - * the counter as we can read the sectors in IO submission |
---|
1470 | | - * patch using seqence counters. |
---|
1471 | | - * |
---|
1472 | | - * TODO: Ideally set_capacity() and get_capacity() should be |
---|
1473 | | - * converted to make use of bd_mutex and sequence counters. |
---|
1474 | | - */ |
---|
1475 | | - seqcount_init(&disk->part0.nr_sects_seq); |
---|
1476 | | - if (hd_ref_init(&disk->part0)) { |
---|
1477 | | - hd_free_part(&disk->part0); |
---|
1478 | | - kfree(disk); |
---|
1479 | | - return NULL; |
---|
1480 | | - } |
---|
| 1731 | + disk->part0.dkstats = alloc_percpu(struct disk_stats); |
---|
| 1732 | + if (!disk->part0.dkstats) |
---|
| 1733 | + goto out_free_disk; |
---|
1481 | 1734 | |
---|
1482 | | - disk->minors = minors; |
---|
1483 | | - rand_initialize_disk(disk); |
---|
1484 | | - disk_to_dev(disk)->class = &block_class; |
---|
1485 | | - disk_to_dev(disk)->type = &disk_type; |
---|
1486 | | - device_initialize(disk_to_dev(disk)); |
---|
| 1735 | + init_rwsem(&disk->lookup_sem); |
---|
| 1736 | + disk->node_id = node_id; |
---|
| 1737 | + if (disk_expand_part_tbl(disk, 0)) { |
---|
| 1738 | + free_percpu(disk->part0.dkstats); |
---|
| 1739 | + goto out_free_disk; |
---|
1487 | 1740 | } |
---|
| 1741 | + |
---|
| 1742 | + ptbl = rcu_dereference_protected(disk->part_tbl, 1); |
---|
| 1743 | + rcu_assign_pointer(ptbl->part[0], &disk->part0); |
---|
| 1744 | + |
---|
| 1745 | + /* |
---|
| 1746 | + * set_capacity() and get_capacity() currently don't use |
---|
| 1747 | + * seqcounter to read/update the part0->nr_sects. Still init |
---|
| 1748 | + * the counter as we can read the sectors in IO submission |
---|
| 1749 | + * patch using seqence counters. |
---|
| 1750 | + * |
---|
| 1751 | + * TODO: Ideally set_capacity() and get_capacity() should be |
---|
| 1752 | + * converted to make use of bd_mutex and sequence counters. |
---|
| 1753 | + */ |
---|
| 1754 | + hd_sects_seq_init(&disk->part0); |
---|
| 1755 | + if (hd_ref_init(&disk->part0)) |
---|
| 1756 | + goto out_free_part0; |
---|
| 1757 | + |
---|
| 1758 | + disk->minors = minors; |
---|
| 1759 | + rand_initialize_disk(disk); |
---|
| 1760 | + disk_to_dev(disk)->class = &block_class; |
---|
| 1761 | + disk_to_dev(disk)->type = &disk_type; |
---|
| 1762 | + device_initialize(disk_to_dev(disk)); |
---|
1488 | 1763 | return disk; |
---|
| 1764 | + |
---|
| 1765 | +out_free_part0: |
---|
| 1766 | + hd_free_part(&disk->part0); |
---|
| 1767 | +out_free_disk: |
---|
| 1768 | + kfree(disk); |
---|
| 1769 | + return NULL; |
---|
1489 | 1770 | } |
---|
1490 | 1771 | EXPORT_SYMBOL(__alloc_disk_node); |
---|
1491 | 1772 | |
---|
| 1773 | +/** |
---|
| 1774 | + * get_disk_and_module - increments the gendisk and gendisk fops module refcount |
---|
| 1775 | + * @disk: the struct gendisk to increment the refcount for |
---|
| 1776 | + * |
---|
| 1777 | + * This increments the refcount for the struct gendisk, and the gendisk's |
---|
| 1778 | + * fops module owner. |
---|
| 1779 | + * |
---|
| 1780 | + * Context: Any context. |
---|
| 1781 | + */ |
---|
1492 | 1782 | struct kobject *get_disk_and_module(struct gendisk *disk) |
---|
1493 | 1783 | { |
---|
1494 | 1784 | struct module *owner; |
---|
.. | .. |
---|
1509 | 1799 | } |
---|
1510 | 1800 | EXPORT_SYMBOL(get_disk_and_module); |
---|
1511 | 1801 | |
---|
| 1802 | +/** |
---|
| 1803 | + * put_disk - decrements the gendisk refcount |
---|
| 1804 | + * @disk: the struct gendisk to decrement the refcount for |
---|
| 1805 | + * |
---|
| 1806 | + * This decrements the refcount for the struct gendisk. When this reaches 0 |
---|
| 1807 | + * we'll have disk_release() called. |
---|
| 1808 | + * |
---|
| 1809 | + * Context: Any context, but the last reference must not be dropped from |
---|
| 1810 | + * atomic context. |
---|
| 1811 | + */ |
---|
1512 | 1812 | void put_disk(struct gendisk *disk) |
---|
1513 | 1813 | { |
---|
1514 | 1814 | if (disk) |
---|
.. | .. |
---|
1516 | 1816 | } |
---|
1517 | 1817 | EXPORT_SYMBOL(put_disk); |
---|
1518 | 1818 | |
---|
1519 | | -/* |
---|
| 1819 | +/** |
---|
| 1820 | + * put_disk_and_module - decrements the module and gendisk refcount |
---|
| 1821 | + * @disk: the struct gendisk to decrement the refcount for |
---|
| 1822 | + * |
---|
1520 | 1823 | * This is a counterpart of get_disk_and_module() and thus also of |
---|
1521 | 1824 | * get_gendisk(). |
---|
| 1825 | + * |
---|
| 1826 | + * Context: Any context, but the last reference must not be dropped from |
---|
| 1827 | + * atomic context. |
---|
1522 | 1828 | */ |
---|
1523 | 1829 | void put_disk_and_module(struct gendisk *disk) |
---|
1524 | 1830 | { |
---|
.. | .. |
---|
1575 | 1881 | |
---|
1576 | 1882 | EXPORT_SYMBOL(bdev_read_only); |
---|
1577 | 1883 | |
---|
1578 | | -int invalidate_partition(struct gendisk *disk, int partno) |
---|
1579 | | -{ |
---|
1580 | | - int res = 0; |
---|
1581 | | - struct block_device *bdev = bdget_disk(disk, partno); |
---|
1582 | | - if (bdev) { |
---|
1583 | | - fsync_bdev(bdev); |
---|
1584 | | - res = __invalidate_device(bdev, true); |
---|
1585 | | - bdput(bdev); |
---|
1586 | | - } |
---|
1587 | | - return res; |
---|
1588 | | -} |
---|
1589 | | - |
---|
1590 | | -EXPORT_SYMBOL(invalidate_partition); |
---|
1591 | | - |
---|
1592 | 1884 | /* |
---|
1593 | 1885 | * Disk events - monitor disk events like media change and eject request. |
---|
1594 | 1886 | */ |
---|
.. | .. |
---|
1630 | 1922 | |
---|
1631 | 1923 | /* |
---|
1632 | 1924 | * If device-specific poll interval is set, always use it. If |
---|
1633 | | - * the default is being used, poll iff there are events which |
---|
1634 | | - * can't be monitored asynchronously. |
---|
| 1925 | + * the default is being used, poll if the POLL flag is set. |
---|
1635 | 1926 | */ |
---|
1636 | 1927 | if (ev->poll_msecs >= 0) |
---|
1637 | 1928 | intv_msecs = ev->poll_msecs; |
---|
1638 | | - else if (disk->events & ~disk->async_events) |
---|
| 1929 | + else if (disk->event_flags & DISK_EVENT_FLAG_POLL) |
---|
1639 | 1930 | intv_msecs = disk_events_dfl_poll_msecs; |
---|
1640 | 1931 | |
---|
1641 | 1932 | return msecs_to_jiffies(intv_msecs); |
---|
.. | .. |
---|
1760 | 2051 | * CONTEXT: |
---|
1761 | 2052 | * Might sleep. |
---|
1762 | 2053 | */ |
---|
1763 | | -unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask) |
---|
| 2054 | +static unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask) |
---|
1764 | 2055 | { |
---|
1765 | | - const struct block_device_operations *bdops = disk->fops; |
---|
1766 | 2056 | struct disk_events *ev = disk->ev; |
---|
1767 | 2057 | unsigned int pending; |
---|
1768 | 2058 | unsigned int clearing = mask; |
---|
1769 | 2059 | |
---|
1770 | | - if (!ev) { |
---|
1771 | | - /* for drivers still using the old ->media_changed method */ |
---|
1772 | | - if ((mask & DISK_EVENT_MEDIA_CHANGE) && |
---|
1773 | | - bdops->media_changed && bdops->media_changed(disk)) |
---|
1774 | | - return DISK_EVENT_MEDIA_CHANGE; |
---|
| 2060 | + if (!ev) |
---|
1775 | 2061 | return 0; |
---|
1776 | | - } |
---|
1777 | 2062 | |
---|
1778 | 2063 | disk_block_events(disk); |
---|
1779 | 2064 | |
---|
.. | .. |
---|
1803 | 2088 | |
---|
1804 | 2089 | return pending; |
---|
1805 | 2090 | } |
---|
| 2091 | + |
---|
| 2092 | +/** |
---|
| 2093 | + * bdev_check_media_change - check if a removable media has been changed |
---|
| 2094 | + * @bdev: block device to check |
---|
| 2095 | + * |
---|
| 2096 | + * Check whether a removable media has been changed, and attempt to free all |
---|
| 2097 | + * dentries and inodes and invalidates all block device page cache entries in |
---|
| 2098 | + * that case. |
---|
| 2099 | + * |
---|
| 2100 | + * Returns %true if the block device changed, or %false if not. |
---|
| 2101 | + */ |
---|
| 2102 | +bool bdev_check_media_change(struct block_device *bdev) |
---|
| 2103 | +{ |
---|
| 2104 | + unsigned int events; |
---|
| 2105 | + |
---|
| 2106 | + events = disk_clear_events(bdev->bd_disk, DISK_EVENT_MEDIA_CHANGE | |
---|
| 2107 | + DISK_EVENT_EJECT_REQUEST); |
---|
| 2108 | + if (!(events & DISK_EVENT_MEDIA_CHANGE)) |
---|
| 2109 | + return false; |
---|
| 2110 | + |
---|
| 2111 | + if (__invalidate_device(bdev, true)) |
---|
| 2112 | + pr_warn("VFS: busy inodes on changed media %s\n", |
---|
| 2113 | + bdev->bd_disk->disk_name); |
---|
| 2114 | + set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); |
---|
| 2115 | + return true; |
---|
| 2116 | +} |
---|
| 2117 | +EXPORT_SYMBOL(bdev_check_media_change); |
---|
1806 | 2118 | |
---|
1807 | 2119 | /* |
---|
1808 | 2120 | * Separate this part out so that a different pointer for clearing_ptr can be |
---|
.. | .. |
---|
1845 | 2157 | |
---|
1846 | 2158 | /* |
---|
1847 | 2159 | * Tell userland about new events. Only the events listed in |
---|
1848 | | - * @disk->events are reported. Unlisted events are processed the |
---|
1849 | | - * same internally but never get reported to userland. |
---|
| 2160 | + * @disk->events are reported, and only if DISK_EVENT_FLAG_UEVENT |
---|
| 2161 | + * is set. Otherwise, events are processed internally but never |
---|
| 2162 | + * get reported to userland. |
---|
1850 | 2163 | */ |
---|
1851 | 2164 | for (i = 0; i < ARRAY_SIZE(disk_uevents); i++) |
---|
1852 | | - if (events & disk->events & (1 << i)) |
---|
| 2165 | + if ((events & disk->events & (1 << i)) && |
---|
| 2166 | + (disk->event_flags & DISK_EVENT_FLAG_UEVENT)) |
---|
1853 | 2167 | envp[nr_events++] = disk_uevents[i]; |
---|
1854 | 2168 | |
---|
1855 | 2169 | if (nr_events) |
---|
.. | .. |
---|
1862 | 2176 | * |
---|
1863 | 2177 | * events : list of all supported events |
---|
1864 | 2178 | * events_async : list of events which can be detected w/o polling |
---|
| 2179 | + * (always empty, only for backwards compatibility) |
---|
1865 | 2180 | * events_poll_msecs : polling interval, 0: disable, -1: system default |
---|
1866 | 2181 | */ |
---|
1867 | 2182 | static ssize_t __disk_events_show(unsigned int events, char *buf) |
---|
.. | .. |
---|
1886 | 2201 | { |
---|
1887 | 2202 | struct gendisk *disk = dev_to_disk(dev); |
---|
1888 | 2203 | |
---|
| 2204 | + if (!(disk->event_flags & DISK_EVENT_FLAG_UEVENT)) |
---|
| 2205 | + return 0; |
---|
| 2206 | + |
---|
1889 | 2207 | return __disk_events_show(disk->events, buf); |
---|
1890 | 2208 | } |
---|
1891 | 2209 | |
---|
1892 | 2210 | static ssize_t disk_events_async_show(struct device *dev, |
---|
1893 | 2211 | struct device_attribute *attr, char *buf) |
---|
1894 | 2212 | { |
---|
1895 | | - struct gendisk *disk = dev_to_disk(dev); |
---|
1896 | | - |
---|
1897 | | - return __disk_events_show(disk->async_events, buf); |
---|
| 2213 | + return 0; |
---|
1898 | 2214 | } |
---|
1899 | 2215 | |
---|
1900 | 2216 | static ssize_t disk_events_poll_msecs_show(struct device *dev, |
---|
.. | .. |
---|
1902 | 2218 | char *buf) |
---|
1903 | 2219 | { |
---|
1904 | 2220 | struct gendisk *disk = dev_to_disk(dev); |
---|
| 2221 | + |
---|
| 2222 | + if (!disk->ev) |
---|
| 2223 | + return sprintf(buf, "-1\n"); |
---|
1905 | 2224 | |
---|
1906 | 2225 | return sprintf(buf, "%ld\n", disk->ev->poll_msecs); |
---|
1907 | 2226 | } |
---|
.. | .. |
---|
1918 | 2237 | |
---|
1919 | 2238 | if (intv < 0 && intv != -1) |
---|
1920 | 2239 | return -EINVAL; |
---|
| 2240 | + |
---|
| 2241 | + if (!disk->ev) |
---|
| 2242 | + return -ENODEV; |
---|
1921 | 2243 | |
---|
1922 | 2244 | disk_block_events(disk); |
---|
1923 | 2245 | disk->ev->poll_msecs = intv; |
---|
.. | .. |
---|
1943 | 2265 | * The default polling interval can be specified by the kernel |
---|
1944 | 2266 | * parameter block.events_dfl_poll_msecs which defaults to 0 |
---|
1945 | 2267 | * (disable). This can also be modified runtime by writing to |
---|
1946 | | - * /sys/module/block/events_dfl_poll_msecs. |
---|
| 2268 | + * /sys/module/block/parameters/events_dfl_poll_msecs. |
---|
1947 | 2269 | */ |
---|
1948 | 2270 | static int disk_events_set_dfl_poll_msecs(const char *val, |
---|
1949 | 2271 | const struct kernel_param *kp) |
---|
.. | .. |
---|
1983 | 2305 | { |
---|
1984 | 2306 | struct disk_events *ev; |
---|
1985 | 2307 | |
---|
1986 | | - if (!disk->fops->check_events) |
---|
| 2308 | + if (!disk->fops->check_events || !disk->events) |
---|
1987 | 2309 | return; |
---|
1988 | 2310 | |
---|
1989 | 2311 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); |
---|
.. | .. |
---|
2005 | 2327 | |
---|
2006 | 2328 | static void disk_add_events(struct gendisk *disk) |
---|
2007 | 2329 | { |
---|
2008 | | - if (!disk->ev) |
---|
2009 | | - return; |
---|
2010 | | - |
---|
2011 | 2330 | /* FIXME: error handling */ |
---|
2012 | 2331 | if (sysfs_create_files(&disk_to_dev(disk)->kobj, disk_events_attrs) < 0) |
---|
2013 | 2332 | pr_warn("%s: failed to create sysfs files for events\n", |
---|
2014 | 2333 | disk->disk_name); |
---|
| 2334 | + |
---|
| 2335 | + if (!disk->ev) |
---|
| 2336 | + return; |
---|
2015 | 2337 | |
---|
2016 | 2338 | mutex_lock(&disk_events_mutex); |
---|
2017 | 2339 | list_add_tail(&disk->ev->node, &disk_events); |
---|
.. | .. |
---|
2026 | 2348 | |
---|
2027 | 2349 | static void disk_del_events(struct gendisk *disk) |
---|
2028 | 2350 | { |
---|
2029 | | - if (!disk->ev) |
---|
2030 | | - return; |
---|
| 2351 | + if (disk->ev) { |
---|
| 2352 | + disk_block_events(disk); |
---|
2031 | 2353 | |
---|
2032 | | - disk_block_events(disk); |
---|
2033 | | - |
---|
2034 | | - mutex_lock(&disk_events_mutex); |
---|
2035 | | - list_del_init(&disk->ev->node); |
---|
2036 | | - mutex_unlock(&disk_events_mutex); |
---|
| 2354 | + mutex_lock(&disk_events_mutex); |
---|
| 2355 | + list_del_init(&disk->ev->node); |
---|
| 2356 | + mutex_unlock(&disk_events_mutex); |
---|
| 2357 | + } |
---|
2037 | 2358 | |
---|
2038 | 2359 | sysfs_remove_files(&disk_to_dev(disk)->kobj, disk_events_attrs); |
---|
2039 | 2360 | } |
---|