diff --git a/include/linux/swap.h b/include/linux/swap.h
index 34de0d8bf4fa..984a652b9925 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -446,8 +446,8 @@ extern swp_entry_t get_swap_page_of_type(int);
 extern int get_swap_pages(int n, swp_entry_t swp_entries[], int entry_size);
 extern int add_swap_count_continuation(swp_entry_t, gfp_t);
 extern void swap_shmem_alloc(swp_entry_t);
-extern int swap_duplicate(swp_entry_t);
-extern int swapcache_prepare(swp_entry_t);
+extern int swap_duplicate(swp_entry_t *entry, int entry_size);
+extern int swapcache_prepare(swp_entry_t entry, int entry_size);
 extern void swap_free(swp_entry_t);
 extern void swapcache_free_entries(swp_entry_t *entries, int n);
 extern int free_swap_and_cache(swp_entry_t);
@@ -505,7 +505,8 @@ static inline void show_swap_cache_info(void)
 }
 
 #define free_swap_and_cache(e) ({(is_migration_entry(e) || is_device_private_entry(e));})
-#define swapcache_prepare(e) ({(is_migration_entry(e) || is_device_private_entry(e));})
+#define swapcache_prepare(e, s)						\
+	({(is_migration_entry(e) || is_device_private_entry(e)); })
 
 static inline int add_swap_count_continuation(swp_entry_t swp, gfp_t gfp_mask)
 {
@@ -516,7 +517,7 @@ static inline void swap_shmem_alloc(swp_entry_t swp)
 {
 }
 
-static inline int swap_duplicate(swp_entry_t swp)
+static inline int swap_duplicate(swp_entry_t *swp, int entry_size)
 {
 	return 0;
 }
diff --git a/mm/memory.c b/mm/memory.c
index fa8894c70575..207e90717305 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -709,7 +709,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 		swp_entry_t entry = pte_to_swp_entry(pte);
 
 		if (likely(!non_swap_entry(entry))) {
-			if (swap_duplicate(entry) < 0)
+			if (swap_duplicate(&entry, 1) < 0)
 				return entry.val;
 
 			/* make sure dst_mm is on swapoff's mmlist. */
diff --git a/mm/rmap.c b/mm/rmap.c
index 1e79fac3186b..3bb4be720bc0 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1598,7 +1598,7 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 				break;
 			}
 
-			if (swap_duplicate(entry) < 0) {
+			if (swap_duplicate(&entry, 1) < 0) {
 				set_pte_at(mm, address, pvmw.pte, pteval);
 				ret = false;
 				page_vma_mapped_walk_done(&pvmw);
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 8f53d2a80253..bca34fc7a5e5 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -402,7 +402,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
 		/*
 		 * Swap entry may have been freed since our caller observed it.
 		 */
-		err = swapcache_prepare(entry);
+		err = swapcache_prepare(entry, 1);
 		if (err == -EEXIST) {
 			/*
 			 * We might race against get_swap_page() and stumble
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 6a570ef00fa7..a5a1ab46dab7 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -534,6 +534,40 @@ static void dec_cluster_info_page(struct swap_info_struct *p,
 		free_cluster(p, idx);
 }
 
+/*
+ * When swapout a THP in one piece, PMD page mappings to THP are
+ * replaced by PMD swap mappings to the corresponding swap cluster.
+ * cluster_swapcount() returns the PMD swap mapping count.
+ *
+ * cluster_count() = PMD swap mapping count + count of allocated swap
+ * entries in cluster.  If a cluster is mapped by PMD, all swap
+ * entries inside is used, so here cluster_count() = PMD swap mapping
+ * count + SWAPFILE_CLUSTER.
+ */
+static inline int cluster_swapcount(struct swap_cluster_info *ci)
+{
+	VM_BUG_ON(!cluster_is_huge(ci) || cluster_count(ci) < SWAPFILE_CLUSTER);
+	return cluster_count(ci) - SWAPFILE_CLUSTER;
+}
+
+/*
+ * Set PMD swap mapping count for the huge cluster
+ */
+static inline void cluster_set_swapcount(struct swap_cluster_info *ci,
+					 unsigned int count)
+{
+	VM_BUG_ON(!cluster_is_huge(ci) || cluster_count(ci) < SWAPFILE_CLUSTER);
+	cluster_set_count(ci, SWAPFILE_CLUSTER + count);
+}
+
+static inline void cluster_add_swapcount(struct swap_cluster_info *ci, int add)
+{
+	int count = cluster_swapcount(ci) + add;
+
+	VM_BUG_ON(count < 0);
+	cluster_set_swapcount(ci, count);
+}
+
 /*
  * It's possible scan_swap_map() uses a free cluster in the middle of free
  * cluster list. Avoiding such abuse to avoid list corruption.
@@ -3487,35 +3521,66 @@ static int __swap_duplicate_locked(struct swap_info_struct *p,
 }
 
 /*
- * Verify that a swap entry is valid and increment its swap map count.
+ * Verify that the swap entries from *entry is valid and increment their
+ * PMD/PTE swap mapping count.
  *
  * Returns error code in following case.
  * - success -> 0
  * - swp_entry is invalid -> EINVAL
- * - swp_entry is migration entry -> EINVAL
  * - swap-cache reference is requested but there is already one. -> EEXIST
  * - swap-cache reference is requested but the entry is not used. -> ENOENT
  * - swap-mapped reference requested but needs continued swap count. -> ENOMEM
+ * - the huge swap cluster has been split. -> ENOTDIR
  */
-static int __swap_duplicate(swp_entry_t entry, unsigned char usage)
+static int __swap_duplicate(swp_entry_t *entry, int entry_size,
+			    unsigned char usage)
 {
 	struct swap_info_struct *p;
 	struct swap_cluster_info *ci;
 	unsigned long offset;
 	int err = -EINVAL;
+	int i, size = swap_entry_size(entry_size);
 
-	p = get_swap_device(entry);
+	p = get_swap_device(*entry);
 	if (!p)
 		goto out;
 
-	offset = swp_offset(entry);
+	offset = swp_offset(*entry);
 	ci = lock_cluster_or_swap_info(p, offset);
-	err = __swap_duplicate_locked(p, offset, usage);
+	if (size == SWAPFILE_CLUSTER) {
+		/*
+		 * The huge swap cluster has been split, for example, failed to
+		 * allocate huge page during swapin, the caller should split
+		 * the PMD swap mapping and operate on normal swap entries.
+		 */
+		if (!cluster_is_huge(ci)) {
+			err = -ENOTDIR;
+			goto unlock;
+		}
+		VM_BUG_ON(!IS_ALIGNED(offset, size));
+		/* If cluster is huge, all swap entries inside is in-use */
+		VM_BUG_ON(cluster_count(ci) < SWAPFILE_CLUSTER);
+	}
+	/* p->swap_map[] = PMD swap map count + PTE swap map count */
+	for (i = 0; i < size; i++) {
+		err = __swap_duplicate_locked(p, offset + i, usage);
+		if (err && size != 1) {
+			*entry = swp_entry(p->type, offset + i);
+			goto undup;
+		}
+	}
+	if (size == SWAPFILE_CLUSTER && usage == 1)
+		cluster_add_swapcount(ci, usage);
+unlock:
 	unlock_cluster_or_swap_info(p, ci);
 
 	put_swap_device(p);
 out:
 	return err;
+undup:
+	for (i--; i >= 0; i--)
+		__swap_entry_free_locked(p, offset + i, usage);
+	goto unlock;
 }
 
 /*
@@ -3524,36 +3589,44 @@ static int __swap_duplicate(swp_entry_t entry, unsigned char usage)
  */
 void swap_shmem_alloc(swp_entry_t entry)
 {
-	__swap_duplicate(entry, SWAP_MAP_SHMEM);
+	__swap_duplicate(&entry, 1, SWAP_MAP_SHMEM);
 }
 
 /*
  * Increase reference count of swap entry by 1.
- * Returns 0 for success, or -ENOMEM if a swap_count_continuation is required
- * but could not be atomically allocated.  Returns 0, just as if it succeeded,
- * if __swap_duplicate() fails for another reason (-EINVAL or -ENOENT), which
- * might occur if a page table entry has got corrupted.
+ *
+ * Return error code in following case.
+ * - success -> 0
+ * - swap_count_continuation is required but could not be atomically allocated.
+ *   *entry is used to return swap entry to call add_swap_count_continuation().
+ *								      -> ENOMEM
+ * - otherwise same as __swap_duplicate()
  */
-int swap_duplicate(swp_entry_t entry)
+int swap_duplicate(swp_entry_t *entry, int entry_size)
 {
 	int err = 0;
 
-	while (!err && __swap_duplicate(entry, 1) == -ENOMEM)
-		err = add_swap_count_continuation(entry, GFP_ATOMIC);
+	while (!err &&
+	       (err = __swap_duplicate(entry, entry_size, 1)) == -ENOMEM)
+		err = add_swap_count_continuation(*entry, GFP_ATOMIC);
+	/* If kernel works correctly, other errno is impossible */
+	VM_BUG_ON(err && err != -ENOMEM && err != -ENOTDIR);
 	return err;
 }
 
 /*
  * @entry: swap entry for which we allocate swap cache.
+ * @entry_size: size of the swap entry, 1 or SWAPFILE_CLUSTER
  *
  * Called when allocating swap cache for existing swap entry,
  * This can return error codes. Returns 0 at success.
- * -EBUSY means there is a swap cache.
- * Note: return code is different from swap_duplicate().
+ * -EINVAL means the swap device has been swapoff.
+ * -EEXIST means there is a swap cache.
+ * Otherwise same as __swap_duplicate()
  */
-int swapcache_prepare(swp_entry_t entry)
+int swapcache_prepare(swp_entry_t entry, int entry_size)
 {
-	return __swap_duplicate(entry, SWAP_HAS_CACHE);
+	return __swap_duplicate(&entry, entry_size, SWAP_HAS_CACHE);
 }
 
 struct swap_info_struct *swp_swap_info(swp_entry_t entry)
