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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/mm/page_io.c
  3.  *
  4.  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  5.  *
  6.  *  Swap reorganised 29.12.95, 
  7.  *  Asynchronous swapping added 30.12.95. Stephen Tweedie
  8.  *  Removed race in async swapping. 14.4.1996. Bruno Haible
  9.  *  Add swap of shared pages through the page cache. 20.2.1998. Stephen Tweedie
  10.  *  Always use brw_page, life becomes simpler. 12 May 1998 Eric Biederman
  11.  */
  12. #include <linux/mm.h>
  13. #include <linux/kernel_stat.h>
  14. #include <linux/swap.h>
  15. #include <linux/locks.h>
  16. #include <linux/swapctl.h>
  17. #include <asm/pgtable.h>
  18. /*
  19.  * Reads or writes a swap page.
  20.  * wait=1: start I/O and wait for completion. wait=0: start asynchronous I/O.
  21.  *
  22.  * Important prevention of race condition: the caller *must* atomically 
  23.  * create a unique swap cache entry for this swap page before calling
  24.  * rw_swap_page, and must lock that page.  By ensuring that there is a
  25.  * single page of memory reserved for the swap entry, the normal VM page
  26.  * lock on that page also doubles as a lock on swap entries.  Having only
  27.  * one lock to deal with per swap entry (rather than locking swap and memory
  28.  * independently) also makes it easier to make certain swapping operations
  29.  * atomic, which is particularly important when we are trying to ensure 
  30.  * that shared pages stay shared while being swapped.
  31.  */
  32. static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
  33. {
  34. unsigned long offset;
  35. int zones[PAGE_SIZE/512];
  36. int zones_used;
  37. kdev_t dev = 0;
  38. int block_size;
  39. struct inode *swapf = 0;
  40. if (rw == READ) {
  41. ClearPageUptodate(page);
  42. kstat.pswpin++;
  43. } else
  44. kstat.pswpout++;
  45. get_swaphandle_info(entry, &offset, &dev, &swapf);
  46. if (dev) {
  47. zones[0] = offset;
  48. zones_used = 1;
  49. block_size = PAGE_SIZE;
  50. } else if (swapf) {
  51. int i, j;
  52. unsigned int block = offset
  53. << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
  54. block_size = swapf->i_sb->s_blocksize;
  55. for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
  56. if (!(zones[i] = bmap(swapf,block++))) {
  57. printk("rw_swap_page: bad swap filen");
  58. return 0;
  59. }
  60. zones_used = i;
  61. dev = swapf->i_dev;
  62. } else {
  63. return 0;
  64. }
  65.   /* block_size == PAGE_SIZE/zones_used */
  66.   brw_page(rw, page, dev, zones, block_size);
  67.   /* Note! For consistency we do all of the logic,
  68.    * decrementing the page count, and unlocking the page in the
  69.    * swap lock map - in the IO completion handler.
  70.    */
  71. return 1;
  72. }
  73. /*
  74.  * A simple wrapper so the base function doesn't need to enforce
  75.  * that all swap pages go through the swap cache! We verify that:
  76.  *  - the page is locked
  77.  *  - it's marked as being swap-cache
  78.  *  - it's associated with the swap inode
  79.  */
  80. void rw_swap_page(int rw, struct page *page)
  81. {
  82. swp_entry_t entry;
  83. entry.val = page->index;
  84. if (!PageLocked(page))
  85. PAGE_BUG(page);
  86. if (!PageSwapCache(page))
  87. PAGE_BUG(page);
  88. if (page->mapping != &swapper_space)
  89. PAGE_BUG(page);
  90. if (!rw_swap_page_base(rw, entry, page))
  91. UnlockPage(page);
  92. }
  93. /*
  94.  * The swap lock map insists that pages be in the page cache!
  95.  * Therefore we can't use it.  Later when we can remove the need for the
  96.  * lock map and we can reduce the number of functions exported.
  97.  */
  98. void rw_swap_page_nolock(int rw, swp_entry_t entry, char *buf)
  99. {
  100. struct page *page = virt_to_page(buf);
  101. if (!PageLocked(page))
  102. PAGE_BUG(page);
  103. if (PageSwapCache(page))
  104. PAGE_BUG(page);
  105. if (page->mapping)
  106. PAGE_BUG(page);
  107. /* needs sync_page to wait I/O completation */
  108. page->mapping = &swapper_space;
  109. if (!rw_swap_page_base(rw, entry, page))
  110. UnlockPage(page);
  111. wait_on_page(page);
  112. page->mapping = NULL;
  113. }