diff options
-rw-r--r-- | include/linux/swap.h | 1 | ||||
-rw-r--r-- | mm/swapfile.c | 44 |
2 files changed, 30 insertions, 15 deletions
diff --git a/include/linux/swap.h b/include/linux/swap.h index 38f288475e67..f2b16ac0b539 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -123,7 +123,6 @@ struct swap_info_struct { | |||
123 | struct file *swap_file; | 123 | struct file *swap_file; |
124 | struct block_device *bdev; | 124 | struct block_device *bdev; |
125 | struct list_head extent_list; | 125 | struct list_head extent_list; |
126 | int nr_extents; | ||
127 | struct swap_extent *curr_swap_extent; | 126 | struct swap_extent *curr_swap_extent; |
128 | unsigned old_block_size; | 127 | unsigned old_block_size; |
129 | unsigned short * swap_map; | 128 | unsigned short * swap_map; |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 73521d39e985..d4da84ee3925 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -854,7 +854,6 @@ static void destroy_swap_extents(struct swap_info_struct *sis) | |||
854 | list_del(&se->list); | 854 | list_del(&se->list); |
855 | kfree(se); | 855 | kfree(se); |
856 | } | 856 | } |
857 | sis->nr_extents = 0; | ||
858 | } | 857 | } |
859 | 858 | ||
860 | /* | 859 | /* |
@@ -893,8 +892,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
893 | new_se->start_block = start_block; | 892 | new_se->start_block = start_block; |
894 | 893 | ||
895 | list_add_tail(&new_se->list, &sis->extent_list); | 894 | list_add_tail(&new_se->list, &sis->extent_list); |
896 | sis->nr_extents++; | 895 | return 1; |
897 | return 0; | ||
898 | } | 896 | } |
899 | 897 | ||
900 | /* | 898 | /* |
@@ -928,7 +926,7 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, | |||
928 | * This is extremely effective. The average number of iterations in | 926 | * This is extremely effective. The average number of iterations in |
929 | * map_swap_page() has been measured at about 0.3 per page. - akpm. | 927 | * map_swap_page() has been measured at about 0.3 per page. - akpm. |
930 | */ | 928 | */ |
931 | static int setup_swap_extents(struct swap_info_struct *sis) | 929 | static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) |
932 | { | 930 | { |
933 | struct inode *inode; | 931 | struct inode *inode; |
934 | unsigned blocks_per_page; | 932 | unsigned blocks_per_page; |
@@ -936,11 +934,15 @@ static int setup_swap_extents(struct swap_info_struct *sis) | |||
936 | unsigned blkbits; | 934 | unsigned blkbits; |
937 | sector_t probe_block; | 935 | sector_t probe_block; |
938 | sector_t last_block; | 936 | sector_t last_block; |
937 | sector_t lowest_block = -1; | ||
938 | sector_t highest_block = 0; | ||
939 | int nr_extents = 0; | ||
939 | int ret; | 940 | int ret; |
940 | 941 | ||
941 | inode = sis->swap_file->f_mapping->host; | 942 | inode = sis->swap_file->f_mapping->host; |
942 | if (S_ISBLK(inode->i_mode)) { | 943 | if (S_ISBLK(inode->i_mode)) { |
943 | ret = add_swap_extent(sis, 0, sis->max, 0); | 944 | ret = add_swap_extent(sis, 0, sis->max, 0); |
945 | *span = sis->pages; | ||
944 | goto done; | 946 | goto done; |
945 | } | 947 | } |
946 | 948 | ||
@@ -985,19 +987,28 @@ static int setup_swap_extents(struct swap_info_struct *sis) | |||
985 | } | 987 | } |
986 | } | 988 | } |
987 | 989 | ||
990 | first_block >>= (PAGE_SHIFT - blkbits); | ||
991 | if (page_no) { /* exclude the header page */ | ||
992 | if (first_block < lowest_block) | ||
993 | lowest_block = first_block; | ||
994 | if (first_block > highest_block) | ||
995 | highest_block = first_block; | ||
996 | } | ||
997 | |||
988 | /* | 998 | /* |
989 | * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks | 999 | * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks |
990 | */ | 1000 | */ |
991 | ret = add_swap_extent(sis, page_no, 1, | 1001 | ret = add_swap_extent(sis, page_no, 1, first_block); |
992 | first_block >> (PAGE_SHIFT - blkbits)); | 1002 | if (ret < 0) |
993 | if (ret) | ||
994 | goto out; | 1003 | goto out; |
1004 | nr_extents += ret; | ||
995 | page_no++; | 1005 | page_no++; |
996 | probe_block += blocks_per_page; | 1006 | probe_block += blocks_per_page; |
997 | reprobe: | 1007 | reprobe: |
998 | continue; | 1008 | continue; |
999 | } | 1009 | } |
1000 | ret = 0; | 1010 | ret = nr_extents; |
1011 | *span = 1 + highest_block - lowest_block; | ||
1001 | if (page_no == 0) | 1012 | if (page_no == 0) |
1002 | page_no = 1; /* force Empty message */ | 1013 | page_no = 1; /* force Empty message */ |
1003 | sis->max = page_no; | 1014 | sis->max = page_no; |
@@ -1265,6 +1276,8 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1265 | union swap_header *swap_header = NULL; | 1276 | union swap_header *swap_header = NULL; |
1266 | int swap_header_version; | 1277 | int swap_header_version; |
1267 | int nr_good_pages = 0; | 1278 | int nr_good_pages = 0; |
1279 | int nr_extents; | ||
1280 | sector_t span; | ||
1268 | unsigned long maxpages = 1; | 1281 | unsigned long maxpages = 1; |
1269 | int swapfilesize; | 1282 | int swapfilesize; |
1270 | unsigned short *swap_map; | 1283 | unsigned short *swap_map; |
@@ -1300,7 +1313,6 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1300 | nr_swapfiles = type+1; | 1313 | nr_swapfiles = type+1; |
1301 | INIT_LIST_HEAD(&p->extent_list); | 1314 | INIT_LIST_HEAD(&p->extent_list); |
1302 | p->flags = SWP_USED; | 1315 | p->flags = SWP_USED; |
1303 | p->nr_extents = 0; | ||
1304 | p->swap_file = NULL; | 1316 | p->swap_file = NULL; |
1305 | p->old_block_size = 0; | 1317 | p->old_block_size = 0; |
1306 | p->swap_map = NULL; | 1318 | p->swap_map = NULL; |
@@ -1477,9 +1489,11 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1477 | p->swap_map[0] = SWAP_MAP_BAD; | 1489 | p->swap_map[0] = SWAP_MAP_BAD; |
1478 | p->max = maxpages; | 1490 | p->max = maxpages; |
1479 | p->pages = nr_good_pages; | 1491 | p->pages = nr_good_pages; |
1480 | error = setup_swap_extents(p); | 1492 | nr_extents = setup_swap_extents(p, &span); |
1481 | if (error) | 1493 | if (nr_extents < 0) { |
1494 | error = nr_extents; | ||
1482 | goto bad_swap; | 1495 | goto bad_swap; |
1496 | } | ||
1483 | nr_good_pages = p->pages; | 1497 | nr_good_pages = p->pages; |
1484 | } | 1498 | } |
1485 | if (!nr_good_pages) { | 1499 | if (!nr_good_pages) { |
@@ -1494,9 +1508,11 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags) | |||
1494 | p->flags = SWP_ACTIVE; | 1508 | p->flags = SWP_ACTIVE; |
1495 | nr_swap_pages += nr_good_pages; | 1509 | nr_swap_pages += nr_good_pages; |
1496 | total_swap_pages += nr_good_pages; | 1510 | total_swap_pages += nr_good_pages; |
1497 | printk(KERN_INFO "Adding %dk swap on %s. Priority:%d extents:%d\n", | 1511 | |
1498 | nr_good_pages<<(PAGE_SHIFT-10), name, | 1512 | printk(KERN_INFO "Adding %dk swap on %s. " |
1499 | p->prio, p->nr_extents); | 1513 | "Priority:%d extents:%d across:%lluk\n", |
1514 | nr_good_pages<<(PAGE_SHIFT-10), name, p->prio, | ||
1515 | nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10)); | ||
1500 | 1516 | ||
1501 | /* insert swap space into swap_list: */ | 1517 | /* insert swap space into swap_list: */ |
1502 | prev = -1; | 1518 | prev = -1; |