diff options
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index b4979d423d2b..e9b161bde95b 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -294,7 +294,7 @@ out: | |||
294 | static int migrate_page_move_mapping(struct address_space *mapping, | 294 | static int migrate_page_move_mapping(struct address_space *mapping, |
295 | struct page *newpage, struct page *page) | 295 | struct page *newpage, struct page *page) |
296 | { | 296 | { |
297 | struct page **radix_pointer; | 297 | void **pslot; |
298 | 298 | ||
299 | if (!mapping) { | 299 | if (!mapping) { |
300 | /* Anonymous page */ | 300 | /* Anonymous page */ |
@@ -305,12 +305,11 @@ static int migrate_page_move_mapping(struct address_space *mapping, | |||
305 | 305 | ||
306 | write_lock_irq(&mapping->tree_lock); | 306 | write_lock_irq(&mapping->tree_lock); |
307 | 307 | ||
308 | radix_pointer = (struct page **)radix_tree_lookup_slot( | 308 | pslot = radix_tree_lookup_slot(&mapping->page_tree, |
309 | &mapping->page_tree, | 309 | page_index(page)); |
310 | page_index(page)); | ||
311 | 310 | ||
312 | if (page_count(page) != 2 + !!PagePrivate(page) || | 311 | if (page_count(page) != 2 + !!PagePrivate(page) || |
313 | *radix_pointer != page) { | 312 | (struct page *)radix_tree_deref_slot(pslot) != page) { |
314 | write_unlock_irq(&mapping->tree_lock); | 313 | write_unlock_irq(&mapping->tree_lock); |
315 | return -EAGAIN; | 314 | return -EAGAIN; |
316 | } | 315 | } |
@@ -318,7 +317,7 @@ static int migrate_page_move_mapping(struct address_space *mapping, | |||
318 | /* | 317 | /* |
319 | * Now we know that no one else is looking at the page. | 318 | * Now we know that no one else is looking at the page. |
320 | */ | 319 | */ |
321 | get_page(newpage); | 320 | get_page(newpage); /* add cache reference */ |
322 | #ifdef CONFIG_SWAP | 321 | #ifdef CONFIG_SWAP |
323 | if (PageSwapCache(page)) { | 322 | if (PageSwapCache(page)) { |
324 | SetPageSwapCache(newpage); | 323 | SetPageSwapCache(newpage); |
@@ -326,8 +325,14 @@ static int migrate_page_move_mapping(struct address_space *mapping, | |||
326 | } | 325 | } |
327 | #endif | 326 | #endif |
328 | 327 | ||
329 | *radix_pointer = newpage; | 328 | radix_tree_replace_slot(pslot, newpage); |
329 | |||
330 | /* | ||
331 | * Drop cache reference from old page. | ||
332 | * We know this isn't the last reference. | ||
333 | */ | ||
330 | __put_page(page); | 334 | __put_page(page); |
335 | |||
331 | write_unlock_irq(&mapping->tree_lock); | 336 | write_unlock_irq(&mapping->tree_lock); |
332 | 337 | ||
333 | return 0; | 338 | return 0; |