Commit ee4dd6d5 authored by Junxian Huang's avatar Junxian Huang Committed by Xinghai Cen
Browse files

RDMA/hns: Fix delayed destruction of db not taking effect

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBQK42



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

Driver allocates and frees db in a unit of page. One db page will be
shared by multiple dbs. Currently the delayed destruiction of db only
depends on the delayed_unmap_flag of the db itself. It means if this
flag of the last db in a page is not set, this page will still be
freed, and the delayed-destruction mechanism won't take effect despite
the flag of some previous dbs may be set.

A db page is associated with a umem_node. Add a flag to umem_node
to indicate whether this page should be delayed-destroyed.

Fixes: 431c875e ("RDMA/hns: Fix simultaneous reset and resource deregistration")
Signed-off-by: default avatarJunxian Huang <huangjunxian6@hisilicon.com>
Signed-off-by: default avatarXinghai Cen <cenxinghai@h-partners.com>
parent 33a7922b
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -67,17 +67,20 @@ void hns_roce_db_unmap_user(struct hns_roce_ucontext *context,
			    bool delayed_unmap_flag)
			    bool delayed_unmap_flag)
{
{
	struct hns_roce_dev *hr_dev = to_hr_dev(context->ibucontext.device);
	struct hns_roce_dev *hr_dev = to_hr_dev(context->ibucontext.device);
	struct hns_roce_umem_node *umem_node = db->u.user_page->umem_node;


	mutex_lock(&context->page_mutex);
	mutex_lock(&context->page_mutex);


	umem_node->delayed_unmap_flag |= delayed_unmap_flag;

	refcount_dec(&db->u.user_page->refcount);
	refcount_dec(&db->u.user_page->refcount);
	if (refcount_dec_if_one(&db->u.user_page->refcount)) {
	if (refcount_dec_if_one(&db->u.user_page->refcount)) {
		list_del(&db->u.user_page->list);
		list_del(&db->u.user_page->list);
		if (delayed_unmap_flag) {
		if (umem_node->delayed_unmap_flag) {
			hns_roce_add_unfree_umem(db->u.user_page, hr_dev);
			hns_roce_add_unfree_umem(db->u.user_page, hr_dev);
		} else {
		} else {
			ib_umem_release(db->u.user_page->umem);
			ib_umem_release(db->u.user_page->umem);
			kvfree(db->u.user_page->umem_node);
			kvfree(umem_node);
		}
		}
		kfree(db->u.user_page);
		kfree(db->u.user_page);
	}
	}
+1 −0
Original line number Original line Diff line number Diff line
@@ -500,6 +500,7 @@ struct hns_roce_db_pgdir {
struct hns_roce_umem_node {
struct hns_roce_umem_node {
	struct ib_umem *umem;
	struct ib_umem *umem;
	struct list_head list;
	struct list_head list;
	bool delayed_unmap_flag;
};
};


struct hns_roce_user_db_page {
struct hns_roce_user_db_page {