1 /* 2 * gendisk handling 3 */ 4 5 #include <linux/module.h> 6 #include <linux/fs.h> 7 #include <linux/genhd.h> 8 #include <linux/kdev_t.h> 9 #include <linux/kernel.h> 10 #include <linux/blkdev.h> 11 #include <linux/init.h> 12 #include <linux/spinlock.h> 13 #include <linux/seq_file.h> 14 #include <linux/slab.h> 15 #include <linux/kmod.h> 16 #include <linux/kobj_map.h> 17 #include <linux/buffer_head.h> 18 #include <linux/mutex.h> 19 20 #include "blk.h" 21 22 static DEFINE_MUTEX(block_class_lock); 23 #ifndef CONFIG_SYSFS_DEPRECATED 24 struct kobject *block_depr; 25 #endif 26 27 static struct device_type disk_type; 28 29 /* 30 * Can be deleted altogether. Later. 31 * 32 */ 33 static struct blk_major_name { 34 struct blk_major_name *next; 35 int major; 36 char name[16]; 37 } *major_names[BLKDEV_MAJOR_HASH_SIZE]; 38 39 /* index in the above - for now: assume no multimajor ranges */ 40 static inline int major_to_index(int major) 41 { 42 return major % BLKDEV_MAJOR_HASH_SIZE; 43 } 44 45 #ifdef CONFIG_PROC_FS 46 void blkdev_show(struct seq_file *f, off_t offset) 47 { 48 struct blk_major_name *dp; 49 50 if (offset < BLKDEV_MAJOR_HASH_SIZE) { 51 mutex_lock(&block_class_lock); 52 for (dp = major_names[offset]; dp; dp = dp->next) 53 seq_printf(f, "%3d %s\n", dp->major, dp->name); 54 mutex_unlock(&block_class_lock); 55 } 56 } 57 #endif /* CONFIG_PROC_FS */ 58 59 int register_blkdev(unsigned int major, const char *name) 60 { 61 struct blk_major_name **n, *p; 62 int index, ret = 0; 63 64 mutex_lock(&block_class_lock); 65 66 /* temporary */ 67 if (major == 0) { 68 for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) { 69 if (major_names[index] == NULL) 70 break; 71 } 72 73 if (index == 0) { 74 printk("register_blkdev: failed to get major for %s\n", 75 name); 76 ret = -EBUSY; 77 goto out; 78 } 79 major = index; 80 ret = major; 81 } 82 83 p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL); 84 if (p == NULL) { 85 ret = -ENOMEM; 86 goto out; 87 } 88 89 p->major = major; 90 strlcpy(p->name, name, sizeof(p->name)); 91 p->next = NULL; 92 index = major_to_index(major); 93 94 for (n = &major_names[index]; *n; n = &(*n)->next) { 95 if ((*n)->major == major) 96 break; 97 } 98 if (!*n) 99 *n = p; 100 else 101 ret = -EBUSY; 102 103 if (ret < 0) { 104 printk("register_blkdev: cannot get major %d for %s\n", 105 major, name); 106 kfree(p); 107 } 108 out: 109 mutex_unlock(&block_class_lock); 110 return ret; 111 } 112 113 EXPORT_SYMBOL(register_blkdev); 114 115 void unregister_blkdev(unsigned int major, const char *name) 116 { 117 struct blk_major_name **n; 118 struct blk_major_name *p = NULL; 119 int index = major_to_index(major); 120 121 mutex_lock(&block_class_lock); 122 for (n = &major_names[index]; *n; n = &(*n)->next) 123 if ((*n)->major == major) 124 break; 125 if (!*n || strcmp((*n)->name, name)) { 126 WARN_ON(1); 127 } else { 128 p = *n; 129 *n = p->next; 130 } 131 mutex_unlock(&block_class_lock); 132 kfree(p); 133 } 134 135 EXPORT_SYMBOL(unregister_blkdev); 136 137 static struct kobj_map *bdev_map; 138 139 /* 140 * Register device numbers dev..(dev+range-1) 141 * range must be nonzero 142 * The hash chain is sorted on range, so that subranges can override. 143 */ 144 void blk_register_region(dev_t devt, unsigned long range, struct module *module, 145 struct kobject *(*probe)(dev_t, int *, void *), 146 int (*lock)(dev_t, void *), void *data) 147 { 148 kobj_map(bdev_map, devt, range, module, probe, lock, data); 149 } 150 151 EXPORT_SYMBOL(blk_register_region); 152 153 void blk_unregister_region(dev_t devt, unsigned long range) 154 { 155 kobj_unmap(bdev_map, devt, range); 156 } 157 158 EXPORT_SYMBOL(blk_unregister_region); 159 160 static struct kobject *exact_match(dev_t devt, int *part, void *data) 161 { 162 struct gendisk *p = data; 163 164 return &p->dev.kobj; 165 } 166 167 static int exact_lock(dev_t devt, void *data) 168 { 169 struct gendisk *p = data; 170 171 if (!get_disk(p)) 172 return -1; 173 return 0; 174 } 175 176 /** 177 * add_disk - add partitioning information to kernel list 178 * @disk: per-device partitioning information 179 * 180 * This function registers the partitioning information in @disk 181 * with the kernel. 182 */ 183 void add_disk(struct gendisk *disk) 184 { 185 struct backing_dev_info *bdi; 186 int retval; 187 188 disk->flags |= GENHD_FL_UP; 189 blk_register_region(MKDEV(disk->major, disk->first_minor), 190 disk->minors, NULL, exact_match, exact_lock, disk); 191 register_disk(disk); 192 blk_register_queue(disk); 193 blk_register_filter(disk); 194 195 bdi = &disk->queue->backing_dev_info; 196 bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor)); 197 retval = sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi"); 198 WARN_ON(retval); 199 } 200 201 EXPORT_SYMBOL(add_disk); 202 EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */ 203 204 void unlink_gendisk(struct gendisk *disk) 205 { 206 blk_unregister_filter(disk); 207 sysfs_remove_link(&disk->dev.kobj, "bdi"); 208 bdi_unregister(&disk->queue->backing_dev_info); 209 blk_unregister_queue(disk); 210 blk_unregister_region(MKDEV(disk->major, disk->first_minor), 211 disk->minors); 212 } 213 214 /** 215 * get_gendisk - get partitioning information for a given device 216 * @dev: device to get partitioning information for 217 * 218 * This function gets the structure containing partitioning 219 * information for the given device @dev. 220 */ 221 struct gendisk *get_gendisk(dev_t devt, int *part) 222 { 223 struct kobject *kobj = kobj_lookup(bdev_map, devt, part); 224 struct device *dev = kobj_to_dev(kobj); 225 226 return kobj ? dev_to_disk(dev) : NULL; 227 } 228 229 /* 230 * print a partitions - intended for places where the root filesystem can't be 231 * mounted and thus to give the victim some idea of what went wrong 232 */ 233 static int printk_partition(struct device *dev, void *data) 234 { 235 struct gendisk *sgp; 236 char buf[BDEVNAME_SIZE]; 237 int n; 238 239 if (dev->type != &disk_type) 240 goto exit; 241 242 sgp = dev_to_disk(dev); 243 /* 244 * Don't show empty devices or things that have been surpressed 245 */ 246 if (get_capacity(sgp) == 0 || 247 (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) 248 goto exit; 249 250 /* 251 * Note, unlike /proc/partitions, I am showing the numbers in 252 * hex - the same format as the root= option takes. 253 */ 254 printk("%02x%02x %10llu %s", 255 sgp->major, sgp->first_minor, 256 (unsigned long long)get_capacity(sgp) >> 1, 257 disk_name(sgp, 0, buf)); 258 if (sgp->driverfs_dev != NULL && 259 sgp->driverfs_dev->driver != NULL) 260 printk(" driver: %s\n", 261 sgp->driverfs_dev->driver->name); 262 else 263 printk(" (driver?)\n"); 264 265 /* now show the partitions */ 266 for (n = 0; n < sgp->minors - 1; ++n) { 267 if (sgp->part[n] == NULL) 268 goto exit; 269 if (sgp->part[n]->nr_sects == 0) 270 goto exit; 271 printk(" %02x%02x %10llu %s\n", 272 sgp->major, n + 1 + sgp->first_minor, 273 (unsigned long long)sgp->part[n]->nr_sects >> 1, 274 disk_name(sgp, n + 1, buf)); 275 } 276 exit: 277 return 0; 278 } 279 280 /* 281 * print a full list of all partitions - intended for places where the root 282 * filesystem can't be mounted and thus to give the victim some idea of what 283 * went wrong 284 */ 285 void __init printk_all_partitions(void) 286 { 287 mutex_lock(&block_class_lock); 288 class_for_each_device(&block_class, NULL, NULL, printk_partition); 289 mutex_unlock(&block_class_lock); 290 } 291 292 #ifdef CONFIG_PROC_FS 293 /* iterator */ 294 static int find_start(struct device *dev, void *data) 295 { 296 loff_t k = *(loff_t *)data; 297 298 if (dev->type != &disk_type) 299 return 0; 300 if (!k--) 301 return 1; 302 return 0; 303 } 304 305 static void *part_start(struct seq_file *part, loff_t *pos) 306 { 307 struct device *dev; 308 loff_t n = *pos; 309 310 if (!n) 311 seq_puts(part, "major minor #blocks name\n\n"); 312 313 mutex_lock(&block_class_lock); 314 dev = class_find_device(&block_class, NULL, (void *)pos, find_start); 315 if (dev) 316 return dev_to_disk(dev); 317 return NULL; 318 } 319 320 static int find_next(struct device *dev, void *data) 321 { 322 if (dev->type == &disk_type) 323 return 1; 324 return 0; 325 } 326 327 static void *part_next(struct seq_file *part, void *v, loff_t *pos) 328 { 329 struct gendisk *gp = v; 330 struct device *dev; 331 ++*pos; 332 dev = class_find_device(&block_class, &gp->dev, NULL, find_next); 333 if (dev) 334 return dev_to_disk(dev); 335 return NULL; 336 } 337 338 static void part_stop(struct seq_file *part, void *v) 339 { 340 mutex_unlock(&block_class_lock); 341 } 342 343 static int show_partition(struct seq_file *part, void *v) 344 { 345 struct gendisk *sgp = v; 346 int n; 347 char buf[BDEVNAME_SIZE]; 348 349 /* Don't show non-partitionable removeable devices or empty devices */ 350 if (!get_capacity(sgp) || 351 (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) 352 return 0; 353 if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) 354 return 0; 355 356 /* show the full disk and all non-0 size partitions of it */ 357 seq_printf(part, "%4d %4d %10llu %s\n", 358 sgp->major, sgp->first_minor, 359 (unsigned long long)get_capacity(sgp) >> 1, 360 disk_name(sgp, 0, buf)); 361 for (n = 0; n < sgp->minors - 1; n++) { 362 if (!sgp->part[n]) 363 continue; 364 if (sgp->part[n]->nr_sects == 0) 365 continue; 366 seq_printf(part, "%4d %4d %10llu %s\n", 367 sgp->major, n + 1 + sgp->first_minor, 368 (unsigned long long)sgp->part[n]->nr_sects >> 1 , 369 disk_name(sgp, n + 1, buf)); 370 } 371 372 return 0; 373 } 374 375 const struct seq_operations partitions_op = { 376 .start = part_start, 377 .next = part_next, 378 .stop = part_stop, 379 .show = show_partition 380 }; 381 #endif 382 383 384 static struct kobject *base_probe(dev_t devt, int *part, void *data) 385 { 386 if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0) 387 /* Make old-style 2.4 aliases work */ 388 request_module("block-major-%d", MAJOR(devt)); 389 return NULL; 390 } 391 392 static int __init genhd_device_init(void) 393 { 394 int error; 395 396 block_class.dev_kobj = sysfs_dev_block_kobj; 397 error = class_register(&block_class); 398 if (unlikely(error)) 399 return error; 400 bdev_map = kobj_map_init(base_probe, &block_class_lock); 401 blk_dev_init(); 402 403 #ifndef CONFIG_SYSFS_DEPRECATED 404 /* create top-level block dir */ 405 block_depr = kobject_create_and_add("block", NULL); 406 #endif 407 return 0; 408 } 409 410 subsys_initcall(genhd_device_init); 411 412 static ssize_t disk_range_show(struct device *dev, 413 struct device_attribute *attr, char *buf) 414 { 415 struct gendisk *disk = dev_to_disk(dev); 416 417 return sprintf(buf, "%d\n", disk->minors); 418 } 419 420 static ssize_t disk_removable_show(struct device *dev, 421 struct device_attribute *attr, char *buf) 422 { 423 struct gendisk *disk = dev_to_disk(dev); 424 425 return sprintf(buf, "%d\n", 426 (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0)); 427 } 428 429 static ssize_t disk_ro_show(struct device *dev, 430 struct device_attribute *attr, char *buf) 431 { 432 struct gendisk *disk = dev_to_disk(dev); 433 434 return sprintf(buf, "%d\n", disk->policy ? 1 : 0); 435 } 436 437 static ssize_t disk_size_show(struct device *dev, 438 struct device_attribute *attr, char *buf) 439 { 440 struct gendisk *disk = dev_to_disk(dev); 441 442 return sprintf(buf, "%llu\n", (unsigned long long)get_capacity(disk)); 443 } 444 445 static ssize_t disk_capability_show(struct device *dev, 446 struct device_attribute *attr, char *buf) 447 { 448 struct gendisk *disk = dev_to_disk(dev); 449 450 return sprintf(buf, "%x\n", disk->flags); 451 } 452 453 static ssize_t disk_stat_show(struct device *dev, 454 struct device_attribute *attr, char *buf) 455 { 456 struct gendisk *disk = dev_to_disk(dev); 457 458 preempt_disable(); 459 disk_round_stats(disk); 460 preempt_enable(); 461 return sprintf(buf, 462 "%8lu %8lu %8llu %8u " 463 "%8lu %8lu %8llu %8u " 464 "%8u %8u %8u" 465 "\n", 466 disk_stat_read(disk, ios[READ]), 467 disk_stat_read(disk, merges[READ]), 468 (unsigned long long)disk_stat_read(disk, sectors[READ]), 469 jiffies_to_msecs(disk_stat_read(disk, ticks[READ])), 470 disk_stat_read(disk, ios[WRITE]), 471 disk_stat_read(disk, merges[WRITE]), 472 (unsigned long long)disk_stat_read(disk, sectors[WRITE]), 473 jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])), 474 disk->in_flight, 475 jiffies_to_msecs(disk_stat_read(disk, io_ticks)), 476 jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); 477 } 478 479 #ifdef CONFIG_FAIL_MAKE_REQUEST 480 static ssize_t disk_fail_show(struct device *dev, 481 struct device_attribute *attr, char *buf) 482 { 483 struct gendisk *disk = dev_to_disk(dev); 484 485 return sprintf(buf, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0); 486 } 487 488 static ssize_t disk_fail_store(struct device *dev, 489 struct device_attribute *attr, 490 const char *buf, size_t count) 491 { 492 struct gendisk *disk = dev_to_disk(dev); 493 int i; 494 495 if (count > 0 && sscanf(buf, "%d", &i) > 0) { 496 if (i == 0) 497 disk->flags &= ~GENHD_FL_FAIL; 498 else 499 disk->flags |= GENHD_FL_FAIL; 500 } 501 502 return count; 503 } 504 505 #endif 506 507 static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); 508 static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); 509 static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); 510 static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL); 511 static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); 512 static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL); 513 #ifdef CONFIG_FAIL_MAKE_REQUEST 514 static struct device_attribute dev_attr_fail = 515 __ATTR(make-it-fail, S_IRUGO|S_IWUSR, disk_fail_show, disk_fail_store); 516 #endif 517 518 static struct attribute *disk_attrs[] = { 519 &dev_attr_range.attr, 520 &dev_attr_removable.attr, 521 &dev_attr_ro.attr, 522 &dev_attr_size.attr, 523 &dev_attr_capability.attr, 524 &dev_attr_stat.attr, 525 #ifdef CONFIG_FAIL_MAKE_REQUEST 526 &dev_attr_fail.attr, 527 #endif 528 NULL 529 }; 530 531 static struct attribute_group disk_attr_group = { 532 .attrs = disk_attrs, 533 }; 534 535 static struct attribute_group *disk_attr_groups[] = { 536 &disk_attr_group, 537 NULL 538 }; 539 540 static void disk_release(struct device *dev) 541 { 542 struct gendisk *disk = dev_to_disk(dev); 543 544 kfree(disk->random); 545 kfree(disk->part); 546 free_disk_stats(disk); 547 kfree(disk); 548 } 549 struct class block_class = { 550 .name = "block", 551 }; 552 553 static struct device_type disk_type = { 554 .name = "disk", 555 .groups = disk_attr_groups, 556 .release = disk_release, 557 }; 558 559 #ifdef CONFIG_PROC_FS 560 /* 561 * aggregate disk stat collector. Uses the same stats that the sysfs 562 * entries do, above, but makes them available through one seq_file. 563 * 564 * The output looks suspiciously like /proc/partitions with a bunch of 565 * extra fields. 566 */ 567 568 static void *diskstats_start(struct seq_file *part, loff_t *pos) 569 { 570 struct device *dev; 571 572 mutex_lock(&block_class_lock); 573 dev = class_find_device(&block_class, NULL, (void *)pos, find_start); 574 if (dev) 575 return dev_to_disk(dev); 576 return NULL; 577 } 578 579 static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos) 580 { 581 struct gendisk *gp = v; 582 struct device *dev; 583 584 ++*pos; 585 dev = class_find_device(&block_class, &gp->dev, NULL, find_next); 586 if (dev) 587 return dev_to_disk(dev); 588 return NULL; 589 } 590 591 static void diskstats_stop(struct seq_file *part, void *v) 592 { 593 mutex_unlock(&block_class_lock); 594 } 595 596 static int diskstats_show(struct seq_file *s, void *v) 597 { 598 struct gendisk *gp = v; 599 char buf[BDEVNAME_SIZE]; 600 int n = 0; 601 602 /* 603 if (&gp->dev.kobj.entry == block_class.devices.next) 604 seq_puts(s, "major minor name" 605 " rio rmerge rsect ruse wio wmerge " 606 "wsect wuse running use aveq" 607 "\n\n"); 608 */ 609 610 preempt_disable(); 611 disk_round_stats(gp); 612 preempt_enable(); 613 seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", 614 gp->major, n + gp->first_minor, disk_name(gp, n, buf), 615 disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), 616 (unsigned long long)disk_stat_read(gp, sectors[0]), 617 jiffies_to_msecs(disk_stat_read(gp, ticks[0])), 618 disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]), 619 (unsigned long long)disk_stat_read(gp, sectors[1]), 620 jiffies_to_msecs(disk_stat_read(gp, ticks[1])), 621 gp->in_flight, 622 jiffies_to_msecs(disk_stat_read(gp, io_ticks)), 623 jiffies_to_msecs(disk_stat_read(gp, time_in_queue))); 624 625 /* now show all non-0 size partitions of it */ 626 for (n = 0; n < gp->minors - 1; n++) { 627 struct hd_struct *hd = gp->part[n]; 628 629 if (!hd || !hd->nr_sects) 630 continue; 631 632 preempt_disable(); 633 part_round_stats(hd); 634 preempt_enable(); 635 seq_printf(s, "%4d %4d %s %lu %lu %llu " 636 "%u %lu %lu %llu %u %u %u %u\n", 637 gp->major, n + gp->first_minor + 1, 638 disk_name(gp, n + 1, buf), 639 part_stat_read(hd, ios[0]), 640 part_stat_read(hd, merges[0]), 641 (unsigned long long)part_stat_read(hd, sectors[0]), 642 jiffies_to_msecs(part_stat_read(hd, ticks[0])), 643 part_stat_read(hd, ios[1]), 644 part_stat_read(hd, merges[1]), 645 (unsigned long long)part_stat_read(hd, sectors[1]), 646 jiffies_to_msecs(part_stat_read(hd, ticks[1])), 647 hd->in_flight, 648 jiffies_to_msecs(part_stat_read(hd, io_ticks)), 649 jiffies_to_msecs(part_stat_read(hd, time_in_queue)) 650 ); 651 } 652 653 return 0; 654 } 655 656 const struct seq_operations diskstats_op = { 657 .start = diskstats_start, 658 .next = diskstats_next, 659 .stop = diskstats_stop, 660 .show = diskstats_show 661 }; 662 #endif /* CONFIG_PROC_FS */ 663 664 static void media_change_notify_thread(struct work_struct *work) 665 { 666 struct gendisk *gd = container_of(work, struct gendisk, async_notify); 667 char event[] = "MEDIA_CHANGE=1"; 668 char *envp[] = { event, NULL }; 669 670 /* 671 * set enviroment vars to indicate which event this is for 672 * so that user space will know to go check the media status. 673 */ 674 kobject_uevent_env(&gd->dev.kobj, KOBJ_CHANGE, envp); 675 put_device(gd->driverfs_dev); 676 } 677 678 #if 0 679 void genhd_media_change_notify(struct gendisk *disk) 680 { 681 get_device(disk->driverfs_dev); 682 schedule_work(&disk->async_notify); 683 } 684 EXPORT_SYMBOL_GPL(genhd_media_change_notify); 685 #endif /* 0 */ 686 687 struct find_block { 688 const char *name; 689 int part; 690 }; 691 692 static int match_id(struct device *dev, void *data) 693 { 694 struct find_block *find = data; 695 696 if (dev->type != &disk_type) 697 return 0; 698 if (strcmp(dev->bus_id, find->name) == 0) { 699 struct gendisk *disk = dev_to_disk(dev); 700 if (find->part < disk->minors) 701 return 1; 702 } 703 return 0; 704 } 705 706 dev_t blk_lookup_devt(const char *name, int part) 707 { 708 struct device *dev; 709 dev_t devt = MKDEV(0, 0); 710 struct find_block find; 711 712 mutex_lock(&block_class_lock); 713 find.name = name; 714 find.part = part; 715 dev = class_find_device(&block_class, NULL, (void *)&find, match_id); 716 if (dev) 717 devt = MKDEV(MAJOR(dev->devt), 718 MINOR(dev->devt) + part); 719 mutex_unlock(&block_class_lock); 720 721 return devt; 722 } 723 EXPORT_SYMBOL(blk_lookup_devt); 724 725 struct gendisk *alloc_disk(int minors) 726 { 727 return alloc_disk_node(minors, -1); 728 } 729 730 struct gendisk *alloc_disk_node(int minors, int node_id) 731 { 732 struct gendisk *disk; 733 734 disk = kmalloc_node(sizeof(struct gendisk), 735 GFP_KERNEL | __GFP_ZERO, node_id); 736 if (disk) { 737 if (!init_disk_stats(disk)) { 738 kfree(disk); 739 return NULL; 740 } 741 if (minors > 1) { 742 int size = (minors - 1) * sizeof(struct hd_struct *); 743 disk->part = kmalloc_node(size, 744 GFP_KERNEL | __GFP_ZERO, node_id); 745 if (!disk->part) { 746 free_disk_stats(disk); 747 kfree(disk); 748 return NULL; 749 } 750 } 751 disk->minors = minors; 752 rand_initialize_disk(disk); 753 disk->dev.class = &block_class; 754 disk->dev.type = &disk_type; 755 device_initialize(&disk->dev); 756 INIT_WORK(&disk->async_notify, 757 media_change_notify_thread); 758 } 759 return disk; 760 } 761 762 EXPORT_SYMBOL(alloc_disk); 763 EXPORT_SYMBOL(alloc_disk_node); 764 765 struct kobject *get_disk(struct gendisk *disk) 766 { 767 struct module *owner; 768 struct kobject *kobj; 769 770 if (!disk->fops) 771 return NULL; 772 owner = disk->fops->owner; 773 if (owner && !try_module_get(owner)) 774 return NULL; 775 kobj = kobject_get(&disk->dev.kobj); 776 if (kobj == NULL) { 777 module_put(owner); 778 return NULL; 779 } 780 return kobj; 781 782 } 783 784 EXPORT_SYMBOL(get_disk); 785 786 void put_disk(struct gendisk *disk) 787 { 788 if (disk) 789 kobject_put(&disk->dev.kobj); 790 } 791 792 EXPORT_SYMBOL(put_disk); 793 794 void set_device_ro(struct block_device *bdev, int flag) 795 { 796 if (bdev->bd_contains != bdev) 797 bdev->bd_part->policy = flag; 798 else 799 bdev->bd_disk->policy = flag; 800 } 801 802 EXPORT_SYMBOL(set_device_ro); 803 804 void set_disk_ro(struct gendisk *disk, int flag) 805 { 806 int i; 807 disk->policy = flag; 808 for (i = 0; i < disk->minors - 1; i++) 809 if (disk->part[i]) disk->part[i]->policy = flag; 810 } 811 812 EXPORT_SYMBOL(set_disk_ro); 813 814 int bdev_read_only(struct block_device *bdev) 815 { 816 if (!bdev) 817 return 0; 818 else if (bdev->bd_contains != bdev) 819 return bdev->bd_part->policy; 820 else 821 return bdev->bd_disk->policy; 822 } 823 824 EXPORT_SYMBOL(bdev_read_only); 825 826 int invalidate_partition(struct gendisk *disk, int index) 827 { 828 int res = 0; 829 struct block_device *bdev = bdget_disk(disk, index); 830 if (bdev) { 831 fsync_bdev(bdev); 832 res = __invalidate_device(bdev); 833 bdput(bdev); 834 } 835 return res; 836 } 837 838 EXPORT_SYMBOL(invalidate_partition); 839