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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.    linear.c : Multiple Devices driver for Linux
  3.               Copyright (C) 1994-96 Marc ZYNGIER
  4.       <zyngier@ufr-info-p7.ibp.fr> or
  5.       <maz@gloups.fdn.fr>
  6.    Linear mode management functions.
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2, or (at your option)
  10.    any later version.
  11.    
  12.    You should have received a copy of the GNU General Public License
  13.    (for example /usr/src/linux/COPYING); if not, write to the Free
  14.    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  15. */
  16. #include <linux/module.h>
  17. #include <linux/raid/md.h>
  18. #include <linux/slab.h>
  19. #include <linux/raid/linear.h>
  20. #define MAJOR_NR MD_MAJOR
  21. #define MD_DRIVER
  22. #define MD_PERSONALITY
  23. static int linear_run (mddev_t *mddev)
  24. {
  25. linear_conf_t *conf;
  26. struct linear_hash *table;
  27. mdk_rdev_t *rdev;
  28. int size, i, j, nb_zone;
  29. unsigned int curr_offset;
  30. MOD_INC_USE_COUNT;
  31. conf = kmalloc (sizeof (*conf), GFP_KERNEL);
  32. if (!conf)
  33. goto out;
  34. mddev->private = conf;
  35. if (md_check_ordering(mddev)) {
  36. printk("linear: disks are not ordered, aborting!n");
  37. goto out;
  38. }
  39. /*
  40.  * Find the smallest device.
  41.  */
  42. conf->smallest = NULL;
  43. curr_offset = 0;
  44. ITERATE_RDEV_ORDERED(mddev,rdev,j) {
  45. dev_info_t *disk = conf->disks + j;
  46. disk->dev = rdev->dev;
  47. disk->size = rdev->size;
  48. disk->offset = curr_offset;
  49. curr_offset += disk->size;
  50. if (!conf->smallest || (disk->size < conf->smallest->size))
  51. conf->smallest = disk;
  52. }
  53. nb_zone = conf->nr_zones =
  54. md_size[mdidx(mddev)] / conf->smallest->size +
  55. ((md_size[mdidx(mddev)] % conf->smallest->size) ? 1 : 0);
  56.   
  57. conf->hash_table = kmalloc (sizeof (struct linear_hash) * nb_zone,
  58. GFP_KERNEL);
  59. if (!conf->hash_table)
  60. goto out;
  61. /*
  62.  * Here we generate the linear hash table
  63.  */
  64. table = conf->hash_table;
  65. i = 0;
  66. size = 0;
  67. for (j = 0; j < mddev->nb_dev; j++) {
  68. dev_info_t *disk = conf->disks + j;
  69. if (size < 0) {
  70. table[-1].dev1 = disk;
  71. }
  72. size += disk->size;
  73. while (size>0) {
  74. table->dev0 = disk;
  75. table->dev1 = NULL;
  76. size -= conf->smallest->size;
  77. table++;
  78. }
  79. }
  80. if (table-conf->hash_table != nb_zone)
  81. BUG();
  82. return 0;
  83. out:
  84. if (conf)
  85. kfree(conf);
  86. MOD_DEC_USE_COUNT;
  87. return 1;
  88. }
  89. static int linear_stop (mddev_t *mddev)
  90. {
  91. linear_conf_t *conf = mddev_to_conf(mddev);
  92.   
  93. kfree(conf->hash_table);
  94. kfree(conf);
  95. MOD_DEC_USE_COUNT;
  96. return 0;
  97. }
  98. static int linear_make_request (mddev_t *mddev,
  99. int rw, struct buffer_head * bh)
  100. {
  101.         linear_conf_t *conf = mddev_to_conf(mddev);
  102.         struct linear_hash *hash;
  103.         dev_info_t *tmp_dev;
  104.         long block;
  105. block = bh->b_rsector >> 1;
  106. hash = conf->hash_table + (block / conf->smallest->size);
  107.   
  108. if (block >= (hash->dev0->size + hash->dev0->offset)) {
  109. if (!hash->dev1) {
  110. printk ("linear_make_request : hash->dev1==NULL for block %ldn",
  111. block);
  112. buffer_IO_error(bh);
  113. return 0;
  114. }
  115. tmp_dev = hash->dev1;
  116. } else
  117. tmp_dev = hash->dev0;
  118.     
  119. if (block >= (tmp_dev->size + tmp_dev->offset)
  120. || block < tmp_dev->offset) {
  121. printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ldn", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
  122. buffer_IO_error(bh);
  123. return 0;
  124. }
  125. bh->b_rdev = tmp_dev->dev;
  126. bh->b_rsector = bh->b_rsector - (tmp_dev->offset << 1);
  127. return 1;
  128. }
  129. static int linear_status (char *page, mddev_t *mddev)
  130. {
  131. int sz = 0;
  132. #undef MD_DEBUG
  133. #ifdef MD_DEBUG
  134. int j;
  135. linear_conf_t *conf = mddev_to_conf(mddev);
  136.   
  137. sz += sprintf(page+sz, "      ");
  138. for (j = 0; j < conf->nr_zones; j++)
  139. {
  140. sz += sprintf(page+sz, "[%s",
  141. partition_name(conf->hash_table[j].dev0->dev));
  142. if (conf->hash_table[j].dev1)
  143. sz += sprintf(page+sz, "/%s] ",
  144.   partition_name(conf->hash_table[j].dev1->dev));
  145. else
  146. sz += sprintf(page+sz, "] ");
  147. }
  148. sz += sprintf(page+sz, "n");
  149. #endif
  150. sz += sprintf(page+sz, " %dk rounding", mddev->param.chunk_size/1024);
  151. return sz;
  152. }
  153. static mdk_personality_t linear_personality=
  154. {
  155. name: "linear",
  156. make_request: linear_make_request,
  157. run: linear_run,
  158. stop: linear_stop,
  159. status: linear_status,
  160. };
  161. static int md__init linear_init (void)
  162. {
  163. return register_md_personality (LINEAR, &linear_personality);
  164. }
  165. static void linear_exit (void)
  166. {
  167. unregister_md_personality (LINEAR);
  168. }
  169. module_init(linear_init);
  170. module_exit(linear_exit);
  171. MODULE_LICENSE("GPL");