xref: /openbmc/linux/block/genhd.c (revision 22246614)
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 
187 	disk->flags |= GENHD_FL_UP;
188 	blk_register_region(MKDEV(disk->major, disk->first_minor),
189 			    disk->minors, NULL, exact_match, exact_lock, disk);
190 	register_disk(disk);
191 	blk_register_queue(disk);
192 
193 	bdi = &disk->queue->backing_dev_info;
194 	bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor));
195 	sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
196 }
197 
198 EXPORT_SYMBOL(add_disk);
199 EXPORT_SYMBOL(del_gendisk);	/* in partitions/check.c */
200 
201 void unlink_gendisk(struct gendisk *disk)
202 {
203 	sysfs_remove_link(&disk->dev.kobj, "bdi");
204 	bdi_unregister(&disk->queue->backing_dev_info);
205 	blk_unregister_queue(disk);
206 	blk_unregister_region(MKDEV(disk->major, disk->first_minor),
207 			      disk->minors);
208 }
209 
210 /**
211  * get_gendisk - get partitioning information for a given device
212  * @dev: device to get partitioning information for
213  *
214  * This function gets the structure containing partitioning
215  * information for the given device @dev.
216  */
217 struct gendisk *get_gendisk(dev_t devt, int *part)
218 {
219 	struct kobject *kobj = kobj_lookup(bdev_map, devt, part);
220 	struct device *dev = kobj_to_dev(kobj);
221 
222 	return  kobj ? dev_to_disk(dev) : NULL;
223 }
224 
225 /*
226  * print a full list of all partitions - intended for places where the root
227  * filesystem can't be mounted and thus to give the victim some idea of what
228  * went wrong
229  */
230 void __init printk_all_partitions(void)
231 {
232 	struct device *dev;
233 	struct gendisk *sgp;
234 	char buf[BDEVNAME_SIZE];
235 	int n;
236 
237 	mutex_lock(&block_class_lock);
238 	/* For each block device... */
239 	list_for_each_entry(dev, &block_class.devices, node) {
240 		if (dev->type != &disk_type)
241 			continue;
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 			continue;
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 				continue;
269 			if (sgp->part[n]->nr_sects == 0)
270 				continue;
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 	}
277 
278 	mutex_unlock(&block_class_lock);
279 }
280 
281 #ifdef CONFIG_PROC_FS
282 /* iterator */
283 static void *part_start(struct seq_file *part, loff_t *pos)
284 {
285 	loff_t k = *pos;
286 	struct device *dev;
287 
288 	mutex_lock(&block_class_lock);
289 	list_for_each_entry(dev, &block_class.devices, node) {
290 		if (dev->type != &disk_type)
291 			continue;
292 		if (!k--)
293 			return dev_to_disk(dev);
294 	}
295 	return NULL;
296 }
297 
298 static void *part_next(struct seq_file *part, void *v, loff_t *pos)
299 {
300 	struct gendisk *gp = v;
301 	struct device *dev;
302 	++*pos;
303 	list_for_each_entry(dev, &gp->dev.node, node) {
304 		if (&dev->node == &block_class.devices)
305 			return NULL;
306 		if (dev->type == &disk_type)
307 			return dev_to_disk(dev);
308 	}
309 	return NULL;
310 }
311 
312 static void part_stop(struct seq_file *part, void *v)
313 {
314 	mutex_unlock(&block_class_lock);
315 }
316 
317 static int show_partition(struct seq_file *part, void *v)
318 {
319 	struct gendisk *sgp = v;
320 	int n;
321 	char buf[BDEVNAME_SIZE];
322 
323 	if (&sgp->dev.node == block_class.devices.next)
324 		seq_puts(part, "major minor  #blocks  name\n\n");
325 
326 	/* Don't show non-partitionable removeable devices or empty devices */
327 	if (!get_capacity(sgp) ||
328 			(sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE)))
329 		return 0;
330 	if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)
331 		return 0;
332 
333 	/* show the full disk and all non-0 size partitions of it */
334 	seq_printf(part, "%4d  %4d %10llu %s\n",
335 		sgp->major, sgp->first_minor,
336 		(unsigned long long)get_capacity(sgp) >> 1,
337 		disk_name(sgp, 0, buf));
338 	for (n = 0; n < sgp->minors - 1; n++) {
339 		if (!sgp->part[n])
340 			continue;
341 		if (sgp->part[n]->nr_sects == 0)
342 			continue;
343 		seq_printf(part, "%4d  %4d %10llu %s\n",
344 			sgp->major, n + 1 + sgp->first_minor,
345 			(unsigned long long)sgp->part[n]->nr_sects >> 1 ,
346 			disk_name(sgp, n + 1, buf));
347 	}
348 
349 	return 0;
350 }
351 
352 const struct seq_operations partitions_op = {
353 	.start	= part_start,
354 	.next	= part_next,
355 	.stop	= part_stop,
356 	.show	= show_partition
357 };
358 #endif
359 
360 
361 static struct kobject *base_probe(dev_t devt, int *part, void *data)
362 {
363 	if (request_module("block-major-%d-%d", MAJOR(devt), MINOR(devt)) > 0)
364 		/* Make old-style 2.4 aliases work */
365 		request_module("block-major-%d", MAJOR(devt));
366 	return NULL;
367 }
368 
369 static int __init genhd_device_init(void)
370 {
371 	int error = class_register(&block_class);
372 	if (unlikely(error))
373 		return error;
374 	bdev_map = kobj_map_init(base_probe, &block_class_lock);
375 	blk_dev_init();
376 
377 #ifndef CONFIG_SYSFS_DEPRECATED
378 	/* create top-level block dir */
379 	block_depr = kobject_create_and_add("block", NULL);
380 #endif
381 	return 0;
382 }
383 
384 subsys_initcall(genhd_device_init);
385 
386 static ssize_t disk_range_show(struct device *dev,
387 			       struct device_attribute *attr, char *buf)
388 {
389 	struct gendisk *disk = dev_to_disk(dev);
390 
391 	return sprintf(buf, "%d\n", disk->minors);
392 }
393 
394 static ssize_t disk_removable_show(struct device *dev,
395 				   struct device_attribute *attr, char *buf)
396 {
397 	struct gendisk *disk = dev_to_disk(dev);
398 
399 	return sprintf(buf, "%d\n",
400 		       (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0));
401 }
402 
403 static ssize_t disk_size_show(struct device *dev,
404 			      struct device_attribute *attr, char *buf)
405 {
406 	struct gendisk *disk = dev_to_disk(dev);
407 
408 	return sprintf(buf, "%llu\n", (unsigned long long)get_capacity(disk));
409 }
410 
411 static ssize_t disk_capability_show(struct device *dev,
412 				    struct device_attribute *attr, char *buf)
413 {
414 	struct gendisk *disk = dev_to_disk(dev);
415 
416 	return sprintf(buf, "%x\n", disk->flags);
417 }
418 
419 static ssize_t disk_stat_show(struct device *dev,
420 			      struct device_attribute *attr, char *buf)
421 {
422 	struct gendisk *disk = dev_to_disk(dev);
423 
424 	preempt_disable();
425 	disk_round_stats(disk);
426 	preempt_enable();
427 	return sprintf(buf,
428 		"%8lu %8lu %8llu %8u "
429 		"%8lu %8lu %8llu %8u "
430 		"%8u %8u %8u"
431 		"\n",
432 		disk_stat_read(disk, ios[READ]),
433 		disk_stat_read(disk, merges[READ]),
434 		(unsigned long long)disk_stat_read(disk, sectors[READ]),
435 		jiffies_to_msecs(disk_stat_read(disk, ticks[READ])),
436 		disk_stat_read(disk, ios[WRITE]),
437 		disk_stat_read(disk, merges[WRITE]),
438 		(unsigned long long)disk_stat_read(disk, sectors[WRITE]),
439 		jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])),
440 		disk->in_flight,
441 		jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
442 		jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
443 }
444 
445 #ifdef CONFIG_FAIL_MAKE_REQUEST
446 static ssize_t disk_fail_show(struct device *dev,
447 			      struct device_attribute *attr, char *buf)
448 {
449 	struct gendisk *disk = dev_to_disk(dev);
450 
451 	return sprintf(buf, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0);
452 }
453 
454 static ssize_t disk_fail_store(struct device *dev,
455 			       struct device_attribute *attr,
456 			       const char *buf, size_t count)
457 {
458 	struct gendisk *disk = dev_to_disk(dev);
459 	int i;
460 
461 	if (count > 0 && sscanf(buf, "%d", &i) > 0) {
462 		if (i == 0)
463 			disk->flags &= ~GENHD_FL_FAIL;
464 		else
465 			disk->flags |= GENHD_FL_FAIL;
466 	}
467 
468 	return count;
469 }
470 
471 #endif
472 
473 static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
474 static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
475 static DEVICE_ATTR(size, S_IRUGO, disk_size_show, NULL);
476 static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL);
477 static DEVICE_ATTR(stat, S_IRUGO, disk_stat_show, NULL);
478 #ifdef CONFIG_FAIL_MAKE_REQUEST
479 static struct device_attribute dev_attr_fail =
480 	__ATTR(make-it-fail, S_IRUGO|S_IWUSR, disk_fail_show, disk_fail_store);
481 #endif
482 
483 static struct attribute *disk_attrs[] = {
484 	&dev_attr_range.attr,
485 	&dev_attr_removable.attr,
486 	&dev_attr_size.attr,
487 	&dev_attr_capability.attr,
488 	&dev_attr_stat.attr,
489 #ifdef CONFIG_FAIL_MAKE_REQUEST
490 	&dev_attr_fail.attr,
491 #endif
492 	NULL
493 };
494 
495 static struct attribute_group disk_attr_group = {
496 	.attrs = disk_attrs,
497 };
498 
499 static struct attribute_group *disk_attr_groups[] = {
500 	&disk_attr_group,
501 	NULL
502 };
503 
504 static void disk_release(struct device *dev)
505 {
506 	struct gendisk *disk = dev_to_disk(dev);
507 
508 	kfree(disk->random);
509 	kfree(disk->part);
510 	free_disk_stats(disk);
511 	kfree(disk);
512 }
513 struct class block_class = {
514 	.name		= "block",
515 };
516 
517 static struct device_type disk_type = {
518 	.name		= "disk",
519 	.groups		= disk_attr_groups,
520 	.release	= disk_release,
521 };
522 
523 /*
524  * aggregate disk stat collector.  Uses the same stats that the sysfs
525  * entries do, above, but makes them available through one seq_file.
526  *
527  * The output looks suspiciously like /proc/partitions with a bunch of
528  * extra fields.
529  */
530 
531 static void *diskstats_start(struct seq_file *part, loff_t *pos)
532 {
533 	loff_t k = *pos;
534 	struct device *dev;
535 
536 	mutex_lock(&block_class_lock);
537 	list_for_each_entry(dev, &block_class.devices, node) {
538 		if (dev->type != &disk_type)
539 			continue;
540 		if (!k--)
541 			return dev_to_disk(dev);
542 	}
543 	return NULL;
544 }
545 
546 static void *diskstats_next(struct seq_file *part, void *v, loff_t *pos)
547 {
548 	struct gendisk *gp = v;
549 	struct device *dev;
550 
551 	++*pos;
552 	list_for_each_entry(dev, &gp->dev.node, node) {
553 		if (&dev->node == &block_class.devices)
554 			return NULL;
555 		if (dev->type == &disk_type)
556 			return dev_to_disk(dev);
557 	}
558 	return NULL;
559 }
560 
561 static void diskstats_stop(struct seq_file *part, void *v)
562 {
563 	mutex_unlock(&block_class_lock);
564 }
565 
566 static int diskstats_show(struct seq_file *s, void *v)
567 {
568 	struct gendisk *gp = v;
569 	char buf[BDEVNAME_SIZE];
570 	int n = 0;
571 
572 	/*
573 	if (&gp->dev.kobj.entry == block_class.devices.next)
574 		seq_puts(s,	"major minor name"
575 				"     rio rmerge rsect ruse wio wmerge "
576 				"wsect wuse running use aveq"
577 				"\n\n");
578 	*/
579 
580 	preempt_disable();
581 	disk_round_stats(gp);
582 	preempt_enable();
583 	seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n",
584 		gp->major, n + gp->first_minor, disk_name(gp, n, buf),
585 		disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]),
586 		(unsigned long long)disk_stat_read(gp, sectors[0]),
587 		jiffies_to_msecs(disk_stat_read(gp, ticks[0])),
588 		disk_stat_read(gp, ios[1]), disk_stat_read(gp, merges[1]),
589 		(unsigned long long)disk_stat_read(gp, sectors[1]),
590 		jiffies_to_msecs(disk_stat_read(gp, ticks[1])),
591 		gp->in_flight,
592 		jiffies_to_msecs(disk_stat_read(gp, io_ticks)),
593 		jiffies_to_msecs(disk_stat_read(gp, time_in_queue)));
594 
595 	/* now show all non-0 size partitions of it */
596 	for (n = 0; n < gp->minors - 1; n++) {
597 		struct hd_struct *hd = gp->part[n];
598 
599 		if (!hd || !hd->nr_sects)
600 			continue;
601 
602 		preempt_disable();
603 		part_round_stats(hd);
604 		preempt_enable();
605 		seq_printf(s, "%4d %4d %s %lu %lu %llu "
606 			   "%u %lu %lu %llu %u %u %u %u\n",
607 			   gp->major, n + gp->first_minor + 1,
608 			   disk_name(gp, n + 1, buf),
609 			   part_stat_read(hd, ios[0]),
610 			   part_stat_read(hd, merges[0]),
611 			   (unsigned long long)part_stat_read(hd, sectors[0]),
612 			   jiffies_to_msecs(part_stat_read(hd, ticks[0])),
613 			   part_stat_read(hd, ios[1]),
614 			   part_stat_read(hd, merges[1]),
615 			   (unsigned long long)part_stat_read(hd, sectors[1]),
616 			   jiffies_to_msecs(part_stat_read(hd, ticks[1])),
617 			   hd->in_flight,
618 			   jiffies_to_msecs(part_stat_read(hd, io_ticks)),
619 			   jiffies_to_msecs(part_stat_read(hd, time_in_queue))
620 			);
621 	}
622 
623 	return 0;
624 }
625 
626 const struct seq_operations diskstats_op = {
627 	.start	= diskstats_start,
628 	.next	= diskstats_next,
629 	.stop	= diskstats_stop,
630 	.show	= diskstats_show
631 };
632 
633 static void media_change_notify_thread(struct work_struct *work)
634 {
635 	struct gendisk *gd = container_of(work, struct gendisk, async_notify);
636 	char event[] = "MEDIA_CHANGE=1";
637 	char *envp[] = { event, NULL };
638 
639 	/*
640 	 * set enviroment vars to indicate which event this is for
641 	 * so that user space will know to go check the media status.
642 	 */
643 	kobject_uevent_env(&gd->dev.kobj, KOBJ_CHANGE, envp);
644 	put_device(gd->driverfs_dev);
645 }
646 
647 #if 0
648 void genhd_media_change_notify(struct gendisk *disk)
649 {
650 	get_device(disk->driverfs_dev);
651 	schedule_work(&disk->async_notify);
652 }
653 EXPORT_SYMBOL_GPL(genhd_media_change_notify);
654 #endif  /*  0  */
655 
656 dev_t blk_lookup_devt(const char *name, int part)
657 {
658 	struct device *dev;
659 	dev_t devt = MKDEV(0, 0);
660 
661 	mutex_lock(&block_class_lock);
662 	list_for_each_entry(dev, &block_class.devices, node) {
663 		if (strcmp(dev->bus_id, name) == 0) {
664 			struct gendisk *disk = dev_to_disk(dev);
665 
666 			if (part < disk->minors)
667 				devt = MKDEV(MAJOR(dev->devt),
668 					     MINOR(dev->devt) + part);
669 			break;
670 		}
671 	}
672 	mutex_unlock(&block_class_lock);
673 
674 	return devt;
675 }
676 EXPORT_SYMBOL(blk_lookup_devt);
677 
678 struct gendisk *alloc_disk(int minors)
679 {
680 	return alloc_disk_node(minors, -1);
681 }
682 
683 struct gendisk *alloc_disk_node(int minors, int node_id)
684 {
685 	struct gendisk *disk;
686 
687 	disk = kmalloc_node(sizeof(struct gendisk),
688 				GFP_KERNEL | __GFP_ZERO, node_id);
689 	if (disk) {
690 		if (!init_disk_stats(disk)) {
691 			kfree(disk);
692 			return NULL;
693 		}
694 		if (minors > 1) {
695 			int size = (minors - 1) * sizeof(struct hd_struct *);
696 			disk->part = kmalloc_node(size,
697 				GFP_KERNEL | __GFP_ZERO, node_id);
698 			if (!disk->part) {
699 				free_disk_stats(disk);
700 				kfree(disk);
701 				return NULL;
702 			}
703 		}
704 		disk->minors = minors;
705 		rand_initialize_disk(disk);
706 		disk->dev.class = &block_class;
707 		disk->dev.type = &disk_type;
708 		device_initialize(&disk->dev);
709 		INIT_WORK(&disk->async_notify,
710 			media_change_notify_thread);
711 	}
712 	return disk;
713 }
714 
715 EXPORT_SYMBOL(alloc_disk);
716 EXPORT_SYMBOL(alloc_disk_node);
717 
718 struct kobject *get_disk(struct gendisk *disk)
719 {
720 	struct module *owner;
721 	struct kobject *kobj;
722 
723 	if (!disk->fops)
724 		return NULL;
725 	owner = disk->fops->owner;
726 	if (owner && !try_module_get(owner))
727 		return NULL;
728 	kobj = kobject_get(&disk->dev.kobj);
729 	if (kobj == NULL) {
730 		module_put(owner);
731 		return NULL;
732 	}
733 	return kobj;
734 
735 }
736 
737 EXPORT_SYMBOL(get_disk);
738 
739 void put_disk(struct gendisk *disk)
740 {
741 	if (disk)
742 		kobject_put(&disk->dev.kobj);
743 }
744 
745 EXPORT_SYMBOL(put_disk);
746 
747 void set_device_ro(struct block_device *bdev, int flag)
748 {
749 	if (bdev->bd_contains != bdev)
750 		bdev->bd_part->policy = flag;
751 	else
752 		bdev->bd_disk->policy = flag;
753 }
754 
755 EXPORT_SYMBOL(set_device_ro);
756 
757 void set_disk_ro(struct gendisk *disk, int flag)
758 {
759 	int i;
760 	disk->policy = flag;
761 	for (i = 0; i < disk->minors - 1; i++)
762 		if (disk->part[i]) disk->part[i]->policy = flag;
763 }
764 
765 EXPORT_SYMBOL(set_disk_ro);
766 
767 int bdev_read_only(struct block_device *bdev)
768 {
769 	if (!bdev)
770 		return 0;
771 	else if (bdev->bd_contains != bdev)
772 		return bdev->bd_part->policy;
773 	else
774 		return bdev->bd_disk->policy;
775 }
776 
777 EXPORT_SYMBOL(bdev_read_only);
778 
779 int invalidate_partition(struct gendisk *disk, int index)
780 {
781 	int res = 0;
782 	struct block_device *bdev = bdget_disk(disk, index);
783 	if (bdev) {
784 		fsync_bdev(bdev);
785 		res = __invalidate_device(bdev);
786 		bdput(bdev);
787 	}
788 	return res;
789 }
790 
791 EXPORT_SYMBOL(invalidate_partition);
792