aboutsummaryrefslogtreecommitdiffstats
path: root/mm/migrate.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/migrate.c')
-rw-r--r--mm/migrate.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index 385db89f0c33..037b0967c1e3 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -522,15 +522,12 @@ static int writeout(struct address_space *mapping, struct page *page)
522 remove_migration_ptes(page, page); 522 remove_migration_ptes(page, page);
523 523
524 rc = mapping->a_ops->writepage(page, &wbc); 524 rc = mapping->a_ops->writepage(page, &wbc);
525 if (rc < 0)
526 /* I/O Error writing */
527 return -EIO;
528 525
529 if (rc != AOP_WRITEPAGE_ACTIVATE) 526 if (rc != AOP_WRITEPAGE_ACTIVATE)
530 /* unlocked. Relock */ 527 /* unlocked. Relock */
531 lock_page(page); 528 lock_page(page);
532 529
533 return -EAGAIN; 530 return (rc < 0) ? -EIO : -EAGAIN;
534} 531}
535 532
536/* 533/*
@@ -990,25 +987,18 @@ out:
990/* 987/*
991 * Determine the nodes of an array of pages and store it in an array of status. 988 * Determine the nodes of an array of pages and store it in an array of status.
992 */ 989 */
993static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages, 990static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages,
994 const void __user * __user *pages, 991 const void __user **pages, int *status)
995 int __user *status)
996{ 992{
997 unsigned long i; 993 unsigned long i;
998 int err;
999 994
1000 down_read(&mm->mmap_sem); 995 down_read(&mm->mmap_sem);
1001 996
1002 for (i = 0; i < nr_pages; i++) { 997 for (i = 0; i < nr_pages; i++) {
1003 const void __user *p; 998 unsigned long addr = (unsigned long)(*pages);
1004 unsigned long addr;
1005 struct vm_area_struct *vma; 999 struct vm_area_struct *vma;
1006 struct page *page; 1000 struct page *page;
1007 1001 int err = -EFAULT;
1008 err = -EFAULT;
1009 if (get_user(p, pages+i))
1010 goto out;
1011 addr = (unsigned long) p;
1012 1002
1013 vma = find_vma(mm, addr); 1003 vma = find_vma(mm, addr);
1014 if (!vma) 1004 if (!vma)
@@ -1027,12 +1017,52 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
1027 1017
1028 err = page_to_nid(page); 1018 err = page_to_nid(page);
1029set_status: 1019set_status:
1030 put_user(err, status+i); 1020 *status = err;
1021
1022 pages++;
1023 status++;
1024 }
1025
1026 up_read(&mm->mmap_sem);
1027}
1028
1029/*
1030 * Determine the nodes of a user array of pages and store it in
1031 * a user array of status.
1032 */
1033static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
1034 const void __user * __user *pages,
1035 int __user *status)
1036{
1037#define DO_PAGES_STAT_CHUNK_NR 16
1038 const void __user *chunk_pages[DO_PAGES_STAT_CHUNK_NR];
1039 int chunk_status[DO_PAGES_STAT_CHUNK_NR];
1040 unsigned long i, chunk_nr = DO_PAGES_STAT_CHUNK_NR;
1041 int err;
1042
1043 for (i = 0; i < nr_pages; i += chunk_nr) {
1044 if (chunk_nr + i > nr_pages)
1045 chunk_nr = nr_pages - i;
1046
1047 err = copy_from_user(chunk_pages, &pages[i],
1048 chunk_nr * sizeof(*chunk_pages));
1049 if (err) {
1050 err = -EFAULT;
1051 goto out;
1052 }
1053
1054 do_pages_stat_array(mm, chunk_nr, chunk_pages, chunk_status);
1055
1056 err = copy_to_user(&status[i], chunk_status,
1057 chunk_nr * sizeof(*chunk_status));
1058 if (err) {
1059 err = -EFAULT;
1060 goto out;
1061 }
1031 } 1062 }
1032 err = 0; 1063 err = 0;
1033 1064
1034out: 1065out:
1035 up_read(&mm->mmap_sem);
1036 return err; 1066 return err;
1037} 1067}
1038 1068