|
@@ -1345,7 +1345,7 @@ static void destroy_swap_extents(struct swap_info_struct *sis)
|
|
|
*
|
|
|
* This function rather assumes that it is called in ascending page order.
|
|
|
*/
|
|
|
-static int
|
|
|
+int
|
|
|
add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,
|
|
|
unsigned long nr_pages, sector_t start_block)
|
|
|
{
|
|
@@ -1421,106 +1421,25 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
|
|
|
struct file *swap_file = sis->swap_file;
|
|
|
struct address_space *mapping = swap_file->f_mapping;
|
|
|
struct inode *inode = mapping->host;
|
|
|
- unsigned blocks_per_page;
|
|
|
- unsigned long page_no;
|
|
|
- unsigned blkbits;
|
|
|
- sector_t probe_block;
|
|
|
- sector_t last_block;
|
|
|
- sector_t lowest_block = -1;
|
|
|
- sector_t highest_block = 0;
|
|
|
- int nr_extents = 0;
|
|
|
int ret;
|
|
|
|
|
|
if (S_ISBLK(inode->i_mode)) {
|
|
|
ret = add_swap_extent(sis, 0, sis->max, 0);
|
|
|
*span = sis->pages;
|
|
|
- goto out;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
if (mapping->a_ops->swap_activate) {
|
|
|
- ret = mapping->a_ops->swap_activate(swap_file);
|
|
|
+ ret = mapping->a_ops->swap_activate(sis, swap_file, span);
|
|
|
if (!ret) {
|
|
|
sis->flags |= SWP_FILE;
|
|
|
ret = add_swap_extent(sis, 0, sis->max, 0);
|
|
|
*span = sis->pages;
|
|
|
}
|
|
|
- goto out;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
- blkbits = inode->i_blkbits;
|
|
|
- blocks_per_page = PAGE_SIZE >> blkbits;
|
|
|
-
|
|
|
- /*
|
|
|
- * Map all the blocks into the extent list. This code doesn't try
|
|
|
- * to be very smart.
|
|
|
- */
|
|
|
- probe_block = 0;
|
|
|
- page_no = 0;
|
|
|
- last_block = i_size_read(inode) >> blkbits;
|
|
|
- while ((probe_block + blocks_per_page) <= last_block &&
|
|
|
- page_no < sis->max) {
|
|
|
- unsigned block_in_page;
|
|
|
- sector_t first_block;
|
|
|
-
|
|
|
- first_block = bmap(inode, probe_block);
|
|
|
- if (first_block == 0)
|
|
|
- goto bad_bmap;
|
|
|
-
|
|
|
- /*
|
|
|
- * It must be PAGE_SIZE aligned on-disk
|
|
|
- */
|
|
|
- if (first_block & (blocks_per_page - 1)) {
|
|
|
- probe_block++;
|
|
|
- goto reprobe;
|
|
|
- }
|
|
|
-
|
|
|
- for (block_in_page = 1; block_in_page < blocks_per_page;
|
|
|
- block_in_page++) {
|
|
|
- sector_t block;
|
|
|
-
|
|
|
- block = bmap(inode, probe_block + block_in_page);
|
|
|
- if (block == 0)
|
|
|
- goto bad_bmap;
|
|
|
- if (block != first_block + block_in_page) {
|
|
|
- /* Discontiguity */
|
|
|
- probe_block++;
|
|
|
- goto reprobe;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- first_block >>= (PAGE_SHIFT - blkbits);
|
|
|
- if (page_no) { /* exclude the header page */
|
|
|
- if (first_block < lowest_block)
|
|
|
- lowest_block = first_block;
|
|
|
- if (first_block > highest_block)
|
|
|
- highest_block = first_block;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks
|
|
|
- */
|
|
|
- ret = add_swap_extent(sis, page_no, 1, first_block);
|
|
|
- if (ret < 0)
|
|
|
- goto out;
|
|
|
- nr_extents += ret;
|
|
|
- page_no++;
|
|
|
- probe_block += blocks_per_page;
|
|
|
-reprobe:
|
|
|
- continue;
|
|
|
- }
|
|
|
- ret = nr_extents;
|
|
|
- *span = 1 + highest_block - lowest_block;
|
|
|
- if (page_no == 0)
|
|
|
- page_no = 1; /* force Empty message */
|
|
|
- sis->max = page_no;
|
|
|
- sis->pages = page_no - 1;
|
|
|
- sis->highest_bit = page_no - 1;
|
|
|
-out:
|
|
|
- return ret;
|
|
|
-bad_bmap:
|
|
|
- printk(KERN_ERR "swapon: swapfile has holes\n");
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ return generic_swapfile_activate(sis, swap_file, span);
|
|
|
}
|
|
|
|
|
|
static void enable_swap_info(struct swap_info_struct *p, int prio,
|