Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
0002 /*
0003  * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
0004  */
0005 
0006 #include <rdma/rdma_cm.h>
0007 #include <rdma/ib_verbs.h>
0008 #include <rdma/restrack.h>
0009 #include <rdma/rdma_counter.h>
0010 #include <linux/mutex.h>
0011 #include <linux/sched/task.h>
0012 #include <linux/pid_namespace.h>
0013 
0014 #include "cma_priv.h"
0015 #include "restrack.h"
0016 
0017 /**
0018  * rdma_restrack_init() - initialize and allocate resource tracking
0019  * @dev:  IB device
0020  *
0021  * Return: 0 on success
0022  */
0023 int rdma_restrack_init(struct ib_device *dev)
0024 {
0025     struct rdma_restrack_root *rt;
0026     int i;
0027 
0028     dev->res = kcalloc(RDMA_RESTRACK_MAX, sizeof(*rt), GFP_KERNEL);
0029     if (!dev->res)
0030         return -ENOMEM;
0031 
0032     rt = dev->res;
0033 
0034     for (i = 0; i < RDMA_RESTRACK_MAX; i++)
0035         xa_init_flags(&rt[i].xa, XA_FLAGS_ALLOC);
0036 
0037     return 0;
0038 }
0039 
0040 static const char *type2str(enum rdma_restrack_type type)
0041 {
0042     static const char * const names[RDMA_RESTRACK_MAX] = {
0043         [RDMA_RESTRACK_PD] = "PD",
0044         [RDMA_RESTRACK_CQ] = "CQ",
0045         [RDMA_RESTRACK_QP] = "QP",
0046         [RDMA_RESTRACK_CM_ID] = "CM_ID",
0047         [RDMA_RESTRACK_MR] = "MR",
0048         [RDMA_RESTRACK_CTX] = "CTX",
0049         [RDMA_RESTRACK_COUNTER] = "COUNTER",
0050         [RDMA_RESTRACK_SRQ] = "SRQ",
0051     };
0052 
0053     return names[type];
0054 };
0055 
0056 /**
0057  * rdma_restrack_clean() - clean resource tracking
0058  * @dev:  IB device
0059  */
0060 void rdma_restrack_clean(struct ib_device *dev)
0061 {
0062     struct rdma_restrack_root *rt = dev->res;
0063     struct rdma_restrack_entry *e;
0064     char buf[TASK_COMM_LEN];
0065     bool found = false;
0066     const char *owner;
0067     int i;
0068 
0069     for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) {
0070         struct xarray *xa = &dev->res[i].xa;
0071 
0072         if (!xa_empty(xa)) {
0073             unsigned long index;
0074 
0075             if (!found) {
0076                 pr_err("restrack: %s", CUT_HERE);
0077                 dev_err(&dev->dev, "BUG: RESTRACK detected leak of resources\n");
0078             }
0079             xa_for_each(xa, index, e) {
0080                 if (rdma_is_kernel_res(e)) {
0081                     owner = e->kern_name;
0082                 } else {
0083                     /*
0084                      * There is no need to call get_task_struct here,
0085                      * because we can be here only if there are more
0086                      * get_task_struct() call than put_task_struct().
0087                      */
0088                     get_task_comm(buf, e->task);
0089                     owner = buf;
0090                 }
0091 
0092                 pr_err("restrack: %s %s object allocated by %s is not freed\n",
0093                        rdma_is_kernel_res(e) ? "Kernel" :
0094                                    "User",
0095                        type2str(e->type), owner);
0096             }
0097             found = true;
0098         }
0099         xa_destroy(xa);
0100     }
0101     if (found)
0102         pr_err("restrack: %s", CUT_HERE);
0103 
0104     kfree(rt);
0105 }
0106 
0107 /**
0108  * rdma_restrack_count() - the current usage of specific object
0109  * @dev:  IB device
0110  * @type: actual type of object to operate
0111  */
0112 int rdma_restrack_count(struct ib_device *dev, enum rdma_restrack_type type)
0113 {
0114     struct rdma_restrack_root *rt = &dev->res[type];
0115     struct rdma_restrack_entry *e;
0116     XA_STATE(xas, &rt->xa, 0);
0117     u32 cnt = 0;
0118 
0119     xa_lock(&rt->xa);
0120     xas_for_each(&xas, e, U32_MAX)
0121         cnt++;
0122     xa_unlock(&rt->xa);
0123     return cnt;
0124 }
0125 EXPORT_SYMBOL(rdma_restrack_count);
0126 
0127 static struct ib_device *res_to_dev(struct rdma_restrack_entry *res)
0128 {
0129     switch (res->type) {
0130     case RDMA_RESTRACK_PD:
0131         return container_of(res, struct ib_pd, res)->device;
0132     case RDMA_RESTRACK_CQ:
0133         return container_of(res, struct ib_cq, res)->device;
0134     case RDMA_RESTRACK_QP:
0135         return container_of(res, struct ib_qp, res)->device;
0136     case RDMA_RESTRACK_CM_ID:
0137         return container_of(res, struct rdma_id_private,
0138                     res)->id.device;
0139     case RDMA_RESTRACK_MR:
0140         return container_of(res, struct ib_mr, res)->device;
0141     case RDMA_RESTRACK_CTX:
0142         return container_of(res, struct ib_ucontext, res)->device;
0143     case RDMA_RESTRACK_COUNTER:
0144         return container_of(res, struct rdma_counter, res)->device;
0145     case RDMA_RESTRACK_SRQ:
0146         return container_of(res, struct ib_srq, res)->device;
0147     default:
0148         WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
0149         return NULL;
0150     }
0151 }
0152 
0153 /**
0154  * rdma_restrack_attach_task() - attach the task onto this resource,
0155  * valid for user space restrack entries.
0156  * @res:  resource entry
0157  * @task: the task to attach
0158  */
0159 static void rdma_restrack_attach_task(struct rdma_restrack_entry *res,
0160                       struct task_struct *task)
0161 {
0162     if (WARN_ON_ONCE(!task))
0163         return;
0164 
0165     if (res->task)
0166         put_task_struct(res->task);
0167     get_task_struct(task);
0168     res->task = task;
0169     res->user = true;
0170 }
0171 
0172 /**
0173  * rdma_restrack_set_name() - set the task for this resource
0174  * @res:  resource entry
0175  * @caller: kernel name, the current task will be used if the caller is NULL.
0176  */
0177 void rdma_restrack_set_name(struct rdma_restrack_entry *res, const char *caller)
0178 {
0179     if (caller) {
0180         res->kern_name = caller;
0181         return;
0182     }
0183 
0184     rdma_restrack_attach_task(res, current);
0185 }
0186 EXPORT_SYMBOL(rdma_restrack_set_name);
0187 
0188 /**
0189  * rdma_restrack_parent_name() - set the restrack name properties based
0190  * on parent restrack
0191  * @dst: destination resource entry
0192  * @parent: parent resource entry
0193  */
0194 void rdma_restrack_parent_name(struct rdma_restrack_entry *dst,
0195                    const struct rdma_restrack_entry *parent)
0196 {
0197     if (rdma_is_kernel_res(parent))
0198         dst->kern_name = parent->kern_name;
0199     else
0200         rdma_restrack_attach_task(dst, parent->task);
0201 }
0202 EXPORT_SYMBOL(rdma_restrack_parent_name);
0203 
0204 /**
0205  * rdma_restrack_new() - Initializes new restrack entry to allow _put() interface
0206  * to release memory in fully automatic way.
0207  * @res: Entry to initialize
0208  * @type: REstrack type
0209  */
0210 void rdma_restrack_new(struct rdma_restrack_entry *res,
0211                enum rdma_restrack_type type)
0212 {
0213     kref_init(&res->kref);
0214     init_completion(&res->comp);
0215     res->type = type;
0216 }
0217 EXPORT_SYMBOL(rdma_restrack_new);
0218 
0219 /**
0220  * rdma_restrack_add() - add object to the reource tracking database
0221  * @res:  resource entry
0222  */
0223 void rdma_restrack_add(struct rdma_restrack_entry *res)
0224 {
0225     struct ib_device *dev = res_to_dev(res);
0226     struct rdma_restrack_root *rt;
0227     int ret = 0;
0228 
0229     if (!dev)
0230         return;
0231 
0232     if (res->no_track)
0233         goto out;
0234 
0235     rt = &dev->res[res->type];
0236 
0237     if (res->type == RDMA_RESTRACK_QP) {
0238         /* Special case to ensure that LQPN points to right QP */
0239         struct ib_qp *qp = container_of(res, struct ib_qp, res);
0240 
0241         WARN_ONCE(qp->qp_num >> 24 || qp->port >> 8,
0242               "QP number 0x%0X and port 0x%0X", qp->qp_num,
0243               qp->port);
0244         res->id = qp->qp_num;
0245         if (qp->qp_type == IB_QPT_SMI || qp->qp_type == IB_QPT_GSI)
0246             res->id |= qp->port << 24;
0247         ret = xa_insert(&rt->xa, res->id, res, GFP_KERNEL);
0248         if (ret)
0249             res->id = 0;
0250     } else if (res->type == RDMA_RESTRACK_COUNTER) {
0251         /* Special case to ensure that cntn points to right counter */
0252         struct rdma_counter *counter;
0253 
0254         counter = container_of(res, struct rdma_counter, res);
0255         ret = xa_insert(&rt->xa, counter->id, res, GFP_KERNEL);
0256         res->id = ret ? 0 : counter->id;
0257     } else {
0258         ret = xa_alloc_cyclic(&rt->xa, &res->id, res, xa_limit_32b,
0259                       &rt->next_id, GFP_KERNEL);
0260         ret = (ret < 0) ? ret : 0;
0261     }
0262 
0263 out:
0264     if (!ret)
0265         res->valid = true;
0266 }
0267 EXPORT_SYMBOL(rdma_restrack_add);
0268 
0269 int __must_check rdma_restrack_get(struct rdma_restrack_entry *res)
0270 {
0271     return kref_get_unless_zero(&res->kref);
0272 }
0273 EXPORT_SYMBOL(rdma_restrack_get);
0274 
0275 /**
0276  * rdma_restrack_get_byid() - translate from ID to restrack object
0277  * @dev: IB device
0278  * @type: resource track type
0279  * @id: ID to take a look
0280  *
0281  * Return: Pointer to restrack entry or -ENOENT in case of error.
0282  */
0283 struct rdma_restrack_entry *
0284 rdma_restrack_get_byid(struct ib_device *dev,
0285                enum rdma_restrack_type type, u32 id)
0286 {
0287     struct rdma_restrack_root *rt = &dev->res[type];
0288     struct rdma_restrack_entry *res;
0289 
0290     xa_lock(&rt->xa);
0291     res = xa_load(&rt->xa, id);
0292     if (!res || !rdma_restrack_get(res))
0293         res = ERR_PTR(-ENOENT);
0294     xa_unlock(&rt->xa);
0295 
0296     return res;
0297 }
0298 EXPORT_SYMBOL(rdma_restrack_get_byid);
0299 
0300 static void restrack_release(struct kref *kref)
0301 {
0302     struct rdma_restrack_entry *res;
0303 
0304     res = container_of(kref, struct rdma_restrack_entry, kref);
0305     if (res->task) {
0306         put_task_struct(res->task);
0307         res->task = NULL;
0308     }
0309     complete(&res->comp);
0310 }
0311 
0312 int rdma_restrack_put(struct rdma_restrack_entry *res)
0313 {
0314     return kref_put(&res->kref, restrack_release);
0315 }
0316 EXPORT_SYMBOL(rdma_restrack_put);
0317 
0318 /**
0319  * rdma_restrack_del() - delete object from the reource tracking database
0320  * @res:  resource entry
0321  */
0322 void rdma_restrack_del(struct rdma_restrack_entry *res)
0323 {
0324     struct rdma_restrack_entry *old;
0325     struct rdma_restrack_root *rt;
0326     struct ib_device *dev;
0327 
0328     if (!res->valid) {
0329         if (res->task) {
0330             put_task_struct(res->task);
0331             res->task = NULL;
0332         }
0333         return;
0334     }
0335 
0336     if (res->no_track)
0337         goto out;
0338 
0339     dev = res_to_dev(res);
0340     if (WARN_ON(!dev))
0341         return;
0342 
0343     rt = &dev->res[res->type];
0344 
0345     old = xa_erase(&rt->xa, res->id);
0346     if (res->type == RDMA_RESTRACK_MR)
0347         return;
0348     WARN_ON(old != res);
0349 
0350 out:
0351     res->valid = false;
0352     rdma_restrack_put(res);
0353     wait_for_completion(&res->comp);
0354 }
0355 EXPORT_SYMBOL(rdma_restrack_del);