genhd.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

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. #include <linux/seq_file.h>
  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. static rwlock_t gendisk_lock = RW_LOCK_UNLOCKED;
  33. EXPORT_SYMBOL(gendisk_head);
  34. /**
  35.  * add_gendisk - add partitioning information to kernel list
  36.  * @gp: per-device partitioning information
  37.  *
  38.  * This function registers the partitioning information in @gp
  39.  * with the kernel.
  40.  */
  41. void
  42. add_gendisk(struct gendisk *gp)
  43. {
  44. struct gendisk *sgp;
  45. write_lock(&gendisk_lock);
  46. /*
  47.    * In 2.5 this will go away. Fix the drivers who rely on
  48.    * old behaviour.
  49.    */
  50. for (sgp = gendisk_head; sgp; sgp = sgp->next)
  51. {
  52. if (sgp == gp)
  53. {
  54. // printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!n",
  55. // sgp->major)
  56. goto out;
  57. }
  58. }
  59. gendisk_array[gp->major] = gp;
  60. gp->next = gendisk_head;
  61. gendisk_head = gp;
  62. out:
  63. write_unlock(&gendisk_lock);
  64. }
  65. EXPORT_SYMBOL(add_gendisk);
  66. /**
  67.  * del_gendisk - remove partitioning information from kernel list
  68.  * @gp: per-device partitioning information
  69.  *
  70.  * This function unregisters the partitioning information in @gp
  71.  * with the kernel.
  72.  */
  73. void
  74. del_gendisk(struct gendisk *gp)
  75. {
  76. struct gendisk **gpp;
  77. write_lock(&gendisk_lock);
  78. gendisk_array[gp->major] = NULL;
  79. for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
  80. if (*gpp == gp)
  81. break;
  82. if (*gpp)
  83. *gpp = (*gpp)->next;
  84. write_unlock(&gendisk_lock);
  85. }
  86. EXPORT_SYMBOL(del_gendisk);
  87. /**
  88.  * get_gendisk - get partitioning information for a given device
  89.  * @dev: device to get partitioning information for
  90.  *
  91.  * This function gets the structure containing partitioning
  92.  * information for the given device @dev.
  93.  */
  94. struct gendisk *
  95. get_gendisk(kdev_t dev)
  96. {
  97. struct gendisk *gp = NULL;
  98. int maj = MAJOR(dev);
  99. read_lock(&gendisk_lock);
  100. if ((gp = gendisk_array[maj]))
  101. goto out;
  102. /* This is needed for early 2.4 source compatiblity.  --hch */
  103. for (gp = gendisk_head; gp; gp = gp->next)
  104. if (gp->major == maj)
  105. break;
  106. out:
  107. read_unlock(&gendisk_lock);
  108. return gp;
  109. }
  110. EXPORT_SYMBOL(get_gendisk);
  111. /**
  112.  * walk_gendisk - issue a command for every registered gendisk
  113.  * @walk: user-specified callback
  114.  * @data: opaque data for the callback
  115.  *
  116.  * This function walks through the gendisk chain and calls back
  117.  * into @walk for every element.
  118.  */
  119. int
  120. walk_gendisk(int (*walk)(struct gendisk *, void *), void *data)
  121. {
  122. struct gendisk *gp;
  123. int error = 0;
  124. read_lock(&gendisk_lock);
  125. for (gp = gendisk_head; gp; gp = gp->next)
  126. if ((error = walk(gp, data)))
  127. break;
  128. read_unlock(&gendisk_lock);
  129. return error;
  130. }
  131. #ifdef CONFIG_PROC_FS
  132. /* iterator */
  133. static void *part_start(struct seq_file *s, loff_t *ppos)
  134. {
  135. struct gendisk *gp;
  136. loff_t pos = *ppos;
  137. read_lock(&gendisk_lock);
  138. for (gp = gendisk_head; gp; gp = gp->next)
  139. if (!pos--)
  140. return gp;
  141. return NULL;
  142. }
  143. static void *part_next(struct seq_file *s, void *v, loff_t *pos)
  144. {
  145. ++*pos;
  146. return ((struct gendisk *)v)->next;
  147. }
  148. static void part_stop(struct seq_file *s, void *v)
  149. {
  150. read_unlock(&gendisk_lock);
  151. }
  152. static int part_show(struct seq_file *s, void *v)
  153. {
  154. struct gendisk *gp = v;
  155. char buf[64];
  156. int n;
  157. if (gp == gendisk_head) {
  158. seq_puts(s, "major minor  #blocks  name"
  159. #ifdef CONFIG_BLK_STATS
  160.     "     rio rmerge rsect ruse wio wmerge "
  161.     "wsect wuse running use aveq"
  162. #endif
  163.    "nn");
  164. }
  165. /* show the full disk and all non-0 size partitions of it */
  166. for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
  167. if (gp->part[n].nr_sects) {
  168. #ifdef CONFIG_BLK_STATS
  169. struct hd_struct *hd = &gp->part[n];
  170. disk_round_stats(hd);
  171. seq_printf(s, "%4d  %4d %10d %s "
  172.       "%d %d %d %d %d %d %d %d %d %d %dn",
  173.       gp->major, n, gp->sizes[n],
  174.       disk_name(gp, n, buf),
  175.       hd->rd_ios, hd->rd_merges,
  176. #define MSEC(x) ((x) * 1000 / HZ)
  177.       hd->rd_sectors, MSEC(hd->rd_ticks),
  178.       hd->wr_ios, hd->wr_merges,
  179.       hd->wr_sectors, MSEC(hd->wr_ticks),
  180.       hd->ios_in_flight, MSEC(hd->io_ticks),
  181.       MSEC(hd->aveq));
  182. #else
  183. seq_printf(s, "%4d  %4d %10d %sn",
  184.    gp->major, n, gp->sizes[n],
  185.    disk_name(gp, n, buf));
  186. #endif /* CONFIG_BLK_STATS */
  187. }
  188. }
  189. return 0;
  190. }
  191. struct seq_operations partitions_op = {
  192. .start = part_start,
  193. .next = part_next,
  194. .stop = part_stop,
  195. .show = part_show,
  196. };
  197. #endif
  198. extern int blk_dev_init(void);
  199. extern int net_dev_init(void);
  200. extern void console_map_init(void);
  201. extern int atmdev_init(void);
  202. int __init device_init(void)
  203. {
  204. blk_dev_init();
  205. sti();
  206. #ifdef CONFIG_NET
  207. net_dev_init();
  208. #endif
  209. #ifdef CONFIG_ATM
  210. (void) atmdev_init();
  211. #endif
  212. #ifdef CONFIG_VT
  213. console_map_init();
  214. #endif
  215. return 0;
  216. }
  217. __initcall(device_init);