RDMA/addr: Use client registration to fix module unload race

Require registration with ib_addr module to prevent caller from
unloading while a callback is in progress.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>

authored by Sean Hefty and committed by Roland Dreier 7a118df3 68586b67

+52 -4
+27 -1
drivers/infiniband/core/addr.c
··· 47 47 struct sockaddr src_addr; 48 48 struct sockaddr dst_addr; 49 49 struct rdma_dev_addr *addr; 50 + struct rdma_addr_client *client; 50 51 void *context; 51 52 void (*callback)(int status, struct sockaddr *src_addr, 52 53 struct rdma_dev_addr *addr, void *context); ··· 61 60 static LIST_HEAD(req_list); 62 61 static DECLARE_WORK(work, process_req, NULL); 63 62 static struct workqueue_struct *addr_wq; 63 + 64 + void rdma_addr_register_client(struct rdma_addr_client *client) 65 + { 66 + atomic_set(&client->refcount, 1); 67 + init_completion(&client->comp); 68 + } 69 + EXPORT_SYMBOL(rdma_addr_register_client); 70 + 71 + static inline void put_client(struct rdma_addr_client *client) 72 + { 73 + if (atomic_dec_and_test(&client->refcount)) 74 + complete(&client->comp); 75 + } 76 + 77 + void rdma_addr_unregister_client(struct rdma_addr_client *client) 78 + { 79 + put_client(client); 80 + wait_for_completion(&client->comp); 81 + } 82 + EXPORT_SYMBOL(rdma_addr_unregister_client); 64 83 65 84 int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, 66 85 const unsigned char *dst_dev_addr) ··· 250 229 list_del(&req->list); 251 230 req->callback(req->status, &req->src_addr, req->addr, 252 231 req->context); 232 + put_client(req->client); 253 233 kfree(req); 254 234 } 255 235 } ··· 286 264 return ret; 287 265 } 288 266 289 - int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, 267 + int rdma_resolve_ip(struct rdma_addr_client *client, 268 + struct sockaddr *src_addr, struct sockaddr *dst_addr, 290 269 struct rdma_dev_addr *addr, int timeout_ms, 291 270 void (*callback)(int status, struct sockaddr *src_addr, 292 271 struct rdma_dev_addr *addr, void *context), ··· 308 285 req->addr = addr; 309 286 req->callback = callback; 310 287 req->context = context; 288 + req->client = client; 289 + atomic_inc(&client->refcount); 311 290 312 291 src_in = (struct sockaddr_in *) &req->src_addr; 313 292 dst_in = (struct sockaddr_in *) &req->dst_addr; ··· 330 305 break; 331 306 default: 332 307 ret = req->status; 308 + atomic_dec(&client->refcount); 333 309 kfree(req); 334 310 break; 335 311 }
+6 -2
drivers/infiniband/core/cma.c
··· 63 63 }; 64 64 65 65 static struct ib_sa_client sa_client; 66 + static struct rdma_addr_client addr_client; 66 67 static LIST_HEAD(dev_list); 67 68 static LIST_HEAD(listen_any_list); 68 69 static DEFINE_MUTEX(lock); ··· 1626 1625 if (cma_any_addr(dst_addr)) 1627 1626 ret = cma_resolve_loopback(id_priv); 1628 1627 else 1629 - ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr, 1630 - &id->route.addr.dev_addr, 1628 + ret = rdma_resolve_ip(&addr_client, &id->route.addr.src_addr, 1629 + dst_addr, &id->route.addr.dev_addr, 1631 1630 timeout_ms, addr_handler, id_priv); 1632 1631 if (ret) 1633 1632 goto err; ··· 2218 2217 return -ENOMEM; 2219 2218 2220 2219 ib_sa_register_client(&sa_client); 2220 + rdma_addr_register_client(&addr_client); 2221 2221 2222 2222 ret = ib_register_client(&cma_client); 2223 2223 if (ret) ··· 2226 2224 return 0; 2227 2225 2228 2226 err: 2227 + rdma_addr_unregister_client(&addr_client); 2229 2228 ib_sa_unregister_client(&sa_client); 2230 2229 destroy_workqueue(cma_wq); 2231 2230 return ret; ··· 2235 2232 static void cma_cleanup(void) 2236 2233 { 2237 2234 ib_unregister_client(&cma_client); 2235 + rdma_addr_unregister_client(&addr_client); 2238 2236 ib_sa_unregister_client(&sa_client); 2239 2237 destroy_workqueue(cma_wq); 2240 2238 idr_destroy(&sdp_ps);
+19 -1
include/rdma/ib_addr.h
··· 36 36 #include <linux/socket.h> 37 37 #include <rdma/ib_verbs.h> 38 38 39 + struct rdma_addr_client { 40 + atomic_t refcount; 41 + struct completion comp; 42 + }; 43 + 44 + /** 45 + * rdma_addr_register_client - Register an address client. 46 + */ 47 + void rdma_addr_register_client(struct rdma_addr_client *client); 48 + 49 + /** 50 + * rdma_addr_unregister_client - Deregister an address client. 51 + * @client: Client object to deregister. 52 + */ 53 + void rdma_addr_unregister_client(struct rdma_addr_client *client); 54 + 39 55 struct rdma_dev_addr { 40 56 unsigned char src_dev_addr[MAX_ADDR_LEN]; 41 57 unsigned char dst_dev_addr[MAX_ADDR_LEN]; ··· 68 52 /** 69 53 * rdma_resolve_ip - Resolve source and destination IP addresses to 70 54 * RDMA hardware addresses. 55 + * @client: Address client associated with request. 71 56 * @src_addr: An optional source address to use in the resolution. If a 72 57 * source address is not provided, a usable address will be returned via 73 58 * the callback. ··· 81 64 * or been canceled. A status of 0 indicates success. 82 65 * @context: User-specified context associated with the call. 83 66 */ 84 - int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, 67 + int rdma_resolve_ip(struct rdma_addr_client *client, 68 + struct sockaddr *src_addr, struct sockaddr *dst_addr, 85 69 struct rdma_dev_addr *addr, int timeout_ms, 86 70 void (*callback)(int status, struct sockaddr *src_addr, 87 71 struct rdma_dev_addr *addr, void *context),