Commit 68dfec3b authored by Chen Wandun's avatar Chen Wandun Committed by Zheng Zengkai
Browse files

mm/swapfile: use new way to fix broken kabi in swap_info_struct

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I645JI



-------------------------------

Commit 46d673d7 ("mm/swapfile: fix broken kabi in swap_info_struct")
uses KABI_EXTEND to fix kabi broken problem, but this is not the safest
way, so use new way to fix this prolem.

Introduce new struct swap_extend_info that contains extend info of swap,
meanwhile use KABI_USE to repalce memory space reserved by KABI_RESERVER.

Signed-off-by: default avatarChen Wandun <chenwandun@huawei.com>
Reviewed-by: default avatarzhangjialin <zhangjialin11@huawei.com>
Reviewed-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 5d934d94
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -246,6 +246,11 @@ struct swap_cluster_list {
	struct swap_cluster_info tail;
};

struct swap_extend_info {
	struct percpu_ref users;	/* indicate and keep swap device valid. */
	struct completion comp;		/* seldom referenced */
};

/*
 * The in-memory structure used to track swap areas.
 */
@@ -293,10 +298,8 @@ struct swap_info_struct {
					 */
	struct work_struct discard_work; /* discard worker */
	struct swap_cluster_list discard_clusters; /* discard clusters list */
	KABI_RESERVE(1)
	KABI_USE(1, struct swap_extend_info *sei)
	KABI_RESERVE(2)
	KABI_EXTEND(struct percpu_ref users)	/* indicate and keep swap device valid. */
	KABI_EXTEND(struct completion comp)	/* seldom referenced */
	struct plist_node avail_lists[]; /*
					   * entries in swap_avail_heads, one
					   * entry per node.
@@ -537,7 +540,7 @@ sector_t swap_page_sector(struct page *page);

static inline void put_swap_device(struct swap_info_struct *si)
{
	percpu_ref_put(&si->users);
	percpu_ref_put(&si->sei->users);
}

#else /* CONFIG_SWAP */
+21 −12
Original line number Diff line number Diff line
@@ -515,10 +515,10 @@ static void swap_discard_work(struct work_struct *work)

static void swap_users_ref_free(struct percpu_ref *ref)
{
	struct swap_info_struct *si;
	struct swap_extend_info *sei;

	si = container_of(ref, struct swap_info_struct, users);
	complete(&si->comp);
	sei = container_of(ref, struct swap_extend_info, users);
	complete(&sei->comp);
}

static void alloc_cluster(struct swap_info_struct *si, unsigned long idx)
@@ -1316,7 +1316,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry)
	si = swp_swap_info(entry);
	if (!si)
		goto bad_nofile;
	if (!percpu_ref_tryget_live(&si->users))
	if (!percpu_ref_tryget_live(&si->sei->users))
		goto out;
	/*
	 * Guarantee the si->users are checked before accessing other
@@ -1336,7 +1336,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry)
out:
	return NULL;
put_out:
	percpu_ref_put(&si->users);
	percpu_ref_put(&si->sei->users);
	return NULL;
}

@@ -2542,7 +2542,7 @@ static void enable_swap_info(struct swap_info_struct *p, int prio,
	/*
	 * Finished initializing swap device, now it's safe to reference it.
	 */
	percpu_ref_resurrect(&p->users);
	percpu_ref_resurrect(&p->sei->users);
	spin_lock(&swap_lock);
	spin_lock(&p->lock);
	_enable_swap_info(p);
@@ -2665,9 +2665,9 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
	 * We need synchronize_rcu() here to protect the accessing to
	 * the swap cache data structure.
	 */
	percpu_ref_kill(&p->users);
	percpu_ref_kill(&p->sei->users);
	synchronize_rcu();
	wait_for_completion(&p->comp);
	wait_for_completion(&p->sei->comp);

	flush_work(&p->discard_work);

@@ -2899,8 +2899,15 @@ static struct swap_info_struct *alloc_swap_info(void)
	if (!p)
		return ERR_PTR(-ENOMEM);

	if (percpu_ref_init(&p->users, swap_users_ref_free,
	p->sei = kvzalloc(sizeof(struct swap_extend_info), GFP_KERNEL);
	if (!p->sei) {
		kvfree(p);
		return ERR_PTR(-ENOMEM);
	}

	if (percpu_ref_init(&p->sei->users, swap_users_ref_free,
			    PERCPU_REF_INIT_DEAD, GFP_KERNEL)) {
		kvfree(p->sei);
		kvfree(p);
		return ERR_PTR(-ENOMEM);
	}
@@ -2912,7 +2919,8 @@ static struct swap_info_struct *alloc_swap_info(void)
	}
	if (type >= MAX_SWAPFILES) {
		spin_unlock(&swap_lock);
		percpu_ref_exit(&p->users);
		percpu_ref_exit(&p->sei->users);
		kvfree(p->sei);
		kvfree(p);
		return ERR_PTR(-EPERM);
	}
@@ -2941,12 +2949,13 @@ static struct swap_info_struct *alloc_swap_info(void)
	p->flags = SWP_USED;
	spin_unlock(&swap_lock);
	if (defer) {
		percpu_ref_exit(&defer->users);
		percpu_ref_exit(&defer->sei->users);
		kvfree(defer->sei);
		kvfree(defer);
	}
	spin_lock_init(&p->lock);
	spin_lock_init(&p->cont_lock);
	init_completion(&p->comp);
	init_completion(&p->sei->comp);

	return p;
}