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