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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/drivers/char/raw.c
  3.  *
  4.  * Front-end raw character devices.  These can be bound to any block
  5.  * devices to provide genuine Unix raw character device semantics.
  6.  *
  7.  * We reserve minor number 0 for a control interface.  ioctl()s on this
  8.  * device are used to bind the other minor numbers to block devices.
  9.  */
  10. #include <linux/fs.h>
  11. #include <linux/iobuf.h>
  12. #include <linux/major.h>
  13. #include <linux/blkdev.h>
  14. #include <linux/raw.h>
  15. #include <linux/capability.h>
  16. #include <linux/smp_lock.h>
  17. #include <asm/uaccess.h>
  18. #define dprintk(x...) 
  19. typedef struct raw_device_data_s {
  20. struct block_device *binding;
  21. int inuse, sector_size, sector_bits;
  22. struct semaphore mutex;
  23. } raw_device_data_t;
  24. static raw_device_data_t raw_devices[256];
  25. static ssize_t rw_raw_dev(int rw, struct file *, char *, size_t, loff_t *);
  26. ssize_t raw_read(struct file *, char *, size_t, loff_t *);
  27. ssize_t raw_write(struct file *, const char *, size_t, loff_t *);
  28. int raw_open(struct inode *, struct file *);
  29. int raw_release(struct inode *, struct file *);
  30. int raw_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
  31. int raw_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
  32. static struct file_operations raw_fops = {
  33. read: raw_read,
  34. write: raw_write,
  35. open: raw_open,
  36. release: raw_release,
  37. ioctl: raw_ioctl,
  38. };
  39. static struct file_operations raw_ctl_fops = {
  40. ioctl: raw_ctl_ioctl,
  41. open: raw_open,
  42. };
  43. static int __init raw_init(void)
  44. {
  45. int i;
  46. register_chrdev(RAW_MAJOR, "raw", &raw_fops);
  47. for (i = 0; i < 256; i++)
  48. init_MUTEX(&raw_devices[i].mutex);
  49. return 0;
  50. }
  51. __initcall(raw_init);
  52. /* 
  53.  * Open/close code for raw IO.
  54.  */
  55. int raw_open(struct inode *inode, struct file *filp)
  56. {
  57. int minor;
  58. struct block_device * bdev;
  59. kdev_t rdev; /* it should eventually go away */
  60. int err;
  61. int sector_size;
  62. int sector_bits;
  63. minor = MINOR(inode->i_rdev);
  64. /* 
  65.  * Is it the control device? 
  66.  */
  67. if (minor == 0) {
  68. filp->f_op = &raw_ctl_fops;
  69. return 0;
  70. }
  71. if (!filp->f_iobuf) {
  72. err = alloc_kiovec(1, &filp->f_iobuf);
  73. if (err)
  74. return err;
  75. }
  76. down(&raw_devices[minor].mutex);
  77. /*
  78.  * No, it is a normal raw device.  All we need to do on open is
  79.  * to check that the device is bound, and force the underlying
  80.  * block device to a sector-size blocksize. 
  81.  */
  82. bdev = raw_devices[minor].binding;
  83. err = -ENODEV;
  84. if (!bdev)
  85. goto out;
  86. atomic_inc(&bdev->bd_count);
  87. rdev = to_kdev_t(bdev->bd_dev);
  88. err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
  89. if (err)
  90. goto out;
  91. /*
  92.  * Don't change the blocksize if we already have users using
  93.  * this device 
  94.  */
  95. if (raw_devices[minor].inuse++)
  96. goto out;
  97. /* 
  98.  * Don't interfere with mounted devices: we cannot safely set
  99.  * the blocksize on a device which is already mounted.  
  100.  */
  101. sector_size = 512;
  102. if (is_mounted(rdev)) {
  103. if (blksize_size[MAJOR(rdev)])
  104. sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];
  105. } else {
  106. if (hardsect_size[MAJOR(rdev)])
  107. sector_size = hardsect_size[MAJOR(rdev)][MINOR(rdev)];
  108. }
  109. set_blocksize(rdev, sector_size);
  110. raw_devices[minor].sector_size = sector_size;
  111. for (sector_bits = 0; !(sector_size & 1); )
  112. sector_size>>=1, sector_bits++;
  113. raw_devices[minor].sector_bits = sector_bits;
  114.  out:
  115. up(&raw_devices[minor].mutex);
  116. return err;
  117. }
  118. int raw_release(struct inode *inode, struct file *filp)
  119. {
  120. int minor;
  121. struct block_device *bdev;
  122. minor = MINOR(inode->i_rdev);
  123. down(&raw_devices[minor].mutex);
  124. bdev = raw_devices[minor].binding;
  125. raw_devices[minor].inuse--;
  126. up(&raw_devices[minor].mutex);
  127. blkdev_put(bdev, BDEV_RAW);
  128. return 0;
  129. }
  130. /* Forward ioctls to the underlying block device. */ 
  131. int raw_ioctl(struct inode *inode, 
  132.   struct file *flip,
  133.   unsigned int command, 
  134.   unsigned long arg)
  135. {
  136. int minor = minor(inode->i_rdev), err; 
  137. struct block_device *b; 
  138. if (minor < 1 && minor > 255)
  139. return -ENODEV;
  140. b = raw_devices[minor].binding;
  141. err = -EINVAL; 
  142. if (b && b->bd_inode && b->bd_op && b->bd_op->ioctl) { 
  143. err = b->bd_op->ioctl(b->bd_inode, NULL, command, arg); 
  144. return err;
  145. /*
  146.  * Deal with ioctls against the raw-device control interface, to bind
  147.  * and unbind other raw devices.  
  148.  */
  149. int raw_ctl_ioctl(struct inode *inode, 
  150.   struct file *flip,
  151.   unsigned int command, 
  152.   unsigned long arg)
  153. {
  154. struct raw_config_request rq;
  155. int err = 0;
  156. int minor;
  157. switch (command) {
  158. case RAW_SETBIND:
  159. case RAW_GETBIND:
  160. /* First, find out which raw minor we want */
  161. err = copy_from_user(&rq, (void *) arg, sizeof(rq));
  162. if (err)
  163. break;
  164. minor = rq.raw_minor;
  165. if (minor <= 0 || minor > MINORMASK) {
  166. err = -EINVAL;
  167. break;
  168. }
  169. if (command == RAW_SETBIND) {
  170. /*
  171.  * This is like making block devices, so demand the
  172.  * same capability
  173.  */
  174. if (!capable(CAP_SYS_ADMIN)) {
  175. err = -EPERM;
  176. break;
  177. }
  178. /* 
  179.  * For now, we don't need to check that the underlying
  180.  * block device is present or not: we can do that when
  181.  * the raw device is opened.  Just check that the
  182.  * major/minor numbers make sense. 
  183.  */
  184. if ((rq.block_major == NODEV && 
  185.      rq.block_minor != NODEV) ||
  186.     rq.block_major > MAX_BLKDEV ||
  187.     rq.block_minor > MINORMASK) {
  188. err = -EINVAL;
  189. break;
  190. }
  191. down(&raw_devices[minor].mutex);
  192. if (raw_devices[minor].inuse) {
  193. up(&raw_devices[minor].mutex);
  194. err = -EBUSY;
  195. break;
  196. }
  197. if (raw_devices[minor].binding)
  198. bdput(raw_devices[minor].binding);
  199. raw_devices[minor].binding = 
  200. bdget(kdev_t_to_nr(MKDEV(rq.block_major, rq.block_minor)));
  201. up(&raw_devices[minor].mutex);
  202. } else {
  203. struct block_device *bdev;
  204. kdev_t dev;
  205. bdev = raw_devices[minor].binding;
  206. if (bdev) {
  207. dev = to_kdev_t(bdev->bd_dev);
  208. rq.block_major = MAJOR(dev);
  209. rq.block_minor = MINOR(dev);
  210. } else {
  211. rq.block_major = rq.block_minor = 0;
  212. }
  213. err = copy_to_user((void *) arg, &rq, sizeof(rq));
  214. }
  215. break;
  216. default:
  217. err = -EINVAL;
  218. }
  219. return err;
  220. }
  221. ssize_t raw_read(struct file *filp, char * buf, 
  222.  size_t size, loff_t *offp)
  223. {
  224. return rw_raw_dev(READ, filp, buf, size, offp);
  225. }
  226. ssize_t raw_write(struct file *filp, const char *buf, 
  227.   size_t size, loff_t *offp)
  228. {
  229. return rw_raw_dev(WRITE, filp, (char *) buf, size, offp);
  230. }
  231. #define SECTOR_BITS 9
  232. #define SECTOR_SIZE (1U << SECTOR_BITS)
  233. #define SECTOR_MASK (SECTOR_SIZE - 1)
  234. ssize_t rw_raw_dev(int rw, struct file *filp, char *buf, 
  235.    size_t size, loff_t *offp)
  236. {
  237. struct kiobuf * iobuf;
  238. int new_iobuf;
  239. int err = 0;
  240. unsigned long blocknr, blocks;
  241. size_t transferred;
  242. int iosize;
  243. int i;
  244. int minor;
  245. kdev_t dev;
  246. unsigned long limit;
  247. int sector_size, sector_bits, sector_mask;
  248. int max_sectors;
  249. /*
  250.  * First, a few checks on device size limits 
  251.  */
  252. minor = MINOR(filp->f_dentry->d_inode->i_rdev);
  253. new_iobuf = 0;
  254. iobuf = filp->f_iobuf;
  255. if (test_and_set_bit(0, &filp->f_iobuf_lock)) {
  256. /*
  257.  * A parallel read/write is using the preallocated iobuf
  258.  * so just run slow and allocate a new one.
  259.  */
  260. err = alloc_kiovec(1, &iobuf);
  261. if (err)
  262. goto out;
  263. new_iobuf = 1;
  264. }
  265. dev = to_kdev_t(raw_devices[minor].binding->bd_dev);
  266. sector_size = raw_devices[minor].sector_size;
  267. sector_bits = raw_devices[minor].sector_bits;
  268. sector_mask = sector_size- 1;
  269. max_sectors = KIO_MAX_SECTORS >> (sector_bits - 9);
  270. if (blk_size[MAJOR(dev)])
  271. limit = (((loff_t) blk_size[MAJOR(dev)][MINOR(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
  272. else
  273. limit = INT_MAX;
  274. dprintk ("rw_raw_dev: dev %d:%d (+%d)n",
  275.  MAJOR(dev), MINOR(dev), limit);
  276. err = -EINVAL;
  277. if ((*offp & sector_mask) || (size & sector_mask))
  278. goto out_free;
  279. err = 0;
  280. if (size)
  281. err = -ENXIO;
  282. if ((*offp >> sector_bits) >= limit)
  283. goto out_free;
  284. /*
  285.  * Split the IO into KIO_MAX_SECTORS chunks, mapping and
  286.  * unmapping the single kiobuf as we go to perform each chunk of
  287.  * IO.  
  288.  */
  289. transferred = 0;
  290. blocknr = *offp >> sector_bits;
  291. while (size > 0) {
  292. blocks = size >> sector_bits;
  293. if (blocks > max_sectors)
  294. blocks = max_sectors;
  295. if (blocks > limit - blocknr)
  296. blocks = limit - blocknr;
  297. if (!blocks)
  298. break;
  299. iosize = blocks << sector_bits;
  300. err = map_user_kiobuf(rw, iobuf, (unsigned long) buf, iosize);
  301. if (err)
  302. break;
  303. for (i=0; i < blocks; i++) 
  304. iobuf->blocks[i] = blocknr++;
  305. err = brw_kiovec(rw, 1, &iobuf, dev, iobuf->blocks, sector_size);
  306. if (rw == READ && err > 0)
  307. mark_dirty_kiobuf(iobuf, err);
  308. if (err >= 0) {
  309. transferred += err;
  310. size -= err;
  311. buf += err;
  312. }
  313. unmap_kiobuf(iobuf);
  314. if (err != iosize)
  315. break;
  316. }
  317. if (transferred) {
  318. *offp += transferred;
  319. err = transferred;
  320. }
  321.  out_free:
  322. if (!new_iobuf)
  323. clear_bit(0, &filp->f_iobuf_lock);
  324. else
  325. free_kiovec(1, &iobuf);
  326.  out:
  327. return err;
  328. }