diff options
Diffstat (limited to 'lib/test_hmm.c')
| -rw-r--r-- | lib/test_hmm.c | 72 | 
1 files changed, 25 insertions, 47 deletions
| diff --git a/lib/test_hmm.c b/lib/test_hmm.c index 056f2e411d7b..5b144bc5c4ec 100644 --- a/lib/test_hmm.c +++ b/lib/test_hmm.c @@ -195,7 +195,8 @@ static int dmirror_fops_release(struct inode *inode, struct file *filp)  static struct dmirror_chunk *dmirror_page_to_chunk(struct page *page)  { -	return container_of(page->pgmap, struct dmirror_chunk, pagemap); +	return container_of(page_pgmap(page), struct dmirror_chunk, +			    pagemap);  }  static struct dmirror_device *dmirror_page_to_device(struct page *page) @@ -706,34 +707,23 @@ static int dmirror_check_atomic(struct dmirror *dmirror, unsigned long start,  	return 0;  } -static int dmirror_atomic_map(unsigned long start, unsigned long end, -			      struct page **pages, struct dmirror *dmirror) +static int dmirror_atomic_map(unsigned long addr, struct page *page, +		struct dmirror *dmirror)  { -	unsigned long pfn, mapped = 0; -	int i; +	void *entry;  	/* Map the migrated pages into the device's page tables. */  	mutex_lock(&dmirror->mutex); -	for (i = 0, pfn = start >> PAGE_SHIFT; pfn < (end >> PAGE_SHIFT); pfn++, i++) { -		void *entry; - -		if (!pages[i]) -			continue; - -		entry = pages[i]; -		entry = xa_tag_pointer(entry, DPT_XA_TAG_ATOMIC); -		entry = xa_store(&dmirror->pt, pfn, entry, GFP_ATOMIC); -		if (xa_is_err(entry)) { -			mutex_unlock(&dmirror->mutex); -			return xa_err(entry); -		} - -		mapped++; +	entry = xa_tag_pointer(page, DPT_XA_TAG_ATOMIC); +	entry = xa_store(&dmirror->pt, addr >> PAGE_SHIFT, entry, GFP_ATOMIC); +	if (xa_is_err(entry)) { +		mutex_unlock(&dmirror->mutex); +		return xa_err(entry);  	}  	mutex_unlock(&dmirror->mutex); -	return mapped; +	return 0;  }  static int dmirror_migrate_finalize_and_map(struct migrate_vma *args, @@ -780,10 +770,8 @@ static int dmirror_exclusive(struct dmirror *dmirror,  	unsigned long start, end, addr;  	unsigned long size = cmd->npages << PAGE_SHIFT;  	struct mm_struct *mm = dmirror->notifier.mm; -	struct page *pages[64];  	struct dmirror_bounce bounce; -	unsigned long next; -	int ret; +	int ret = 0;  	start = cmd->addr;  	end = start + size; @@ -795,36 +783,26 @@ static int dmirror_exclusive(struct dmirror *dmirror,  		return -EINVAL;  	mmap_read_lock(mm); -	for (addr = start; addr < end; addr = next) { -		unsigned long mapped = 0; -		int i; - -		next = min(end, addr + (ARRAY_SIZE(pages) << PAGE_SHIFT)); +	for (addr = start; !ret && addr < end; addr += PAGE_SIZE) { +		struct folio *folio; +		struct page *page; -		ret = make_device_exclusive_range(mm, addr, next, pages, NULL); -		/* -		 * Do dmirror_atomic_map() iff all pages are marked for -		 * exclusive access to avoid accessing uninitialized -		 * fields of pages. -		 */ -		if (ret == (next - addr) >> PAGE_SHIFT) -			mapped = dmirror_atomic_map(addr, next, pages, dmirror); -		for (i = 0; i < ret; i++) { -			if (pages[i]) { -				unlock_page(pages[i]); -				put_page(pages[i]); -			} +		page = make_device_exclusive(mm, addr, NULL, &folio); +		if (IS_ERR(page)) { +			ret = PTR_ERR(page); +			break;  		} -		if (addr + (mapped << PAGE_SHIFT) < next) { -			mmap_read_unlock(mm); -			mmput(mm); -			return -EBUSY; -		} +		ret = dmirror_atomic_map(addr, page, dmirror); +		folio_unlock(folio); +		folio_put(folio);  	}  	mmap_read_unlock(mm);  	mmput(mm); +	if (ret) +		return ret; +  	/* Return the migrated data for verification. */  	ret = dmirror_bounce_init(&bounce, start, size);  	if (ret) | 
