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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.    ataraid.c  Copyright (C) 2001 Red Hat, Inc. All rights reserved.
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2, or (at your option)
  6.    any later version.
  7.    
  8.    You should have received a copy of the GNU General Public License
  9.    (for example /usr/src/linux/COPYING); if not, write to the Free
  10.    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  11.    
  12.    Authors:  Arjan van de Ven <arjanv@redhat.com>
  13.    
  14.    
  15. */
  16. #include <linux/module.h>
  17. #include <linux/init.h>
  18. #include <linux/kernel.h>
  19. #include <linux/mm.h>
  20. #include <asm/semaphore.h>
  21. #include <linux/sched.h>
  22. #include <linux/smp_lock.h>
  23. #include <linux/blkdev.h>
  24. #include <linux/blkpg.h>
  25. #include <linux/genhd.h>
  26. #include <linux/ioctl.h>
  27. #include <linux/kdev_t.h>
  28. #include <linux/swap.h>
  29. #include <linux/ide.h>
  30. #include <asm/uaccess.h>
  31. #include "ataraid.h"
  32.                                         
  33. static int ataraid_hardsect_size[256];
  34. static int ataraid_blksize_size[256];
  35. static struct raid_device_operations* ataraid_ops[16];
  36. static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
  37. static int ataraid_open(struct inode * inode, struct file * filp);
  38. static int ataraid_release(struct inode * inode, struct file * filp);
  39. static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh);
  40. struct gendisk ataraid_gendisk;
  41. static int ataraid_gendisk_sizes[256];
  42. static int ataraid_readahead[256];
  43. static struct block_device_operations ataraid_fops = {
  44. owner: THIS_MODULE,
  45. open:                   ataraid_open,
  46. release:                ataraid_release,
  47. ioctl:                  ataraid_ioctl,
  48. };
  49.                 
  50. static DECLARE_MUTEX(ataraid_sem);
  51. /* Bitmap for the devices currently in use */
  52. static unsigned int ataraiduse;
  53. /* stub fops functions */
  54. static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)  
  55. {
  56. int minor;
  57. minor = MINOR(inode->i_rdev)>>SHIFT;
  58. if ((ataraid_ops[minor])&&(ataraid_ops[minor]->ioctl))
  59. return (ataraid_ops[minor]->ioctl)(inode,file,cmd,arg);
  60. return -EINVAL;
  61. }
  62. static int ataraid_open(struct inode * inode, struct file * filp)
  63. {
  64. int minor;
  65. minor = MINOR(inode->i_rdev)>>SHIFT;
  66. if ((ataraid_ops[minor])&&(ataraid_ops[minor]->open))
  67. return (ataraid_ops[minor]->open)(inode,filp);
  68. return -EINVAL;
  69. }
  70. static int ataraid_release(struct inode * inode, struct file * filp)
  71. {
  72. int minor;
  73. minor = MINOR(inode->i_rdev)>>SHIFT;
  74. if ((ataraid_ops[minor])&&(ataraid_ops[minor]->release))
  75. return (ataraid_ops[minor]->release)(inode,filp);
  76. return -EINVAL;
  77. }
  78. static int ataraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
  79. {
  80. int minor;
  81. int retval;
  82. minor = MINOR(bh->b_rdev)>>SHIFT;
  83. if ((ataraid_ops[minor])&&(ataraid_ops[minor]->make_request)) {
  84. retval= (ataraid_ops[minor]->make_request)(q,rw,bh);
  85. if (retval == -1) {
  86. ataraid_split_request(q,rw,bh);
  87. return 0;
  88. } else
  89. return retval;
  90. }
  91. return -EINVAL;
  92. }
  93. struct buffer_head *ataraid_get_bhead(void)
  94. {
  95. void *ptr = NULL;
  96. while (!ptr) {
  97. ptr=kmalloc(sizeof(struct buffer_head),GFP_NOIO);
  98. if (!ptr) {
  99. __set_current_state(TASK_RUNNING);
  100.                 current->policy |= SCHED_YIELD;
  101.                 schedule();             
  102. }
  103. }
  104. return ptr;
  105. }
  106. EXPORT_SYMBOL(ataraid_get_bhead);
  107. struct ataraid_bh_private *ataraid_get_private(void)
  108. {
  109. void *ptr = NULL;
  110. while (!ptr) {
  111. ptr=kmalloc(sizeof(struct ataraid_bh_private),GFP_NOIO);
  112. if (!ptr) {
  113. __set_current_state(TASK_RUNNING);
  114.                 current->policy |= SCHED_YIELD;
  115.                 schedule();             
  116. }
  117. }
  118. return ptr;
  119. }
  120. EXPORT_SYMBOL(ataraid_get_private);
  121. void ataraid_end_request(struct buffer_head *bh, int uptodate)
  122. {
  123. struct ataraid_bh_private *private = bh->b_private;
  124. if (private==NULL)
  125. BUG();
  126. if (atomic_dec_and_test(&private->count)) {
  127. private->parent->b_end_io(private->parent,uptodate);
  128. private->parent = NULL;
  129. kfree(private);
  130. }
  131. kfree(bh);
  132. }
  133. EXPORT_SYMBOL(ataraid_end_request);
  134. static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh)
  135. {
  136. struct buffer_head *bh1,*bh2;
  137. struct ataraid_bh_private *private;
  138. bh1=ataraid_get_bhead();
  139. bh2=ataraid_get_bhead();
  140. /* If either of those ever fails we're doomed */
  141. if ((!bh1)||(!bh2))
  142. BUG();
  143. private = ataraid_get_private();
  144. if (private==NULL)
  145. BUG();
  146. memcpy(bh1, bh, sizeof(*bh));
  147. memcpy(bh2, bh, sizeof(*bh));
  148. bh1->b_end_io = ataraid_end_request;
  149. bh2->b_end_io = ataraid_end_request;
  150. bh2->b_rsector += bh->b_size >> 10;
  151. bh1->b_size /= 2;
  152. bh2->b_size /= 2;
  153. private->parent = bh;
  154. bh1->b_private = private;
  155. bh2->b_private = private;
  156. atomic_set(&private->count,2);
  157. bh2->b_data +=  bh->b_size/2;
  158. generic_make_request(rw,bh1);
  159. generic_make_request(rw,bh2);
  160. }
  161. /* device register / release functions */
  162. int ataraid_get_device(struct raid_device_operations *fops)
  163. {
  164. int bit;
  165. down(&ataraid_sem);
  166. if (ataraiduse==~0U) {
  167. up(&ataraid_sem);
  168. return -ENODEV;
  169. }
  170. bit=ffz(ataraiduse); 
  171. ataraiduse |= 1<<bit;
  172. ataraid_ops[bit] = fops;
  173. up(&ataraid_sem);
  174. return bit;
  175. }
  176. void ataraid_release_device(int device)
  177. {
  178. down(&ataraid_sem);
  179. if ((ataraiduse & (1<<device))==0)
  180. BUG(); /* device wasn't registered at all */
  181. ataraiduse &= ~(1<<device);
  182. ataraid_ops[device] = NULL;
  183. up(&ataraid_sem);
  184. }
  185. void ataraid_register_disk(int device,long size)
  186. {
  187. register_disk(&ataraid_gendisk, MKDEV(ATAMAJOR,16*device),16,
  188. &ataraid_fops,size);
  189. }
  190. static __init int ataraid_init(void) 
  191. {
  192. int i;
  193.         for(i=0;i<256;i++)
  194. {
  195.          ataraid_hardsect_size[i] = 512;
  196. ataraid_blksize_size[i] = 1024;  
  197. ataraid_readahead[i] = 1023;
  198. }
  199. if (blksize_size[ATAMAJOR]==NULL)
  200. blksize_size[ATAMAJOR] = ataraid_blksize_size;
  201. if (hardsect_size[ATAMAJOR]==NULL)
  202. hardsect_size[ATAMAJOR] = ataraid_hardsect_size;
  203. /* setup the gendisk structure */
  204. ataraid_gendisk.part = kmalloc(256 * sizeof(struct hd_struct),GFP_KERNEL);
  205. if (ataraid_gendisk.part==NULL) {
  206. printk(KERN_ERR "ataraid: Couldn't allocate memory, aborting n");
  207. return -1;
  208. }
  209. memset(&ataraid_gendisk.part[0],0,256*sizeof(struct hd_struct));
  210. ataraid_gendisk.major       = ATAMAJOR;
  211. ataraid_gendisk.major_name  = "ataraid";
  212. ataraid_gendisk.minor_shift = 4;
  213. ataraid_gendisk.max_p     = 15;
  214. ataraid_gendisk.sizes     = &ataraid_gendisk_sizes[0];
  215. ataraid_gendisk.nr_real     = 16;
  216. ataraid_gendisk.fops        = &ataraid_fops;
  217. add_gendisk(&ataraid_gendisk);
  218. if (register_blkdev(ATAMAJOR, "ataraid", &ataraid_fops)) {
  219. printk(KERN_ERR "ataraid: Could not get major %d n",ATAMAJOR);
  220. return -1;
  221. }
  222.                 
  223. blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR),ataraid_make_request);
  224.                                                                                      
  225. return 0;                                                        
  226. }
  227. static void __exit ataraid_exit(void)
  228. {
  229. unregister_blkdev(ATAMAJOR, "ataraid");
  230. hardsect_size[ATAMAJOR] = NULL;
  231. blk_size[ATAMAJOR] = NULL;
  232. blksize_size[ATAMAJOR] = NULL;                       
  233. max_readahead[ATAMAJOR] = NULL;
  234. del_gendisk(&ataraid_gendisk);
  235.         
  236. if (ataraid_gendisk.part) {
  237. kfree(ataraid_gendisk.part);
  238. ataraid_gendisk.part = NULL;
  239. }
  240. }
  241. module_init(ataraid_init);
  242. module_exit(ataraid_exit);
  243. EXPORT_SYMBOL(ataraid_get_device);
  244. EXPORT_SYMBOL(ataraid_release_device);
  245. EXPORT_SYMBOL(ataraid_gendisk);
  246. EXPORT_SYMBOL(ataraid_register_disk);
  247. MODULE_LICENSE("GPL");