Unverified Commit ab9b23cd authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files
parents 49177142 0cf13f3b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -468,6 +468,7 @@ extern int add_to_swap_cache(struct page *, swp_entry_t, gfp_t);
extern int __add_to_swap_cache(struct page *page, swp_entry_t entry);
extern void __delete_from_swap_cache(struct page *);
extern void delete_from_swap_cache(struct page *);
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,
@@ -609,6 +610,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)
+22 −1
Original line number Diff line number Diff line
@@ -2919,6 +2919,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
	struct vm_area_struct *vma = vmf->vma;
	struct page *page = NULL, *swapcache;
	struct mem_cgroup *memcg;
	struct swap_info_struct *si = NULL;
	bool need_clear_cache = false;
	swp_entry_t entry;
	pte_t pte;
	int locked;
@@ -2974,10 +2976,24 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
	swapcache = page;

	if (!page) {
		struct swap_info_struct *si = swp_swap_info(entry);
		si = swp_swap_info(entry);

		if (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);
@@ -3133,6 +3149,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);
	return ret;
out_nomap:
	mem_cgroup_cancel_charge(page, memcg, false);
@@ -3145,6 +3164,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);
	return ret;
}

+13 −0
Original line number Diff line number Diff line
@@ -3590,6 +3590,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));