genhd.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  Code extracted from
  3.  *  linux/kernel/hd.c
  4.  *
  5.  *  Copyright (C) 1991-1998  Linus Torvalds
  6.  *
  7.  *  devfs support - jj, rgooch, 980122
  8.  *
  9.  *  Moved partition checking code to fs/partitions* - Russell King
  10.  *  (linux@arm.uk.linux.org)
  11.  */
  12. /*
  13.  * TODO:  rip out the remaining init crap from this file  --hch
  14.  */
  15. #include <linux/config.h>
  16. #include <linux/module.h>
  17. #include <linux/fs.h>
  18. #include <linux/genhd.h>
  19. #include <linux/kernel.h>
  20. #include <linux/blk.h>
  21. #include <linux/init.h>
  22. #include <linux/spinlock.h>
  23. static rwlock_t gendisk_lock;
  24. /*
  25.  * Global kernel list of partitioning information.
  26.  *
  27.  * XXX: you should _never_ access this directly.
  28.  * the only reason this is exported is source compatiblity.
  29.  */
  30. /*static*/ struct gendisk *gendisk_head;
  31. static struct gendisk *gendisk_array[MAX_BLKDEV];
  32. EXPORT_SYMBOL(gendisk_head);
  33. /**
  34.  * add_gendisk - add partitioning information to kernel list
  35.  * @gp: per-device partitioning information
  36.  *
  37.  * This function registers the partitioning information in @gp
  38.  * with the kernel.
  39.  */
  40. void
  41. add_gendisk(struct gendisk *gp)
  42. {
  43. struct gendisk *sgp;
  44. write_lock(&gendisk_lock);
  45. /*
  46.    * In 2.5 this will go away. Fix the drivers who rely on
  47.    * old behaviour.
  48.    */
  49. for (sgp = gendisk_head; sgp; sgp = sgp->next)
  50. {
  51. if (sgp == gp)
  52. {
  53. // printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!n",
  54. // sgp->major)
  55. goto out;
  56. }
  57. }
  58. gendisk_array[gp->major] = gp;
  59. gp->next = gendisk_head;
  60. gendisk_head = gp;
  61. out:
  62. write_unlock(&gendisk_lock);
  63. }
  64. EXPORT_SYMBOL(add_gendisk);
  65. /**
  66.  * del_gendisk - remove partitioning information from kernel list
  67.  * @gp: per-device partitioning information
  68.  *
  69.  * This function unregisters the partitioning information in @gp
  70.  * with the kernel.
  71.  */
  72. void
  73. del_gendisk(struct gendisk *gp)
  74. {
  75. struct gendisk **gpp;
  76. write_lock(&gendisk_lock);
  77. gendisk_array[gp->major] = NULL;
  78. for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
  79. if (*gpp == gp)
  80. break;
  81. if (*gpp)
  82. *gpp = (*gpp)->next;
  83. write_unlock(&gendisk_lock);
  84. }
  85. EXPORT_SYMBOL(del_gendisk);
  86. /**
  87.  * get_gendisk - get partitioning information for a given device
  88.  * @dev: device to get partitioning information for
  89.  *
  90.  * This function gets the structure containing partitioning
  91.  * information for the given device @dev.
  92.  */
  93. struct gendisk *
  94. get_gendisk(kdev_t dev)
  95. {
  96. struct gendisk *gp = NULL;
  97. int maj = MAJOR(dev);
  98. read_lock(&gendisk_lock);
  99. if ((gp = gendisk_array[maj]))
  100. goto out;
  101. /* This is needed for early 2.4 source compatiblity.  --hch */
  102. for (gp = gendisk_head; gp; gp = gp->next)
  103. if (gp->major == maj)
  104. break;
  105. out:
  106. read_unlock(&gendisk_lock);
  107. return gp;
  108. }
  109. EXPORT_SYMBOL(get_gendisk);
  110. #ifdef CONFIG_PROC_FS
  111. int
  112. get_partition_list(char *page, char **start, off_t offset, int count)
  113. {
  114. struct gendisk *gp;
  115. char buf[64];
  116. int len, n;
  117. len = sprintf(page, "major minor  #blocks  namenn");
  118. read_lock(&gendisk_lock);
  119. for (gp = gendisk_head; gp; gp = gp->next) {
  120. for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
  121. if (gp->part[n].nr_sects == 0)
  122. continue;
  123. len += snprintf(page + len, 63,
  124. "%4d  %4d %10d %sn",
  125. gp->major, n, gp->sizes[n],
  126. disk_name(gp, n, buf));
  127. if (len < offset)
  128. offset -= len, len = 0;
  129. else if (len >= offset + count)
  130. goto out;
  131. }
  132. }
  133. out:
  134. read_unlock(&gendisk_lock);
  135. *start = page + offset;
  136. len -= offset;
  137. if (len < 0)
  138. len = 0;
  139. return len > count ? count : len;
  140. }
  141. #endif
  142. extern int blk_dev_init(void);
  143. #ifdef CONFIG_FUSION_BOOT
  144. extern int fusion_init(void);
  145. #endif
  146. extern int net_dev_init(void);
  147. extern void console_map_init(void);
  148. extern int soc_probe(void);
  149. extern int atmdev_init(void);
  150. extern int i2o_init(void);
  151. extern int cpqarray_init(void);
  152. int __init device_init(void)
  153. {
  154. rwlock_init(&gendisk_lock);
  155. blk_dev_init();
  156. sti();
  157. #ifdef CONFIG_I2O
  158. i2o_init();
  159. #endif
  160. #ifdef CONFIG_FUSION_BOOT
  161. fusion_init();
  162. #endif
  163. #ifdef CONFIG_FC4_SOC
  164. /* This has to be done before scsi_dev_init */
  165. soc_probe();
  166. #endif
  167. #ifdef CONFIG_BLK_CPQ_DA
  168. cpqarray_init();
  169. #endif
  170. #ifdef CONFIG_NET
  171. net_dev_init();
  172. #endif
  173. #ifdef CONFIG_ATM
  174. (void) atmdev_init();
  175. #endif
  176. #ifdef CONFIG_VT
  177. console_map_init();
  178. #endif
  179. return 0;
  180. }
  181. __initcall(device_init);