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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * ramdisk.c - Multiple RAM disk driver - gzip-loading version - v. 0.8 beta.
  3.  * 
  4.  * (C) Chad Page, Theodore Ts'o, et. al, 1995. 
  5.  *
  6.  * This RAM disk is designed to have filesystems created on it and mounted
  7.  * just like a regular floppy disk.  
  8.  *  
  9.  * It also does something suggested by Linus: use the buffer cache as the
  10.  * RAM disk data.  This makes it possible to dynamically allocate the RAM disk
  11.  * buffer - with some consequences I have to deal with as I write this. 
  12.  * 
  13.  * This code is based on the original ramdisk.c, written mostly by
  14.  * Theodore Ts'o (TYT) in 1991.  The code was largely rewritten by
  15.  * Chad Page to use the buffer cache to store the RAM disk data in
  16.  * 1995; Theodore then took over the driver again, and cleaned it up
  17.  * for inclusion in the mainline kernel.
  18.  *
  19.  * The original CRAMDISK code was written by Richard Lyons, and
  20.  * adapted by Chad Page to use the new RAM disk interface.  Theodore
  21.  * Ts'o rewrote it so that both the compressed RAM disk loader and the
  22.  * kernel decompressor uses the same inflate.c codebase.  The RAM disk
  23.  * loader now also loads into a dynamic (buffer cache based) RAM disk,
  24.  * not the old static RAM disk.  Support for the old static RAM disk has
  25.  * been completely removed.
  26.  *
  27.  * Loadable module support added by Tom Dyas.
  28.  *
  29.  * Further cleanups by Chad Page (page0588@sundance.sjsu.edu):
  30.  * Cosmetic changes in #ifdef MODULE, code movement, etc.
  31.  *  When the RAM disk module is removed, free the protected buffers
  32.  *  Default RAM disk size changed to 2.88 MB
  33.  *
  34.  *  Added initrd: Werner Almesberger & Hans Lermen, Feb '96
  35.  *
  36.  * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB) 
  37.  * - Chad Page
  38.  *
  39.  * Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98
  40.  *
  41.  * Make block size and block size shift for RAM disks a global macro
  42.  * and set blk_size for -ENOSPC,     Werner Fink <werner@suse.de>, Apr '99
  43.  */
  44. #include <linux/config.h>
  45. #include <linux/string.h>
  46. #include <linux/slab.h>
  47. #include <linux/module.h>
  48. #include <linux/init.h>
  49. #include <linux/devfs_fs_kernel.h>
  50. #include <linux/smp_lock.h>
  51. #include <asm/uaccess.h>
  52. /*
  53.  * 35 has been officially registered as the RAMDISK major number, but
  54.  * so is the original MAJOR number of 1.  We're using 1 in
  55.  * include/linux/major.h for now
  56.  */
  57. #define MAJOR_NR RAMDISK_MAJOR
  58. #include <linux/blk.h>
  59. #include <linux/blkpg.h>
  60. /* The RAM disk size is now a parameter */
  61. #define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */ 
  62. #ifdef CONFIG_BLK_DEV_INITRD
  63. static int initrd_users;
  64. unsigned long initrd_start, initrd_end;
  65. int initrd_below_start_ok;
  66. #endif
  67. /* Various static variables go here.  Most are used only in the RAM disk code.
  68.  */
  69. static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes   */
  70. static int rd_hardsec[NUM_RAMDISKS]; /* Size of real blocks in bytes */
  71. static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :)  */
  72. static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */
  73. static devfs_handle_t devfs_handle;
  74. static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */
  75. /*
  76.  * Parameters for the boot-loading of the RAM disk.  These are set by
  77.  * init/main.c (from arguments to the kernel command line) or from the
  78.  * architecture-specific setup routine (from the stored boot sector
  79.  * information). 
  80.  */
  81. int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */
  82. /*
  83.  * It would be very desirable to have a soft-blocksize (that in the case
  84.  * of the ramdisk driver is also the hardblocksize ;) of PAGE_SIZE because
  85.  * doing that we'll achieve a far better MM footprint. Using a rd_blocksize of
  86.  * BLOCK_SIZE in the worst case we'll make PAGE_SIZE/BLOCK_SIZE buffer-pages
  87.  * unfreeable. With a rd_blocksize of PAGE_SIZE instead we are sure that only
  88.  * 1 page will be protected. Depending on the size of the ramdisk you
  89.  * may want to change the ramdisk blocksize to achieve a better or worse MM
  90.  * behaviour. The default is still BLOCK_SIZE (needed by rd_load_image that
  91.  * supposes the filesystem in the image uses a BLOCK_SIZE blocksize).
  92.  */
  93. int rd_blocksize = BLOCK_SIZE; /* blocksize of the RAM disks */
  94. /*
  95.  * Copyright (C) 2000 Linus Torvalds.
  96.  *               2000 Transmeta Corp.
  97.  * aops copied from ramfs.
  98.  */
  99. static void ramdisk_updatepage(struct page * page, int need_kmap)
  100. {
  101. if (!Page_Uptodate(page)) {
  102. struct buffer_head *bh = page->buffers;
  103. void * address;
  104. if (need_kmap)
  105. kmap(page);
  106. address = page_address(page);
  107. if (bh) {
  108. struct buffer_head *tmp = bh;
  109. do {
  110. if (!buffer_uptodate(tmp)) {
  111. memset(address, 0, tmp->b_size);
  112. mark_buffer_uptodate(tmp, 1);
  113. }
  114. address += tmp->b_size;
  115. tmp = tmp->b_this_page;
  116. } while (tmp != bh);
  117. } else
  118. memset(address, 0, PAGE_CACHE_SIZE);
  119. if (need_kmap)
  120. kunmap(page);
  121. flush_dcache_page(page);
  122. SetPageUptodate(page);
  123. }
  124. }
  125. static int ramdisk_readpage(struct file *file, struct page * page)
  126. {
  127. ramdisk_updatepage(page, 1);
  128. UnlockPage(page);
  129. return 0;
  130. }
  131. static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
  132. {
  133. ramdisk_updatepage(page, 0);
  134. SetPageDirty(page);
  135. return 0;
  136. }
  137. static int ramdisk_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
  138. {
  139. return 0;
  140. }
  141. static struct address_space_operations ramdisk_aops = {
  142. readpage: ramdisk_readpage,
  143. writepage: fail_writepage,
  144. prepare_write: ramdisk_prepare_write,
  145. commit_write: ramdisk_commit_write,
  146. };
  147. static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor)
  148. {
  149. struct address_space * mapping;
  150. unsigned long index;
  151. int offset, size, err;
  152. err = 0;
  153. mapping = rd_bdev[minor]->bd_inode->i_mapping;
  154. /* writing a buffer cache not uptodate must not clear it */
  155. if (sbh->b_page->mapping == mapping) {
  156. if (rw == WRITE) {
  157. mark_buffer_uptodate(sbh, 1);
  158. SetPageDirty(sbh->b_page);
  159. }
  160. goto out;
  161. }
  162. index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9);
  163. offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK;
  164. size = sbh->b_size;
  165. do {
  166. int count;
  167. struct page * page;
  168. char * src, * dst;
  169. count = PAGE_CACHE_SIZE - offset;
  170. if (count > size)
  171. count = size;
  172. size -= count;
  173. page = grab_cache_page(mapping, index);
  174. if (!page) {
  175. err = -ENOMEM;
  176. goto out;
  177. }
  178. ramdisk_updatepage(page, 1);
  179. index++;
  180. if (rw == READ) {
  181. src = kmap(page);
  182. src += offset;
  183. dst = bh_kmap(sbh);
  184. } else {
  185. dst = kmap(page);
  186. dst += offset;
  187. src = bh_kmap(sbh);
  188. }
  189. offset = 0;
  190. memcpy(dst, src, count);
  191. kunmap(page);
  192. bh_kunmap(sbh);
  193. if (rw == READ) {
  194. flush_dcache_page(sbh->b_page);
  195. } else {
  196. SetPageDirty(page);
  197. }
  198. UnlockPage(page);
  199. __free_page(page);
  200. } while (size);
  201.  out:
  202. return err;
  203. }
  204. /*
  205.  *  Basically, my strategy here is to set up a buffer-head which can't be
  206.  *  deleted, and make that my Ramdisk.  If the request is outside of the
  207.  *  allocated size, we must get rid of it...
  208.  *
  209.  * 19-JAN-1998  Richard Gooch <rgooch@atnf.csiro.au>  Added devfs support
  210.  *
  211.  */
  212. static int rd_make_request(request_queue_t * q, int rw, struct buffer_head *sbh)
  213. {
  214. unsigned int minor;
  215. unsigned long offset, len;
  216. minor = MINOR(sbh->b_rdev);
  217. if (minor >= NUM_RAMDISKS)
  218. goto fail;
  219. offset = sbh->b_rsector << 9;
  220. len = sbh->b_size;
  221. if ((offset + len) > rd_length[minor])
  222. goto fail;
  223. if (rw==READA)
  224. rw=READ;
  225. if ((rw != READ) && (rw != WRITE)) {
  226. printk(KERN_INFO "RAMDISK: bad command: %dn", rw);
  227. goto fail;
  228. }
  229. if (rd_blkdev_pagecache_IO(rw, sbh, minor))
  230. goto fail;
  231. sbh->b_end_io(sbh,1);
  232. return 0;
  233.  fail:
  234. buffer_IO_error(sbh);
  235. return 0;
  236. static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  237. {
  238. int error = -EINVAL;
  239. unsigned int minor;
  240. if (!inode || !inode->i_rdev) 
  241. goto out;
  242. minor = MINOR(inode->i_rdev);
  243. switch (cmd) {
  244. case BLKFLSBUF:
  245. if (!capable(CAP_SYS_ADMIN))
  246. return -EACCES;
  247. /* special: we want to release the ramdisk memory,
  248.    it's not like with the other blockdevices where
  249.    this ioctl only flushes away the buffer cache. */
  250. error = -EBUSY;
  251. down(&inode->i_bdev->bd_sem);
  252. if (inode->i_bdev->bd_openers <= 2) {
  253. truncate_inode_pages(inode->i_mapping, 0);
  254. error = 0;
  255. }
  256. up(&inode->i_bdev->bd_sem);
  257. invalidate_buffers(inode->i_rdev);
  258. break;
  259.           case BLKGETSIZE:   /* Return device size */
  260. if (!arg)
  261. break;
  262. error = put_user(rd_kbsize[minor] << 1, (unsigned long *) arg);
  263. break;
  264.           case BLKGETSIZE64:
  265. error = put_user((u64)rd_kbsize[minor]<<10, (u64*)arg);
  266. break;
  267. case BLKROSET:
  268. case BLKROGET:
  269. case BLKSSZGET:
  270. error = blk_ioctl(inode->i_rdev, cmd, arg);
  271. };
  272. out:
  273. return error;
  274. }
  275. #ifdef CONFIG_BLK_DEV_INITRD
  276. static ssize_t initrd_read(struct file *file, char *buf,
  277.    size_t count, loff_t *ppos)
  278. {
  279. int left;
  280. left = initrd_end - initrd_start - *ppos;
  281. if (count > left) count = left;
  282. if (count == 0) return 0;
  283. if (copy_to_user(buf, (char *)initrd_start + *ppos, count))
  284. return -EFAULT;
  285. *ppos += count;
  286. return count;
  287. }
  288. static int initrd_release(struct inode *inode,struct file *file)
  289. {
  290. extern void free_initrd_mem(unsigned long, unsigned long);
  291. lock_kernel();
  292. if (!--initrd_users) {
  293. free_initrd_mem(initrd_start, initrd_end);
  294. initrd_start = 0;
  295. }
  296. unlock_kernel();
  297. blkdev_put(inode->i_bdev, BDEV_FILE);
  298. return 0;
  299. }
  300. static struct file_operations initrd_fops = {
  301. read: initrd_read,
  302. release: initrd_release,
  303. };
  304. #endif
  305. static int rd_open(struct inode * inode, struct file * filp)
  306. {
  307. int unit = DEVICE_NR(inode->i_rdev);
  308. #ifdef CONFIG_BLK_DEV_INITRD
  309. if (unit == INITRD_MINOR) {
  310. if (!initrd_start) return -ENODEV;
  311. initrd_users++;
  312. filp->f_op = &initrd_fops;
  313. return 0;
  314. }
  315. #endif
  316. if (unit >= NUM_RAMDISKS)
  317. return -ENXIO;
  318. /*
  319.  * Immunize device against invalidate_buffers() and prune_icache().
  320.  */
  321. if (rd_bdev[unit] == NULL) {
  322. rd_bdev[unit] = bdget(kdev_t_to_nr(inode->i_rdev));
  323. rd_bdev[unit]->bd_openers++;
  324. rd_bdev[unit]->bd_inode->i_mapping->a_ops = &ramdisk_aops;
  325. }
  326. return 0;
  327. }
  328. static struct block_device_operations rd_bd_op = {
  329. owner: THIS_MODULE,
  330. open: rd_open,
  331. ioctl: rd_ioctl,
  332. };
  333. /* Before freeing the module, invalidate all of the protected buffers! */
  334. static void __exit rd_cleanup (void)
  335. {
  336. int i;
  337. for (i = 0 ; i < NUM_RAMDISKS; i++) {
  338. struct block_device *bdev = rd_bdev[i];
  339. rd_bdev[i] = NULL;
  340. if (bdev)
  341. blkdev_put(bdev, BDEV_FILE);
  342. destroy_buffers(MKDEV(MAJOR_NR, i));
  343. }
  344. devfs_unregister (devfs_handle);
  345. unregister_blkdev( MAJOR_NR, "ramdisk" );
  346. hardsect_size[MAJOR_NR] = NULL;
  347. blksize_size[MAJOR_NR] = NULL;
  348. blk_size[MAJOR_NR] = NULL;
  349. }
  350. /* This is the registration and initialization section of the RAM disk driver */
  351. static int __init rd_init (void)
  352. {
  353. int i;
  354. if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
  355.     (rd_blocksize & (rd_blocksize-1)))
  356. {
  357. printk("RAMDISK: wrong blocksize %d, reverting to defaultsn",
  358.        rd_blocksize);
  359. rd_blocksize = BLOCK_SIZE;
  360. }
  361. if (register_blkdev(MAJOR_NR, "ramdisk", &rd_bd_op)) {
  362. printk("RAMDISK: Could not get major %d", MAJOR_NR);
  363. return -EIO;
  364. }
  365. blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_make_request);
  366. for (i = 0; i < NUM_RAMDISKS; i++) {
  367. /* rd_size is given in kB */
  368. rd_length[i] = rd_size << 10;
  369. rd_hardsec[i] = rd_blocksize;
  370. rd_blocksizes[i] = rd_blocksize;
  371. rd_kbsize[i] = rd_size;
  372. }
  373. devfs_handle = devfs_mk_dir (NULL, "rd", NULL);
  374. devfs_register_series (devfs_handle, "%u", NUM_RAMDISKS,
  375.        DEVFS_FL_DEFAULT, MAJOR_NR, 0,
  376.        S_IFBLK | S_IRUSR | S_IWUSR,
  377.        &rd_bd_op, NULL);
  378. for (i = 0; i < NUM_RAMDISKS; i++)
  379. register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &rd_bd_op, rd_size<<1);
  380. #ifdef CONFIG_BLK_DEV_INITRD
  381. /* We ought to separate initrd operations here */
  382. register_disk(NULL, MKDEV(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1);
  383. devfs_register(devfs_handle, "initrd", DEVFS_FL_DEFAULT, MAJOR_NR,
  384. INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL);
  385. #endif
  386. hardsect_size[MAJOR_NR] = rd_hardsec; /* Size of the RAM disk blocks */
  387. blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */
  388. blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB  */
  389. /* rd_size is given in kB */
  390. printk("RAMDISK driver initialized: "
  391.        "%d RAM disks of %dK size %d blocksizen",
  392.        NUM_RAMDISKS, rd_size, rd_blocksize);
  393. return 0;
  394. }
  395. module_init(rd_init);
  396. module_exit(rd_cleanup);
  397. /* options - nonmodular */
  398. #ifndef MODULE
  399. static int __init ramdisk_size(char *str)
  400. {
  401. rd_size = simple_strtol(str,NULL,0);
  402. return 1;
  403. }
  404. static int __init ramdisk_size2(char *str) /* kludge */
  405. {
  406. return ramdisk_size(str);
  407. }
  408. static int __init ramdisk_blocksize(char *str)
  409. {
  410. rd_blocksize = simple_strtol(str,NULL,0);
  411. return 1;
  412. }
  413. __setup("ramdisk=", ramdisk_size);
  414. __setup("ramdisk_size=", ramdisk_size2);
  415. __setup("ramdisk_blocksize=", ramdisk_blocksize);
  416. #endif
  417. /* options - modular */
  418. MODULE_PARM     (rd_size, "1i");
  419. MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
  420. MODULE_PARM     (rd_blocksize, "i");
  421. MODULE_PARM_DESC(rd_blocksize, "Blocksize of each RAM disk in bytes.");
  422. MODULE_LICENSE("GPL");