Unverified Commit 0a28d59d authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files
parents 25fdb6da 75acda4d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -478,6 +478,7 @@ extern void __delete_from_swap_cache(struct page *page,
extern void delete_from_swap_cache(struct page *);
extern void clear_shadow_from_swap_cache(int type, unsigned long begin,
				unsigned long end);
void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry);
extern void free_page_and_swap_cache(struct page *);
extern void free_pages_and_swap_cache(struct page **, int);
extern struct page *lookup_swap_cache(swp_entry_t entry,
@@ -638,6 +639,10 @@ static inline int swap_writepage(struct page *p, struct writeback_control *wbc)
	return 0;
}

static inline void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry)
{
}

static inline struct page *lookup_swap_cache(swp_entry_t swp,
					     struct vm_area_struct *vma,
					     unsigned long addr)
+20 −0
Original line number Diff line number Diff line
@@ -3387,6 +3387,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
	struct vm_area_struct *vma = vmf->vma;
	struct page *page = NULL, *swapcache;
	struct swap_info_struct *si = NULL;
	bool need_clear_cache = false;
	swp_entry_t entry;
	pte_t pte;
	int locked;
@@ -3444,6 +3445,20 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
	if (!page) {
		if (data_race(si->flags & SWP_SYNCHRONOUS_IO) &&
		    __swap_count(entry) == 1) {
			/*
			 * Prevent parallel swapin from proceeding with
			 * the cache flag. Otherwise, another thread may
			 * finish swapin first, free the entry, and swapout
			 * reusing the same entry. It's undetectable as
			 * pte_same() returns true due to entry reuse.
			 */
			if (swapcache_prepare(entry)) {
				/* Relax a bit to prevent rapid repeated page faults */
				schedule_timeout_uninterruptible(1);
				goto out;
			}
			need_clear_cache = true;

			/* skip swapcache */
			page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
							vmf->address);
@@ -3613,6 +3628,9 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
unlock:
	pte_unmap_unlock(vmf->pte, vmf->ptl);
out:
	/* Clear the swap cache pin for direct swapin after PTL unlock */
	if (need_clear_cache)
		swapcache_clear(si, entry);
	if (si)
		put_swap_device(si);
	return ret;
@@ -3626,6 +3644,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
		unlock_page(swapcache);
		put_page(swapcache);
	}
	if (need_clear_cache)
		swapcache_clear(si, entry);
	if (si)
		put_swap_device(si);
	return ret;
+13 −0
Original line number Diff line number Diff line
@@ -3688,6 +3688,19 @@ int swapcache_prepare(swp_entry_t entry)
	return __swap_duplicate(entry, SWAP_HAS_CACHE);
}

void swapcache_clear(struct swap_info_struct *si, swp_entry_t entry)
{
	struct swap_cluster_info *ci;
	unsigned long offset = swp_offset(entry);
	unsigned char usage;

	ci = lock_cluster_or_swap_info(si, offset);
	usage = __swap_entry_free_locked(si, offset, SWAP_HAS_CACHE);
	unlock_cluster_or_swap_info(si, ci);
	if (!usage)
		free_swap_slot(entry);
}

struct swap_info_struct *swp_swap_info(swp_entry_t entry)
{
	return swap_type_to_swap_info(swp_type(entry));