Updates to -ck series/patches to reflect BFS 404 changes; revert config to 100 Hz...
[kernel-bfs] / kernel-bfs-2.6.28 / debian / patches / patch_swap_notify_core_support_2.6.28.diff
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;
6  
7                 disk->minors = minors;
8 +               disk->flags |= 
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);
22         struct module *owner;
23  };
24  
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
34  
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:
41         return NULL;
42  }      
43  
44 +static void swap_entry_update(struct swap_info_struct *p, unsigned long offset)
45 +{
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;
52 +       nr_swap_pages++;
53 +       p->inuse_pages--;
54 +}
55 +
56  static int swap_entry_free(struct swap_info_struct *p, unsigned long offset)
57  {
58         int count = p->swap_map[offset];
59         unsigned old;
60 +       struct gendisk *disk;
61  
62         if (count >= SWAP_MAP_MAX)
63                 return count;
64 @@ -283,28 +295,39 @@ static int swap_entry_free(struct swap_i
65         if (count)
66                 return count;
67  
68 -       spin_lock(&p->remap_lock);
69 +       disk = p->bdev->bd_disk;
70  
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;
77 -       nr_swap_pages++;
78 -       p->inuse_pages--;
79 +       if (!p->swap_remap) {
80 +               swap_entry_update(p, offset);
81 +               if (disk->fops->swap_slot_free_notify)
82 +                       disk->fops->swap_slot_free_notify(p->bdev, offset);
83 +               return 0;
84 +       }
85 +
86 +       spin_lock(&p->remap_lock);
87 +       swap_entry_update(p, offset);
88  
89         /* Re-map the page number */
90         old = p->swap_remap[offset] & 0x7FFFFFFF;
91         /* Zero means it was not re-mapped */
92 -       if (!old)
93 -               goto out;
94 +       if (!old) {
95 +               /* Skip notify if flag is set or the page is used */
96 +               if ((disk->flags & GENHD_FL_NOTIFY_REMAPPED_ONLY) || 
97 +                       (p->swap_remap[offset] & 0x80000000))
98 +                       goto out;
99 +
100 +               old = offset;
101 +               goto notify;
102 +       }
103         /* Clear the re-mapping */
104         p->swap_remap[offset] &= 0x80000000;
105         /* Mark the re-mapped page as unused */
106         p->swap_remap[old] &= 0x7FFFFFFF;
107         /* Record how many free pages there are */
108         p->gaps_exist += 1;
109 +notify:
110 +       if (disk->fops->swap_slot_free_notify)
111 +               disk->fops->swap_slot_free_notify(p->bdev, old);
112  out:
113         spin_unlock(&p->remap_lock);
114         return 0;
115 @@ -1110,6 +1135,8 @@ sector_t map_swap_page(struct swap_info_
116         struct swap_extent *start_se = se;
117         unsigned old;
118  
119 +       if (!sis->swap_remap)
120 +               goto out;
121         /*
122          * Instead of using the offset we are given, re-map it to the next
123          * sequential position.
124 @@ -1159,7 +1186,7 @@ sector_t map_swap_page(struct swap_info_
125                         offset = old;
126         }
127         spin_unlock(&sis->remap_lock);
128 -
129 +out:
130         for ( ; ; ) {
131                 struct list_head *lh;
132  
133 @@ -1517,8 +1544,10 @@ SYSCALL_DEFINE1(swapoff, const char __us
134         p->flags = 0;
135         spin_unlock(&swap_lock);
136         mutex_unlock(&swapon_mutex);
137 -       kfree(p->gap_pool_arr);
138 -       vfree(p->swap_remap);
139 +       if (p->swap_remap) {
140 +               kfree(p->gap_pool_arr);
141 +               vfree(p->swap_remap);
142 +       }
143         vfree(swap_map);
144         inode = mapping->host;
145         if (S_ISBLK(inode->i_mode)) {
146 @@ -1832,15 +1861,17 @@ SYSCALL_DEFINE2(swapon, const char __use
147                         error = -ENOMEM;
148                         goto bad_swap;
149                 }
150 -               swap_remap = vmalloc(maxpages * sizeof(unsigned));
151 -               if (!swap_remap) {
152 -                       error = -ENOMEM;
153 -                       goto bad_swap;
154 +               if (p->bdev->bd_disk->flags & GENHD_FL_REMAP_SWAPPED_PAGES) {
155 +                       swap_remap = vmalloc(maxpages * sizeof(unsigned));
156 +                       if (!swap_remap) {
157 +                               error = -ENOMEM;
158 +                               goto bad_swap;
159 +                       }
160 +                       memset(swap_remap, 0, maxpages * sizeof(unsigned));
161                 }
162  
163                 error = 0;
164                 memset(swap_map, 0, maxpages * sizeof(short));
165 -               memset(swap_remap, 0, maxpages * sizeof(unsigned));
166                 for (i = 0; i < swap_header->info.nr_badpages; i++) {
167                         int page_nr = swap_header->info.badpages[i];
168                         if (page_nr <= 0 || page_nr >= swap_header->info.last_page)
169 @@ -1872,13 +1903,15 @@ SYSCALL_DEFINE2(swapon, const char __use
170                 goto bad_swap;
171         }
172  
173 -       p->gap_pool_arr = kmalloc(sizeof(struct swap_gap_node)*
174 -                               SWAP_GAP_TREE_SIZE, GFP_KERNEL);
175 -       if (!p->gap_pool_arr) {
176 -               error = -ENOMEM;
177 -               goto bad_swap;
178 +       if (swap_remap) {
179 +               p->gap_pool_arr = kmalloc(sizeof(struct swap_gap_node)*
180 +                                       SWAP_GAP_TREE_SIZE, GFP_KERNEL);
181 +               if (!p->gap_pool_arr) {
182 +                       error = -ENOMEM;
183 +                       goto bad_swap;
184 +               }
185 +               p->gaps_tree = RB_ROOT;
186         }
187 -       p->gaps_tree = RB_ROOT;
188  
189         mutex_lock(&swapon_mutex);
190         spin_lock(&swap_lock);
191 @@ -1889,11 +1922,13 @@ SYSCALL_DEFINE2(swapon, const char __use
192                 p->prio = --least_priority;
193         p->swap_map = swap_map;
194         p->swap_remap = swap_remap;
195 -       p->gap_next = 1;
196 -       p->gap_end = p->max - 1;
197 -       p->gaps_exist = p->max - 1;
198 -       spin_lock_init(&p->remap_lock);
199 -       mutex_init(&p->remap_mutex);
200 +       if (swap_remap) {
201 +               p->gap_next = 1;
202 +               p->gap_end = p->max - 1;
203 +               p->gaps_exist = p->max - 1;
204 +               spin_lock_init(&p->remap_lock);
205 +               mutex_init(&p->remap_mutex);
206 +       }
207         p->flags = SWP_ACTIVE;
208         nr_swap_pages += nr_good_pages;
209         total_swap_pages += nr_good_pages;
210 @@ -1932,7 +1967,8 @@ bad_swap_2:
211         p->swap_file = NULL;
212         p->flags = 0;
213         spin_unlock(&swap_lock);
214 -       vfree(swap_remap);
215 +       if (swap_remap)
216 +               vfree(swap_remap);
217         vfree(swap_map);
218         if (swap_file)
219                 filp_close(swap_file, NULL);