aboutsummaryrefslogtreecommitdiffstats
path: root/mm/swapfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r--mm/swapfile.c70
1 files changed, 36 insertions, 34 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index dc88a7e4257e..16de84b56644 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -145,23 +145,28 @@ void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page)
145static int discard_swap(struct swap_info_struct *si) 145static int discard_swap(struct swap_info_struct *si)
146{ 146{
147 struct swap_extent *se; 147 struct swap_extent *se;
148 sector_t start_block;
149 sector_t nr_blocks;
148 int err = 0; 150 int err = 0;
149 151
150 list_for_each_entry(se, &si->extent_list, list) { 152 /* Do not discard the swap header page! */
151 sector_t start_block = se->start_block << (PAGE_SHIFT - 9); 153 se = &si->first_swap_extent;
152 sector_t nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9); 154 start_block = (se->start_block + 1) << (PAGE_SHIFT - 9);
155 nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9);
156 if (nr_blocks) {
157 err = blkdev_issue_discard(si->bdev, start_block,
158 nr_blocks, GFP_KERNEL, DISCARD_FL_BARRIER);
159 if (err)
160 return err;
161 cond_resched();
162 }
153 163
154 if (se->start_page == 0) { 164 list_for_each_entry(se, &si->first_swap_extent.list, list) {
155 /* Do not discard the swap header page! */ 165 start_block = se->start_block << (PAGE_SHIFT - 9);
156 start_block += 1 << (PAGE_SHIFT - 9); 166 nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9);
157 nr_blocks -= 1 << (PAGE_SHIFT - 9);
158 if (!nr_blocks)
159 continue;
160 }
161 167
162 err = blkdev_issue_discard(si->bdev, start_block, 168 err = blkdev_issue_discard(si->bdev, start_block,
163 nr_blocks, GFP_KERNEL, 169 nr_blocks, GFP_KERNEL, DISCARD_FL_BARRIER);
164 DISCARD_FL_BARRIER);
165 if (err) 170 if (err)
166 break; 171 break;
167 172
@@ -200,14 +205,11 @@ static void discard_swap_cluster(struct swap_info_struct *si,
200 start_block <<= PAGE_SHIFT - 9; 205 start_block <<= PAGE_SHIFT - 9;
201 nr_blocks <<= PAGE_SHIFT - 9; 206 nr_blocks <<= PAGE_SHIFT - 9;
202 if (blkdev_issue_discard(si->bdev, start_block, 207 if (blkdev_issue_discard(si->bdev, start_block,
203 nr_blocks, GFP_NOIO, 208 nr_blocks, GFP_NOIO, DISCARD_FL_BARRIER))
204 DISCARD_FL_BARRIER))
205 break; 209 break;
206 } 210 }
207 211
208 lh = se->list.next; 212 lh = se->list.next;
209 if (lh == &si->extent_list)
210 lh = lh->next;
211 se = list_entry(lh, struct swap_extent, list); 213 se = list_entry(lh, struct swap_extent, list);
212 } 214 }
213} 215}
@@ -761,10 +763,8 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
761 return type; 763 return type;
762 } 764 }
763 if (bdev == sis->bdev) { 765 if (bdev == sis->bdev) {
764 struct swap_extent *se; 766 struct swap_extent *se = &sis->first_swap_extent;
765 767
766 se = list_entry(sis->extent_list.next,
767 struct swap_extent, list);
768 if (se->start_block == offset) { 768 if (se->start_block == offset) {
769 if (bdev_p) 769 if (bdev_p)
770 *bdev_p = bdgrab(sis->bdev); 770 *bdev_p = bdgrab(sis->bdev);
@@ -1310,8 +1310,6 @@ sector_t map_swap_page(swp_entry_t entry, struct block_device **bdev)
1310 return se->start_block + (offset - se->start_page); 1310 return se->start_block + (offset - se->start_page);
1311 } 1311 }
1312 lh = se->list.next; 1312 lh = se->list.next;
1313 if (lh == &sis->extent_list)
1314 lh = lh->next;
1315 se = list_entry(lh, struct swap_extent, list); 1313 se = list_entry(lh, struct swap_extent, list);
1316 sis->curr_swap_extent = se; 1314 sis->curr_swap_extent = se;
1317 BUG_ON(se == start_se); /* It *must* be present */ 1315 BUG_ON(se == start_se); /* It *must* be present */
@@ -1340,10 +1338,10 @@ sector_t swapdev_block(int type, pgoff_t offset)
1340 */ 1338 */
1341static void destroy_swap_extents(struct swap_info_struct *sis) 1339static void destroy_swap_extents(struct swap_info_struct *sis)
1342{ 1340{
1343 while (!list_empty(&sis->extent_list)) { 1341 while (!list_empty(&sis->first_swap_extent.list)) {
1344 struct swap_extent *se; 1342 struct swap_extent *se;
1345 1343
1346 se = list_entry(sis->extent_list.next, 1344 se = list_entry(sis->first_swap_extent.list.next,
1347 struct swap_extent, list); 1345 struct swap_extent, list);
1348 list_del(&se->list); 1346 list_del(&se->list);
1349 kfree(se); 1347 kfree(se);
@@ -1364,8 +1362,15 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
1364 struct swap_extent *new_se; 1362 struct swap_extent *new_se;
1365 struct list_head *lh; 1363 struct list_head *lh;
1366 1364
1367 lh = sis->extent_list.prev; /* The highest page extent */ 1365 if (start_page == 0) {
1368 if (lh != &sis->extent_list) { 1366 se = &sis->first_swap_extent;
1367 sis->curr_swap_extent = se;
1368 se->start_page = 0;
1369 se->nr_pages = nr_pages;
1370 se->start_block = start_block;
1371 return 1;
1372 } else {
1373 lh = sis->first_swap_extent.list.prev; /* Highest extent */
1369 se = list_entry(lh, struct swap_extent, list); 1374 se = list_entry(lh, struct swap_extent, list);
1370 BUG_ON(se->start_page + se->nr_pages != start_page); 1375 BUG_ON(se->start_page + se->nr_pages != start_page);
1371 if (se->start_block + se->nr_pages == start_block) { 1376 if (se->start_block + se->nr_pages == start_block) {
@@ -1385,7 +1390,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
1385 new_se->nr_pages = nr_pages; 1390 new_se->nr_pages = nr_pages;
1386 new_se->start_block = start_block; 1391 new_se->start_block = start_block;
1387 1392
1388 list_add_tail(&new_se->list, &sis->extent_list); 1393 list_add_tail(&new_se->list, &sis->first_swap_extent.list);
1389 return 1; 1394 return 1;
1390} 1395}
1391 1396
@@ -1437,7 +1442,7 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
1437 if (S_ISBLK(inode->i_mode)) { 1442 if (S_ISBLK(inode->i_mode)) {
1438 ret = add_swap_extent(sis, 0, sis->max, 0); 1443 ret = add_swap_extent(sis, 0, sis->max, 0);
1439 *span = sis->pages; 1444 *span = sis->pages;
1440 goto done; 1445 goto out;
1441 } 1446 }
1442 1447
1443 blkbits = inode->i_blkbits; 1448 blkbits = inode->i_blkbits;
@@ -1508,15 +1513,12 @@ reprobe:
1508 sis->max = page_no; 1513 sis->max = page_no;
1509 sis->pages = page_no - 1; 1514 sis->pages = page_no - 1;
1510 sis->highest_bit = page_no - 1; 1515 sis->highest_bit = page_no - 1;
1511done: 1516out:
1512 sis->curr_swap_extent = list_entry(sis->extent_list.prev, 1517 return ret;
1513 struct swap_extent, list);
1514 goto out;
1515bad_bmap: 1518bad_bmap:
1516 printk(KERN_ERR "swapon: swapfile has holes\n"); 1519 printk(KERN_ERR "swapon: swapfile has holes\n");
1517 ret = -EINVAL; 1520 ret = -EINVAL;
1518out: 1521 goto out;
1519 return ret;
1520} 1522}
1521 1523
1522SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) 1524SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
@@ -1815,7 +1817,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
1815 kfree(p); 1817 kfree(p);
1816 goto out; 1818 goto out;
1817 } 1819 }
1818 INIT_LIST_HEAD(&p->extent_list);
1819 if (type >= nr_swapfiles) { 1820 if (type >= nr_swapfiles) {
1820 p->type = type; 1821 p->type = type;
1821 swap_info[type] = p; 1822 swap_info[type] = p;
@@ -1834,6 +1835,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
1834 * would be relying on p->type to remain valid. 1835 * would be relying on p->type to remain valid.
1835 */ 1836 */
1836 } 1837 }
1838 INIT_LIST_HEAD(&p->first_swap_extent.list);
1837 p->flags = SWP_USED; 1839 p->flags = SWP_USED;
1838 p->next = -1; 1840 p->next = -1;
1839 spin_unlock(&swap_lock); 1841 spin_unlock(&swap_lock);