1 /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ 2 /* 3 * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved. 4 */ 5 6 #include <rdma/rdma_cm.h> 7 #include <rdma/ib_verbs.h> 8 #include <rdma/restrack.h> 9 #include <linux/mutex.h> 10 #include <linux/sched/task.h> 11 #include <linux/pid_namespace.h> 12 13 #include "cma_priv.h" 14 15 void rdma_restrack_init(struct rdma_restrack_root *res) 16 { 17 init_rwsem(&res->rwsem); 18 } 19 20 static const char *type2str(enum rdma_restrack_type type) 21 { 22 static const char * const names[RDMA_RESTRACK_MAX] = { 23 [RDMA_RESTRACK_PD] = "PD", 24 [RDMA_RESTRACK_CQ] = "CQ", 25 [RDMA_RESTRACK_QP] = "QP", 26 [RDMA_RESTRACK_CM_ID] = "CM_ID", 27 [RDMA_RESTRACK_MR] = "MR", 28 }; 29 30 return names[type]; 31 }; 32 33 void rdma_restrack_clean(struct rdma_restrack_root *res) 34 { 35 struct rdma_restrack_entry *e; 36 char buf[TASK_COMM_LEN]; 37 struct ib_device *dev; 38 const char *owner; 39 int bkt; 40 41 if (hash_empty(res->hash)) 42 return; 43 44 dev = container_of(res, struct ib_device, res); 45 pr_err("restrack: %s", CUT_HERE); 46 pr_err("restrack: BUG: RESTRACK detected leak of resources on %s\n", 47 dev->name); 48 hash_for_each(res->hash, bkt, e, node) { 49 if (rdma_is_kernel_res(e)) { 50 owner = e->kern_name; 51 } else { 52 /* 53 * There is no need to call get_task_struct here, 54 * because we can be here only if there are more 55 * get_task_struct() call than put_task_struct(). 56 */ 57 get_task_comm(buf, e->task); 58 owner = buf; 59 } 60 61 pr_err("restrack: %s %s object allocated by %s is not freed\n", 62 rdma_is_kernel_res(e) ? "Kernel" : "User", 63 type2str(e->type), owner); 64 } 65 pr_err("restrack: %s", CUT_HERE); 66 } 67 68 int rdma_restrack_count(struct rdma_restrack_root *res, 69 enum rdma_restrack_type type, 70 struct pid_namespace *ns) 71 { 72 struct rdma_restrack_entry *e; 73 u32 cnt = 0; 74 75 down_read(&res->rwsem); 76 hash_for_each_possible(res->hash, e, node, type) { 77 if (ns == &init_pid_ns || 78 (!rdma_is_kernel_res(e) && 79 ns == task_active_pid_ns(e->task))) 80 cnt++; 81 } 82 up_read(&res->rwsem); 83 return cnt; 84 } 85 EXPORT_SYMBOL(rdma_restrack_count); 86 87 static void set_kern_name(struct rdma_restrack_entry *res) 88 { 89 struct ib_pd *pd; 90 91 switch (res->type) { 92 case RDMA_RESTRACK_QP: 93 pd = container_of(res, struct ib_qp, res)->pd; 94 if (!pd) { 95 WARN_ONCE(true, "XRC QPs are not supported\n"); 96 /* Survive, despite the programmer's error */ 97 res->kern_name = " "; 98 } 99 break; 100 case RDMA_RESTRACK_MR: 101 pd = container_of(res, struct ib_mr, res)->pd; 102 break; 103 default: 104 /* Other types set kern_name directly */ 105 pd = NULL; 106 break; 107 } 108 109 if (pd) 110 res->kern_name = pd->res.kern_name; 111 } 112 113 static struct ib_device *res_to_dev(struct rdma_restrack_entry *res) 114 { 115 switch (res->type) { 116 case RDMA_RESTRACK_PD: 117 return container_of(res, struct ib_pd, res)->device; 118 case RDMA_RESTRACK_CQ: 119 return container_of(res, struct ib_cq, res)->device; 120 case RDMA_RESTRACK_QP: 121 return container_of(res, struct ib_qp, res)->device; 122 case RDMA_RESTRACK_CM_ID: 123 return container_of(res, struct rdma_id_private, 124 res)->id.device; 125 case RDMA_RESTRACK_MR: 126 return container_of(res, struct ib_mr, res)->device; 127 default: 128 WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type); 129 return NULL; 130 } 131 } 132 133 static bool res_is_user(struct rdma_restrack_entry *res) 134 { 135 switch (res->type) { 136 case RDMA_RESTRACK_PD: 137 return container_of(res, struct ib_pd, res)->uobject; 138 case RDMA_RESTRACK_CQ: 139 return container_of(res, struct ib_cq, res)->uobject; 140 case RDMA_RESTRACK_QP: 141 return container_of(res, struct ib_qp, res)->uobject; 142 case RDMA_RESTRACK_CM_ID: 143 return !res->kern_name; 144 case RDMA_RESTRACK_MR: 145 return container_of(res, struct ib_mr, res)->pd->uobject; 146 default: 147 WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type); 148 return false; 149 } 150 } 151 152 void rdma_restrack_add(struct rdma_restrack_entry *res) 153 { 154 struct ib_device *dev = res_to_dev(res); 155 156 if (!dev) 157 return; 158 159 if (res->type != RDMA_RESTRACK_CM_ID || !res_is_user(res)) 160 res->task = NULL; 161 162 if (res_is_user(res)) { 163 if (!res->task) 164 rdma_restrack_set_task(res, current); 165 res->kern_name = NULL; 166 } else { 167 set_kern_name(res); 168 } 169 170 kref_init(&res->kref); 171 init_completion(&res->comp); 172 res->valid = true; 173 174 down_write(&dev->res.rwsem); 175 hash_add(dev->res.hash, &res->node, res->type); 176 up_write(&dev->res.rwsem); 177 } 178 EXPORT_SYMBOL(rdma_restrack_add); 179 180 int __must_check rdma_restrack_get(struct rdma_restrack_entry *res) 181 { 182 return kref_get_unless_zero(&res->kref); 183 } 184 EXPORT_SYMBOL(rdma_restrack_get); 185 186 static void restrack_release(struct kref *kref) 187 { 188 struct rdma_restrack_entry *res; 189 190 res = container_of(kref, struct rdma_restrack_entry, kref); 191 complete(&res->comp); 192 } 193 194 int rdma_restrack_put(struct rdma_restrack_entry *res) 195 { 196 return kref_put(&res->kref, restrack_release); 197 } 198 EXPORT_SYMBOL(rdma_restrack_put); 199 200 void rdma_restrack_del(struct rdma_restrack_entry *res) 201 { 202 struct ib_device *dev; 203 204 if (!res->valid) 205 return; 206 207 dev = res_to_dev(res); 208 if (!dev) 209 return; 210 211 rdma_restrack_put(res); 212 213 wait_for_completion(&res->comp); 214 215 down_write(&dev->res.rwsem); 216 hash_del(&res->node); 217 res->valid = false; 218 if (res->task) 219 put_task_struct(res->task); 220 up_write(&dev->res.rwsem); 221 } 222 EXPORT_SYMBOL(rdma_restrack_del); 223