1
2
3
4
5
6
7
8
9
10
11#include <linux/mm.h>
12#include <linux/sched.h>
13#include <linux/head.h>
14#include <linux/kernel.h>
15#include <linux/kernel_stat.h>
16#include <linux/errno.h>
17#include <linux/string.h>
18#include <linux/stat.h>
19#include <linux/swap.h>
20#include <linux/fs.h>
21#include <linux/locks.h>
22#include <linux/swapctl.h>
23
24#include <asm/dma.h>
25#include <asm/system.h>
26#include <asm/uaccess.h>
27#include <asm/bitops.h>
28#include <asm/pgtable.h>
29
30static struct wait_queue * lock_queue = NULL;
31
32
33
34
35
36
37
38
39
40
41
42
43
44void rw_swap_page(int rw, unsigned long entry, char * buf, int wait)
45{
46 unsigned long type, offset;
47 struct swap_info_struct * p;
48 struct page *page;
49
50 type = SWP_TYPE(entry);
51 if (type >= nr_swapfiles) {
52 printk("Internal error: bad swap-device\n");
53 return;
54 }
55 p = &swap_info[type];
56 offset = SWP_OFFSET(entry);
57 if (offset >= p->max) {
58 printk("rw_swap_page: weirdness\n");
59 return;
60 }
61 if (p->swap_map && !p->swap_map[offset]) {
62 printk("Hmm.. Trying to use unallocated swap (%08lx)\n", entry);
63 return;
64 }
65 if (!(p->flags & SWP_USED)) {
66 printk("Trying to swap to unused swap-device\n");
67 return;
68 }
69
70 while (test_and_set_bit(offset,p->swap_lockmap)) {
71 run_task_queue(&tq_disk);
72 sleep_on(&lock_queue);
73 }
74 if (rw == READ)
75 kstat.pswpin++;
76 else
77 kstat.pswpout++;
78 page = mem_map + MAP_NR(buf);
79 atomic_inc(&page->count);
80 wait_on_page(page);
81 if (p->swap_device) {
82 if (!wait) {
83 set_bit(PG_free_after, &page->flags);
84 set_bit(PG_decr_after, &page->flags);
85 set_bit(PG_swap_unlock_after, &page->flags);
86
87 PageClearSwapCache(page);
88 page->pg_swap_entry = entry;
89 atomic_inc(&nr_async_pages);
90 }
91 ll_rw_page(rw,p->swap_device,offset,buf);
92
93
94
95
96
97 if (!wait)
98 return;
99 wait_on_page(page);
100 } else if (p->swap_file) {
101 struct inode *swapf = p->swap_file->d_inode;
102 unsigned int zones[PAGE_SIZE/512];
103 int i;
104 if (swapf->i_op->bmap == NULL
105 && swapf->i_op->smap != NULL){
106
107
108
109
110
111
112
113
114
115
116
117
118 int j;
119 unsigned int block = offset << 3;
120
121 for (i=0, j=0; j< PAGE_SIZE ; i++, j += 512){
122 if (!(zones[i] = swapf->i_op->smap(swapf,block++))) {
123 printk("rw_swap_page: bad swap file\n");
124 return;
125 }
126 }
127 }else{
128 int j;
129 unsigned int block = offset
130 << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
131
132 for (i=0, j=0; j< PAGE_SIZE ; i++, j +=swapf->i_sb->s_blocksize)
133 if (!(zones[i] = bmap(swapf,block++))) {
134 printk("rw_swap_page: bad swap file\n");
135 }
136 }
137 ll_rw_swap_file(rw,swapf->i_dev, zones, i,buf);
138 } else
139 printk("rw_swap_page: no swap file or device\n");
140 atomic_dec(&page->count);
141 if (offset && !test_and_clear_bit(offset,p->swap_lockmap))
142 printk("rw_swap_page: lock already cleared\n");
143 wake_up(&lock_queue);
144}
145
146
147void swap_after_unlock_page (unsigned long entry)
148{
149 unsigned long type, offset;
150 struct swap_info_struct * p;
151
152 type = SWP_TYPE(entry);
153 if (type >= nr_swapfiles) {
154 printk("swap_after_unlock_page: bad swap-device\n");
155 return;
156 }
157 p = &swap_info[type];
158 offset = SWP_OFFSET(entry);
159 if (offset >= p->max) {
160 printk("swap_after_unlock_page: weirdness\n");
161 return;
162 }
163 if (!test_and_clear_bit(offset,p->swap_lockmap))
164 printk("swap_after_unlock_page: lock already cleared\n");
165 wake_up(&lock_queue);
166}
167
168
169
170
171
172
173void ll_rw_page(int rw, kdev_t dev, unsigned long offset, char * buffer)
174{
175 int block = offset;
176 struct page *page;
177
178 switch (rw) {
179 case READ:
180 break;
181 case WRITE:
182 if (is_read_only(dev)) {
183 printk("Can't page to read-only device %s\n",
184 kdevname(dev));
185 return;
186 }
187 break;
188 default:
189 panic("ll_rw_page: bad block dev cmd, must be R/W");
190 }
191 page = mem_map + MAP_NR(buffer);
192 if (test_and_set_bit(PG_locked, &page->flags))
193 panic ("ll_rw_page: page already locked");
194 brw_page(rw, page, dev, &block, PAGE_SIZE, 0);
195}
196