1 diff -uprN linux-2.6.28/block/genhd.c linux-2.6.28.new/block/genhd.c
2 --- linux-2.6.28/block/genhd.c 2011-03-13 15:15:43.815647000 +0100
3 +++ linux-2.6.28.new/block/genhd.c 2011-03-15 10:13:35.145764805 +0100
4 @@ -1129,6 +1129,8 @@ struct gendisk *alloc_disk_node(int mino
5 disk->part_tbl->part[0] = &disk->part0;
9 + (GENHD_FL_REMAP_SWAPPED_PAGES | GENHD_FL_NOTIFY_REMAPPED_ONLY);
10 rand_initialize_disk(disk);
11 disk_to_dev(disk)->class = &block_class;
12 disk_to_dev(disk)->type = &disk_type;
13 diff -uprN linux-2.6.28/include/linux/blkdev.h linux-2.6.28.new/include/linux/blkdev.h
14 --- linux-2.6.28/include/linux/blkdev.h 2011-02-01 09:54:54.519982520 +0100
15 +++ linux-2.6.28.new/include/linux/blkdev.h 2011-02-01 10:15:39.369903561 +0100
16 @@ -1068,6 +1068,8 @@ struct block_device_operations {
17 int (*media_changed) (struct gendisk *);
18 int (*revalidate_disk) (struct gendisk *);
19 int (*getgeo)(struct block_device *, struct hd_geometry *);
20 + /* this callback is with swap_lock and sometimes page table lock held */
21 + void (*swap_slot_free_notify) (struct block_device *, unsigned long);
25 diff -uprN linux-2.6.28/include/linux/genhd.h linux-2.6.28.new/include/linux/genhd.h
26 --- linux-2.6.28/include/linux/genhd.h 2011-03-13 15:23:58.275368057 +0100
27 +++ linux-2.6.28.new/include/linux/genhd.h 2011-03-15 10:14:01.575121499 +0100
28 @@ -113,6 +113,8 @@ struct hd_struct {
29 #define GENHD_FL_UP 16
30 #define GENHD_FL_SUPPRESS_PARTITION_INFO 32
31 #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
32 +#define GENHD_FL_REMAP_SWAPPED_PAGES 128
33 +#define GENHD_FL_NOTIFY_REMAPPED_ONLY 256
35 #define BLK_SCSI_MAX_CMDS (256)
36 #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
37 diff -uprN linux-2.6.28/mm/swapfile.c linux-2.6.28.new/mm/swapfile.c
38 --- linux-2.6.28/mm/swapfile.c 2011-02-01 09:54:31.434289623 +0100
39 +++ linux-2.6.28.new/mm/swapfile.c 2011-03-15 10:14:50.998178343 +0100
40 @@ -270,10 +270,23 @@ out:
44 +static void swap_entry_update(struct swap_info_struct *p, unsigned long offset)
46 + if (offset < p->lowest_bit)
47 + p->lowest_bit = offset;
48 + if (offset > p->highest_bit)
49 + p->highest_bit = offset;
50 + if (p->prio > swap_info[swap_list.next].prio)
51 + swap_list.next = p - swap_info;
56 static int swap_entry_free(struct swap_info_struct *p, unsigned long offset)
58 int count = p->swap_map[offset];
60 + struct gendisk *disk;
62 if (count >= SWAP_MAP_MAX)
64 @@ -283,28 +296,40 @@ static int swap_entry_free(struct swap_i
68 - spin_lock(&p->remap_lock);
69 + disk = p->bdev->bd_disk;
71 - if (offset < p->lowest_bit)
72 - p->lowest_bit = offset;
73 - if (offset > p->highest_bit)
74 - p->highest_bit = offset;
75 - if (p->prio > swap_info[swap_list.next].prio)
76 - swap_list.next = p - swap_info;
79 + if (p->swap_remap) {
80 + spin_lock(&p->remap_lock);
81 + swap_entry_update(p, offset);
84 + swap_entry_update(p, offset);
85 + if (disk->fops->swap_slot_free_notify)
86 + disk->fops->swap_slot_free_notify(p->bdev, offset);
90 /* Re-map the page number */
91 old = p->swap_remap[offset] & 0x7FFFFFFF;
92 /* Zero means it was not re-mapped */
96 + /* Skip notify if flag is set or the page is used */
97 + if ((disk->flags & GENHD_FL_NOTIFY_REMAPPED_ONLY) ||
98 + (p->swap_remap[offset] & 0x80000000))
104 /* Clear the re-mapping */
105 p->swap_remap[offset] &= 0x80000000;
106 /* Mark the re-mapped page as unused */
107 p->swap_remap[old] &= 0x7FFFFFFF;
108 /* Record how many free pages there are */
111 + if (disk->fops->swap_slot_free_notify)
112 + disk->fops->swap_slot_free_notify(p->bdev, old);
114 spin_unlock(&p->remap_lock);
116 @@ -1110,6 +1135,8 @@ sector_t map_swap_page(struct swap_info_
117 struct swap_extent *start_se = se;
120 + if (!sis->swap_remap)
123 * Instead of using the offset we are given, re-map it to the next
124 * sequential position.
125 @@ -1159,7 +1186,7 @@ sector_t map_swap_page(struct swap_info_
128 spin_unlock(&sis->remap_lock);
132 struct list_head *lh;
134 @@ -1517,8 +1544,10 @@ SYSCALL_DEFINE1(swapoff, const char __us
136 spin_unlock(&swap_lock);
137 mutex_unlock(&swapon_mutex);
138 - kfree(p->gap_pool_arr);
139 - vfree(p->swap_remap);
140 + if (p->swap_remap) {
141 + kfree(p->gap_pool_arr);
142 + vfree(p->swap_remap);
145 inode = mapping->host;
146 if (S_ISBLK(inode->i_mode)) {
147 @@ -1832,15 +1861,17 @@ SYSCALL_DEFINE2(swapon, const char __use
151 - swap_remap = vmalloc(maxpages * sizeof(unsigned));
155 + if (p->bdev->bd_disk->flags & GENHD_FL_REMAP_SWAPPED_PAGES) {
156 + swap_remap = vmalloc(maxpages * sizeof(unsigned));
161 + memset(swap_remap, 0, maxpages * sizeof(unsigned));
165 memset(swap_map, 0, maxpages * sizeof(short));
166 - memset(swap_remap, 0, maxpages * sizeof(unsigned));
167 for (i = 0; i < swap_header->info.nr_badpages; i++) {
168 int page_nr = swap_header->info.badpages[i];
169 if (page_nr <= 0 || page_nr >= swap_header->info.last_page)
170 @@ -1872,13 +1903,15 @@ SYSCALL_DEFINE2(swapon, const char __use
174 - p->gap_pool_arr = kmalloc(sizeof(struct swap_gap_node)*
175 - SWAP_GAP_TREE_SIZE, GFP_KERNEL);
176 - if (!p->gap_pool_arr) {
180 + p->gap_pool_arr = kmalloc(sizeof(struct swap_gap_node)*
181 + SWAP_GAP_TREE_SIZE, GFP_KERNEL);
182 + if (!p->gap_pool_arr) {
186 + p->gaps_tree = RB_ROOT;
188 - p->gaps_tree = RB_ROOT;
190 mutex_lock(&swapon_mutex);
191 spin_lock(&swap_lock);
192 @@ -1889,11 +1922,13 @@ SYSCALL_DEFINE2(swapon, const char __use
193 p->prio = --least_priority;
194 p->swap_map = swap_map;
195 p->swap_remap = swap_remap;
197 - p->gap_end = p->max - 1;
198 - p->gaps_exist = p->max - 1;
199 - spin_lock_init(&p->remap_lock);
200 - mutex_init(&p->remap_mutex);
203 + p->gap_end = p->max - 1;
204 + p->gaps_exist = p->max - 1;
205 + spin_lock_init(&p->remap_lock);
206 + mutex_init(&p->remap_mutex);
208 p->flags = SWP_ACTIVE;
209 nr_swap_pages += nr_good_pages;
210 total_swap_pages += nr_good_pages;
211 @@ -1932,7 +1967,8 @@ bad_swap_2:
214 spin_unlock(&swap_lock);
220 filp_close(swap_file, NULL);