提交 68dfec3b 编写于 作者: C Chen Wandun 提交者: Zheng Zengkai

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: NChen Wandun <chenwandun@huawei.com>
Reviewed-by: Nzhangjialin <zhangjialin11@huawei.com>
Reviewed-by: NKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 5d934d94
...@@ -246,6 +246,11 @@ struct swap_cluster_list { ...@@ -246,6 +246,11 @@ struct swap_cluster_list {
struct swap_cluster_info tail; 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. * The in-memory structure used to track swap areas.
*/ */
...@@ -293,10 +298,8 @@ struct swap_info_struct { ...@@ -293,10 +298,8 @@ struct swap_info_struct {
*/ */
struct work_struct discard_work; /* discard worker */ struct work_struct discard_work; /* discard worker */
struct swap_cluster_list discard_clusters; /* discard clusters list */ struct swap_cluster_list discard_clusters; /* discard clusters list */
KABI_RESERVE(1) KABI_USE(1, struct swap_extend_info *sei)
KABI_RESERVE(2) 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[]; /* struct plist_node avail_lists[]; /*
* entries in swap_avail_heads, one * entries in swap_avail_heads, one
* entry per node. * entry per node.
...@@ -537,7 +540,7 @@ sector_t swap_page_sector(struct page *page); ...@@ -537,7 +540,7 @@ sector_t swap_page_sector(struct page *page);
static inline void put_swap_device(struct swap_info_struct *si) 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 */ #else /* CONFIG_SWAP */
......
...@@ -515,10 +515,10 @@ static void swap_discard_work(struct work_struct *work) ...@@ -515,10 +515,10 @@ static void swap_discard_work(struct work_struct *work)
static void swap_users_ref_free(struct percpu_ref *ref) 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); sei = container_of(ref, struct swap_extend_info, users);
complete(&si->comp); complete(&sei->comp);
} }
static void alloc_cluster(struct swap_info_struct *si, unsigned long idx) 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) ...@@ -1316,7 +1316,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry)
si = swp_swap_info(entry); si = swp_swap_info(entry);
if (!si) if (!si)
goto bad_nofile; goto bad_nofile;
if (!percpu_ref_tryget_live(&si->users)) if (!percpu_ref_tryget_live(&si->sei->users))
goto out; goto out;
/* /*
* Guarantee the si->users are checked before accessing other * Guarantee the si->users are checked before accessing other
...@@ -1336,7 +1336,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry) ...@@ -1336,7 +1336,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry)
out: out:
return NULL; return NULL;
put_out: put_out:
percpu_ref_put(&si->users); percpu_ref_put(&si->sei->users);
return NULL; return NULL;
} }
...@@ -2542,7 +2542,7 @@ static void enable_swap_info(struct swap_info_struct *p, int prio, ...@@ -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. * 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(&swap_lock);
spin_lock(&p->lock); spin_lock(&p->lock);
_enable_swap_info(p); _enable_swap_info(p);
...@@ -2665,9 +2665,9 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) ...@@ -2665,9 +2665,9 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
* We need synchronize_rcu() here to protect the accessing to * We need synchronize_rcu() here to protect the accessing to
* the swap cache data structure. * the swap cache data structure.
*/ */
percpu_ref_kill(&p->users); percpu_ref_kill(&p->sei->users);
synchronize_rcu(); synchronize_rcu();
wait_for_completion(&p->comp); wait_for_completion(&p->sei->comp);
flush_work(&p->discard_work); flush_work(&p->discard_work);
...@@ -2899,8 +2899,15 @@ static struct swap_info_struct *alloc_swap_info(void) ...@@ -2899,8 +2899,15 @@ static struct swap_info_struct *alloc_swap_info(void)
if (!p) if (!p)
return ERR_PTR(-ENOMEM); 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)) { PERCPU_REF_INIT_DEAD, GFP_KERNEL)) {
kvfree(p->sei);
kvfree(p); kvfree(p);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
...@@ -2912,7 +2919,8 @@ static struct swap_info_struct *alloc_swap_info(void) ...@@ -2912,7 +2919,8 @@ static struct swap_info_struct *alloc_swap_info(void)
} }
if (type >= MAX_SWAPFILES) { if (type >= MAX_SWAPFILES) {
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
percpu_ref_exit(&p->users); percpu_ref_exit(&p->sei->users);
kvfree(p->sei);
kvfree(p); kvfree(p);
return ERR_PTR(-EPERM); return ERR_PTR(-EPERM);
} }
...@@ -2941,12 +2949,13 @@ static struct swap_info_struct *alloc_swap_info(void) ...@@ -2941,12 +2949,13 @@ static struct swap_info_struct *alloc_swap_info(void)
p->flags = SWP_USED; p->flags = SWP_USED;
spin_unlock(&swap_lock); spin_unlock(&swap_lock);
if (defer) { if (defer) {
percpu_ref_exit(&defer->users); percpu_ref_exit(&defer->sei->users);
kvfree(defer->sei);
kvfree(defer); kvfree(defer);
} }
spin_lock_init(&p->lock); spin_lock_init(&p->lock);
spin_lock_init(&p->cont_lock); spin_lock_init(&p->cont_lock);
init_completion(&p->comp); init_completion(&p->sei->comp);
return p; return p;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册