diff options
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/hugetlbfs/inode.c | 3 | ||||
-rw-r--r-- | fs/nfs/internal.h | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 4 | ||||
-rw-r--r-- | include/linux/fs.h | 9 | ||||
-rw-r--r-- | include/linux/migrate.h | 2 | ||||
-rw-r--r-- | mm/migrate.c | 129 |
7 files changed, 106 insertions, 47 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index f99a099a7747..1375494c8cb6 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -872,7 +872,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
872 | 872 | ||
873 | #ifdef CONFIG_MIGRATION | 873 | #ifdef CONFIG_MIGRATION |
874 | static int btree_migratepage(struct address_space *mapping, | 874 | static int btree_migratepage(struct address_space *mapping, |
875 | struct page *newpage, struct page *page) | 875 | struct page *newpage, struct page *page, bool sync) |
876 | { | 876 | { |
877 | /* | 877 | /* |
878 | * we can't safely write a btree page from here, | 878 | * we can't safely write a btree page from here, |
@@ -887,7 +887,7 @@ static int btree_migratepage(struct address_space *mapping, | |||
887 | if (page_has_private(page) && | 887 | if (page_has_private(page) && |
888 | !try_to_release_page(page, GFP_KERNEL)) | 888 | !try_to_release_page(page, GFP_KERNEL)) |
889 | return -EAGAIN; | 889 | return -EAGAIN; |
890 | return migrate_page(mapping, newpage, page); | 890 | return migrate_page(mapping, newpage, page, sync); |
891 | } | 891 | } |
892 | #endif | 892 | #endif |
893 | 893 | ||
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index e425ad9d0490..06fd4608a990 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -583,7 +583,8 @@ static int hugetlbfs_set_page_dirty(struct page *page) | |||
583 | } | 583 | } |
584 | 584 | ||
585 | static int hugetlbfs_migrate_page(struct address_space *mapping, | 585 | static int hugetlbfs_migrate_page(struct address_space *mapping, |
586 | struct page *newpage, struct page *page) | 586 | struct page *newpage, struct page *page, |
587 | bool sync) | ||
587 | { | 588 | { |
588 | int rc; | 589 | int rc; |
589 | 590 | ||
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 5ee92538b063..114398a15830 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -332,7 +332,7 @@ void nfs_commit_release_pages(struct nfs_write_data *data); | |||
332 | 332 | ||
333 | #ifdef CONFIG_MIGRATION | 333 | #ifdef CONFIG_MIGRATION |
334 | extern int nfs_migrate_page(struct address_space *, | 334 | extern int nfs_migrate_page(struct address_space *, |
335 | struct page *, struct page *); | 335 | struct page *, struct page *, bool); |
336 | #else | 336 | #else |
337 | #define nfs_migrate_page NULL | 337 | #define nfs_migrate_page NULL |
338 | #endif | 338 | #endif |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 0c3885255f97..889e98bc5a21 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1688,7 +1688,7 @@ out_error: | |||
1688 | 1688 | ||
1689 | #ifdef CONFIG_MIGRATION | 1689 | #ifdef CONFIG_MIGRATION |
1690 | int nfs_migrate_page(struct address_space *mapping, struct page *newpage, | 1690 | int nfs_migrate_page(struct address_space *mapping, struct page *newpage, |
1691 | struct page *page) | 1691 | struct page *page, bool sync) |
1692 | { | 1692 | { |
1693 | /* | 1693 | /* |
1694 | * If PagePrivate is set, then the page is currently associated with | 1694 | * If PagePrivate is set, then the page is currently associated with |
@@ -1703,7 +1703,7 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage, | |||
1703 | 1703 | ||
1704 | nfs_fscache_release_page(page, GFP_KERNEL); | 1704 | nfs_fscache_release_page(page, GFP_KERNEL); |
1705 | 1705 | ||
1706 | return migrate_page(mapping, newpage, page); | 1706 | return migrate_page(mapping, newpage, page, sync); |
1707 | } | 1707 | } |
1708 | #endif | 1708 | #endif |
1709 | 1709 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index a7409bc157e0..b92b73d0b2b9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -609,9 +609,12 @@ struct address_space_operations { | |||
609 | loff_t offset, unsigned long nr_segs); | 609 | loff_t offset, unsigned long nr_segs); |
610 | int (*get_xip_mem)(struct address_space *, pgoff_t, int, | 610 | int (*get_xip_mem)(struct address_space *, pgoff_t, int, |
611 | void **, unsigned long *); | 611 | void **, unsigned long *); |
612 | /* migrate the contents of a page to the specified target */ | 612 | /* |
613 | * migrate the contents of a page to the specified target. If sync | ||
614 | * is false, it must not block. | ||
615 | */ | ||
613 | int (*migratepage) (struct address_space *, | 616 | int (*migratepage) (struct address_space *, |
614 | struct page *, struct page *); | 617 | struct page *, struct page *, bool); |
615 | int (*launder_page) (struct page *); | 618 | int (*launder_page) (struct page *); |
616 | int (*is_partially_uptodate) (struct page *, read_descriptor_t *, | 619 | int (*is_partially_uptodate) (struct page *, read_descriptor_t *, |
617 | unsigned long); | 620 | unsigned long); |
@@ -2537,7 +2540,7 @@ extern int generic_check_addressable(unsigned, u64); | |||
2537 | 2540 | ||
2538 | #ifdef CONFIG_MIGRATION | 2541 | #ifdef CONFIG_MIGRATION |
2539 | extern int buffer_migrate_page(struct address_space *, | 2542 | extern int buffer_migrate_page(struct address_space *, |
2540 | struct page *, struct page *); | 2543 | struct page *, struct page *, bool); |
2541 | #else | 2544 | #else |
2542 | #define buffer_migrate_page NULL | 2545 | #define buffer_migrate_page NULL |
2543 | #endif | 2546 | #endif |
diff --git a/include/linux/migrate.h b/include/linux/migrate.h index e39aeecfe9a2..14e6d2a88475 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h | |||
@@ -11,7 +11,7 @@ typedef struct page *new_page_t(struct page *, unsigned long private, int **); | |||
11 | 11 | ||
12 | extern void putback_lru_pages(struct list_head *l); | 12 | extern void putback_lru_pages(struct list_head *l); |
13 | extern int migrate_page(struct address_space *, | 13 | extern int migrate_page(struct address_space *, |
14 | struct page *, struct page *); | 14 | struct page *, struct page *, bool); |
15 | extern int migrate_pages(struct list_head *l, new_page_t x, | 15 | extern int migrate_pages(struct list_head *l, new_page_t x, |
16 | unsigned long private, bool offlining, | 16 | unsigned long private, bool offlining, |
17 | bool sync); | 17 | bool sync); |
diff --git a/mm/migrate.c b/mm/migrate.c index fc391985899f..4e86f3bacb85 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -216,6 +216,55 @@ out: | |||
216 | pte_unmap_unlock(ptep, ptl); | 216 | pte_unmap_unlock(ptep, ptl); |
217 | } | 217 | } |
218 | 218 | ||
219 | #ifdef CONFIG_BLOCK | ||
220 | /* Returns true if all buffers are successfully locked */ | ||
221 | static bool buffer_migrate_lock_buffers(struct buffer_head *head, bool sync) | ||
222 | { | ||
223 | struct buffer_head *bh = head; | ||
224 | |||
225 | /* Simple case, sync compaction */ | ||
226 | if (sync) { | ||
227 | do { | ||
228 | get_bh(bh); | ||
229 | lock_buffer(bh); | ||
230 | bh = bh->b_this_page; | ||
231 | |||
232 | } while (bh != head); | ||
233 | |||
234 | return true; | ||
235 | } | ||
236 | |||
237 | /* async case, we cannot block on lock_buffer so use trylock_buffer */ | ||
238 | do { | ||
239 | get_bh(bh); | ||
240 | if (!trylock_buffer(bh)) { | ||
241 | /* | ||
242 | * We failed to lock the buffer and cannot stall in | ||
243 | * async migration. Release the taken locks | ||
244 | */ | ||
245 | struct buffer_head *failed_bh = bh; | ||
246 | put_bh(failed_bh); | ||
247 | bh = head; | ||
248 | while (bh != failed_bh) { | ||
249 | unlock_buffer(bh); | ||
250 | put_bh(bh); | ||
251 | bh = bh->b_this_page; | ||
252 | } | ||
253 | return false; | ||
254 | } | ||
255 | |||
256 | bh = bh->b_this_page; | ||
257 | } while (bh != head); | ||
258 | return true; | ||
259 | } | ||
260 | #else | ||
261 | static inline bool buffer_migrate_lock_buffers(struct buffer_head *head, | ||
262 | bool sync) | ||
263 | { | ||
264 | return true; | ||
265 | } | ||
266 | #endif /* CONFIG_BLOCK */ | ||
267 | |||
219 | /* | 268 | /* |
220 | * Replace the page in the mapping. | 269 | * Replace the page in the mapping. |
221 | * | 270 | * |
@@ -225,7 +274,8 @@ out: | |||
225 | * 3 for pages with a mapping and PagePrivate/PagePrivate2 set. | 274 | * 3 for pages with a mapping and PagePrivate/PagePrivate2 set. |
226 | */ | 275 | */ |
227 | static int migrate_page_move_mapping(struct address_space *mapping, | 276 | static int migrate_page_move_mapping(struct address_space *mapping, |
228 | struct page *newpage, struct page *page) | 277 | struct page *newpage, struct page *page, |
278 | struct buffer_head *head, bool sync) | ||
229 | { | 279 | { |
230 | int expected_count; | 280 | int expected_count; |
231 | void **pslot; | 281 | void **pslot; |
@@ -255,6 +305,19 @@ static int migrate_page_move_mapping(struct address_space *mapping, | |||
255 | } | 305 | } |
256 | 306 | ||
257 | /* | 307 | /* |
308 | * In the async migration case of moving a page with buffers, lock the | ||
309 | * buffers using trylock before the mapping is moved. If the mapping | ||
310 | * was moved, we later failed to lock the buffers and could not move | ||
311 | * the mapping back due to an elevated page count, we would have to | ||
312 | * block waiting on other references to be dropped. | ||
313 | */ | ||
314 | if (!sync && head && !buffer_migrate_lock_buffers(head, sync)) { | ||
315 | page_unfreeze_refs(page, expected_count); | ||
316 | spin_unlock_irq(&mapping->tree_lock); | ||
317 | return -EAGAIN; | ||
318 | } | ||
319 | |||
320 | /* | ||
258 | * Now we know that no one else is looking at the page. | 321 | * Now we know that no one else is looking at the page. |
259 | */ | 322 | */ |
260 | get_page(newpage); /* add cache reference */ | 323 | get_page(newpage); /* add cache reference */ |
@@ -409,13 +472,13 @@ EXPORT_SYMBOL(fail_migrate_page); | |||
409 | * Pages are locked upon entry and exit. | 472 | * Pages are locked upon entry and exit. |
410 | */ | 473 | */ |
411 | int migrate_page(struct address_space *mapping, | 474 | int migrate_page(struct address_space *mapping, |
412 | struct page *newpage, struct page *page) | 475 | struct page *newpage, struct page *page, bool sync) |
413 | { | 476 | { |
414 | int rc; | 477 | int rc; |
415 | 478 | ||
416 | BUG_ON(PageWriteback(page)); /* Writeback must be complete */ | 479 | BUG_ON(PageWriteback(page)); /* Writeback must be complete */ |
417 | 480 | ||
418 | rc = migrate_page_move_mapping(mapping, newpage, page); | 481 | rc = migrate_page_move_mapping(mapping, newpage, page, NULL, sync); |
419 | 482 | ||
420 | if (rc) | 483 | if (rc) |
421 | return rc; | 484 | return rc; |
@@ -432,28 +495,28 @@ EXPORT_SYMBOL(migrate_page); | |||
432 | * exist. | 495 | * exist. |
433 | */ | 496 | */ |
434 | int buffer_migrate_page(struct address_space *mapping, | 497 | int buffer_migrate_page(struct address_space *mapping, |
435 | struct page *newpage, struct page *page) | 498 | struct page *newpage, struct page *page, bool sync) |
436 | { | 499 | { |
437 | struct buffer_head *bh, *head; | 500 | struct buffer_head *bh, *head; |
438 | int rc; | 501 | int rc; |
439 | 502 | ||
440 | if (!page_has_buffers(page)) | 503 | if (!page_has_buffers(page)) |
441 | return migrate_page(mapping, newpage, page); | 504 | return migrate_page(mapping, newpage, page, sync); |
442 | 505 | ||
443 | head = page_buffers(page); | 506 | head = page_buffers(page); |
444 | 507 | ||
445 | rc = migrate_page_move_mapping(mapping, newpage, page); | 508 | rc = migrate_page_move_mapping(mapping, newpage, page, head, sync); |
446 | 509 | ||
447 | if (rc) | 510 | if (rc) |
448 | return rc; | 511 | return rc; |
449 | 512 | ||
450 | bh = head; | 513 | /* |
451 | do { | 514 | * In the async case, migrate_page_move_mapping locked the buffers |
452 | get_bh(bh); | 515 | * with an IRQ-safe spinlock held. In the sync case, the buffers |
453 | lock_buffer(bh); | 516 | * need to be locked now |
454 | bh = bh->b_this_page; | 517 | */ |
455 | 518 | if (sync) | |
456 | } while (bh != head); | 519 | BUG_ON(!buffer_migrate_lock_buffers(head, sync)); |
457 | 520 | ||
458 | ClearPagePrivate(page); | 521 | ClearPagePrivate(page); |
459 | set_page_private(newpage, page_private(page)); | 522 | set_page_private(newpage, page_private(page)); |
@@ -530,10 +593,13 @@ static int writeout(struct address_space *mapping, struct page *page) | |||
530 | * Default handling if a filesystem does not provide a migration function. | 593 | * Default handling if a filesystem does not provide a migration function. |
531 | */ | 594 | */ |
532 | static int fallback_migrate_page(struct address_space *mapping, | 595 | static int fallback_migrate_page(struct address_space *mapping, |
533 | struct page *newpage, struct page *page) | 596 | struct page *newpage, struct page *page, bool sync) |
534 | { | 597 | { |
535 | if (PageDirty(page)) | 598 | if (PageDirty(page)) { |
599 | if (!sync) | ||
600 | return -EBUSY; | ||
536 | return writeout(mapping, page); | 601 | return writeout(mapping, page); |
602 | } | ||
537 | 603 | ||
538 | /* | 604 | /* |
539 | * Buffers may be managed in a filesystem specific way. | 605 | * Buffers may be managed in a filesystem specific way. |
@@ -543,7 +609,7 @@ static int fallback_migrate_page(struct address_space *mapping, | |||
543 | !try_to_release_page(page, GFP_KERNEL)) | 609 | !try_to_release_page(page, GFP_KERNEL)) |
544 | return -EAGAIN; | 610 | return -EAGAIN; |
545 | 611 | ||
546 | return migrate_page(mapping, newpage, page); | 612 | return migrate_page(mapping, newpage, page, sync); |
547 | } | 613 | } |
548 | 614 | ||
549 | /* | 615 | /* |
@@ -579,29 +645,18 @@ static int move_to_new_page(struct page *newpage, struct page *page, | |||
579 | 645 | ||
580 | mapping = page_mapping(page); | 646 | mapping = page_mapping(page); |
581 | if (!mapping) | 647 | if (!mapping) |
582 | rc = migrate_page(mapping, newpage, page); | 648 | rc = migrate_page(mapping, newpage, page, sync); |
583 | else { | 649 | else if (mapping->a_ops->migratepage) |
584 | /* | 650 | /* |
585 | * Do not writeback pages if !sync and migratepage is | 651 | * Most pages have a mapping and most filesystems provide a |
586 | * not pointing to migrate_page() which is nonblocking | 652 | * migratepage callback. Anonymous pages are part of swap |
587 | * (swapcache/tmpfs uses migratepage = migrate_page). | 653 | * space which also has its own migratepage callback. This |
654 | * is the most common path for page migration. | ||
588 | */ | 655 | */ |
589 | if (PageDirty(page) && !sync && | 656 | rc = mapping->a_ops->migratepage(mapping, |
590 | mapping->a_ops->migratepage != migrate_page) | 657 | newpage, page, sync); |
591 | rc = -EBUSY; | 658 | else |
592 | else if (mapping->a_ops->migratepage) | 659 | rc = fallback_migrate_page(mapping, newpage, page, sync); |
593 | /* | ||
594 | * Most pages have a mapping and most filesystems | ||
595 | * should provide a migration function. Anonymous | ||
596 | * pages are part of swap space which also has its | ||
597 | * own migration function. This is the most common | ||
598 | * path for page migration. | ||
599 | */ | ||
600 | rc = mapping->a_ops->migratepage(mapping, | ||
601 | newpage, page); | ||
602 | else | ||
603 | rc = fallback_migrate_page(mapping, newpage, page); | ||
604 | } | ||
605 | 660 | ||
606 | if (rc) { | 661 | if (rc) { |
607 | newpage->mapping = NULL; | 662 | newpage->mapping = NULL; |