History

mm: handle multiple owners of device private pages in migrate_vma

Add a new src_owner field to struct migrate_vma. If the field is set, only device private pages with page->pgmap->owner equal to that field are migrated. If the field is not set only "normal" pages are migrated.

Christoph Hellwig committed 6 years ago

Commit 800bb1c1 parent f894ddd4 files · +16 −3Browse files

Unified · Split

4 files
  1. arch/powerpc/kvm/book3s_hv_uvmem.c +1 −0
  2. drivers/gpu/drm/nouveau/nouveau_dmem.c +1 −0
  3. include/linux/migrate.h +8 −0
  4. mm/migrate.c +6 −3
arch/powerpc/kvm/book3s_hv_uvmem.c+1−0
@@ -563,6 +563,7 @@ kvmppc_svm_page_out(struct vm_area_struct *vma, unsigned long start, · 562 unmodified lines
563 mig.end = end;563 mig.end = end;
564 mig.src = &src_pfn;564 mig.src = &src_pfn;
565 mig.dst = &dst_pfn;565 mig.dst = &dst_pfn;
566 mig.src_owner = &kvmppc_uvmem_pgmap;
566 567
567 mutex_lock(&kvm->arch.uvmem_lock);568 mutex_lock(&kvm->arch.uvmem_lock);
568 /* The requested page is already paged-out, nothing to do */569 /* The requested page is already paged-out, nothing to do */
drivers/gpu/drm/nouveau/nouveau_dmem.c+1−0
@@ -176,6 +176,7 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf) · 175 unmodified lines
176 .end = vmf->address + PAGE_SIZE,176 .end = vmf->address + PAGE_SIZE,
177 .src = &src,177 .src = &src,
178 .dst = &dst,178 .dst = &dst,
179 .src_owner = drm->dev,
179 };180 };
180 181
181 /*182 /*
include/linux/migrate.h+8−0
@@ -196,6 +196,14 @@ struct migrate_vma { · 195 unmodified lines
196 unsigned long npages;196 unsigned long npages;
197 unsigned long start;197 unsigned long start;
198 unsigned long end;198 unsigned long end;
199
200 /*
201 * Set to the owner value also stored in page->pgmap->owner for
202 * migrating out of device private memory. If set only device
203 * private pages with this owner are migrated. If not set
204 * device private pages are not migrated at all.
205 */
206 void *src_owner;
199};207};
200 208
201int migrate_vma_setup(struct migrate_vma *args);209int migrate_vma_setup(struct migrate_vma *args);
mm/migrate.c+6−3
@@ -2241,7 +2241,7 @@ again: · 2240 unmodified lines
2241 arch_enter_lazy_mmu_mode();2241 arch_enter_lazy_mmu_mode();
2242 2242
2243 for (; addr < end; addr += PAGE_SIZE, ptep++) {2243 for (; addr < end; addr += PAGE_SIZE, ptep++) {
2244 unsigned long mpfn, pfn;2244 unsigned long mpfn = 0, pfn;
2245 struct page *page;2245 struct page *page;
2246 swp_entry_t entry;2246 swp_entry_t entry;
2247 pte_t pte;2247 pte_t pte;
@@ -2255,8 +2255,6 @@ again: · 7 unmodified lines
2255 }2255 }
2256 2256
2257 if (!pte_present(pte)) {2257 if (!pte_present(pte)) {
2258 mpfn = 0;
2259
2260 /*2258 /*
2261 * Only care about unaddressable device page special2259 * Only care about unaddressable device page special
2262 * page table entry. Other special swap entries are not2260 * page table entry. Other special swap entries are not
@@ -2267,11 +2265,16 @@ again: · 4 unmodified lines
2267 goto next;2265 goto next;
2268 2266
2269 page = device_private_entry_to_page(entry);2267 page = device_private_entry_to_page(entry);
2268 if (page->pgmap->owner != migrate->src_owner)
2269 goto next;
2270
2270 mpfn = migrate_pfn(page_to_pfn(page)) |2271 mpfn = migrate_pfn(page_to_pfn(page)) |
2271 MIGRATE_PFN_MIGRATE;2272 MIGRATE_PFN_MIGRATE;
2272 if (is_write_device_private_entry(entry))2273 if (is_write_device_private_entry(entry))
2273 mpfn |= MIGRATE_PFN_WRITE;2274 mpfn |= MIGRATE_PFN_WRITE;
2274 } else {2275 } else {
2276 if (migrate->src_owner)
2277 goto next;
2275 pfn = pte_pfn(pte);2278 pfn = pte_pfn(pte);
2276 if (is_zero_pfn(pfn)) {2279 if (is_zero_pfn(pfn)) {
2277 mpfn = MIGRATE_PFN_MIGRATE;2280 mpfn = MIGRATE_PFN_MIGRATE;