3346 lines · 89.9 KB · C
RawDownload
/* * Copyright (c) 2004 Topspin Communications.  All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses.  You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * *     Redistribution and use in source and binary forms, with or *     without modification, are permitted provided that the following *     conditions are met: * *      - Redistributions of source code must retain the above *        copyright notice, this list of conditions and the following *        disclaimer. * *      - Redistributions in binary form must reproduce the above *        copyright notice, this list of conditions and the following *        disclaimer in the documentation and/or other materials *        provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include <linux/module.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/netdevice.h>#include <net/net_namespace.h>#include <linux/security.h>#include <linux/notifier.h>#include <linux/hashtable.h>#include <linux/cc_platform.h>#include <rdma/rdma_netlink.h>#include <rdma/ib_addr.h>#include <rdma/ib_cache.h>#include <rdma/rdma_counter.h> #include "core_priv.h"#include "restrack.h" MODULE_AUTHOR("Roland Dreier");MODULE_DESCRIPTION("core kernel InfiniBand API");MODULE_LICENSE("Dual BSD/GPL"); struct workqueue_struct *ib_comp_wq;struct workqueue_struct *ib_comp_unbound_wq;struct workqueue_struct *ib_wq;EXPORT_SYMBOL_GPL(ib_wq);static struct workqueue_struct *ib_unreg_wq; /* * Each of the three rwsem locks (devices, clients, client_data) protects the * xarray of the same name. Specifically it allows the caller to assert that * the MARK will/will not be changing under the lock, and for devices and * clients, that the value in the xarray is still a valid pointer. Change of * the MARK is linked to the object state, so holding the lock and testing the * MARK also asserts that the contained object is in a certain state. * * This is used to build a two stage register/unregister flow where objects * can continue to be in the xarray even though they are still in progress to * register/unregister. * * The xarray itself provides additional locking, and restartable iteration, * which is also relied on. * * Locks should not be nested, with the exception of client_data, which is * allowed to nest under the read side of the other two locks. * * The devices_rwsem also protects the device name list, any change or * assignment of device name must also hold the write side to guarantee unique * names. */ /* * devices contains devices that have had their names assigned. The * devices may not be registered. Users that care about the registration * status need to call ib_device_try_get() on the device to ensure it is * registered, and keep it registered, for the required duration. * */static DEFINE_XARRAY_FLAGS(devices, XA_FLAGS_ALLOC);static DECLARE_RWSEM(devices_rwsem);#define DEVICE_REGISTERED XA_MARK_1#define DEVICE_GID_UPDATES XA_MARK_2 static u32 highest_client_id;#define CLIENT_REGISTERED XA_MARK_1static DEFINE_XARRAY_FLAGS(clients, XA_FLAGS_ALLOC);static DECLARE_RWSEM(clients_rwsem); static void ib_client_put(struct ib_client *client){	if (refcount_dec_and_test(&client->uses))		complete(&client->uses_zero);} /* * If client_data is registered then the corresponding client must also still * be registered. */#define CLIENT_DATA_REGISTERED XA_MARK_1 unsigned int rdma_dev_net_id; /* * A list of net namespaces is maintained in an xarray. This is necessary * because we can't get the locking right using the existing net ns list. We * would require a init_net callback after the list is updated. */static DEFINE_XARRAY_FLAGS(rdma_nets, XA_FLAGS_ALLOC);/* * rwsem to protect accessing the rdma_nets xarray entries. */static DECLARE_RWSEM(rdma_nets_rwsem); bool ib_devices_shared_netns = true;module_param_named(netns_mode, ib_devices_shared_netns, bool, 0444);MODULE_PARM_DESC(netns_mode,		 "Share device among net namespaces; default=1 (shared). In exclusive mode device names are unique per net namespace");/** * rdma_dev_access_netns() - Return whether an rdma device can be accessed *			     from a specified net namespace or not. * @dev:	Pointer to rdma device which needs to be checked * @net:	Pointer to net namesapce for which access to be checked * * When the rdma device is in shared mode, it ignores the net namespace. * When the rdma device is exclusive to a net namespace, rdma device net * namespace is checked against the specified one. */bool rdma_dev_access_netns(const struct ib_device *dev, const struct net *net){	return (ib_devices_shared_netns ||		net_eq(read_pnet(&dev->coredev.rdma_net), net));}EXPORT_SYMBOL(rdma_dev_access_netns); /** * rdma_dev_has_raw_cap() - Returns whether a specified rdma device has *			    CAP_NET_RAW capability or not. * * @dev:	Pointer to rdma device whose capability to be checked * * Returns true if a rdma device's owning user namespace has CAP_NET_RAW * capability, otherwise false. When rdma subsystem is in legacy shared network, * namespace mode, the default net namespace is considered. */bool rdma_dev_has_raw_cap(const struct ib_device *dev){	const struct net *net; 	/* Network namespace is the resource whose user namespace	 * to be considered. When in shared mode, there is no reliable	 * network namespace resource, so consider the default net namespace.	 */	if (ib_devices_shared_netns)		net = &init_net;	else		net = read_pnet(&dev->coredev.rdma_net); 	return ns_capable(net->user_ns, CAP_NET_RAW);}EXPORT_SYMBOL(rdma_dev_has_raw_cap); /* * xarray has this behavior where it won't iterate over NULL values stored in * allocated arrays.  So we need our own iterator to see all values stored in * the array. This does the same thing as xa_for_each except that it also * returns NULL valued entries if the array is allocating. Simplified to only * work on simple xarrays. */static void *xan_find_marked(struct xarray *xa, unsigned long *indexp,			     xa_mark_t filter){	XA_STATE(xas, xa, *indexp);	void *entry; 	rcu_read_lock();	do {		entry = xas_find_marked(&xas, ULONG_MAX, filter);		if (xa_is_zero(entry))			break;	} while (xas_retry(&xas, entry));	rcu_read_unlock(); 	if (entry) {		*indexp = xas.xa_index;		if (xa_is_zero(entry))			return NULL;		return entry;	}	return XA_ERROR(-ENOENT);}#define xan_for_each_marked(xa, index, entry, filter)                          \	for (index = 0, entry = xan_find_marked(xa, &(index), filter);         \	     !xa_is_err(entry);                                                \	     (index)++, entry = xan_find_marked(xa, &(index), filter)) /* RCU hash table mapping netdevice pointers to struct ib_port_data */static DEFINE_SPINLOCK(ndev_hash_lock);static DECLARE_HASHTABLE(ndev_hash, 5); static void free_netdevs(struct ib_device *ib_dev);static void ib_unregister_work(struct work_struct *work);static void __ib_unregister_device(struct ib_device *device);static int ib_security_change(struct notifier_block *nb, unsigned long event,			      void *lsm_data);static void ib_policy_change_task(struct work_struct *work);static DECLARE_WORK(ib_policy_change_work, ib_policy_change_task); static void __ibdev_printk(const char *level, const struct ib_device *ibdev,			   struct va_format *vaf){	if (ibdev && ibdev->dev.parent)		dev_printk_emit(level[1] - '0',				ibdev->dev.parent,				"%s %s %s: %pV",				dev_driver_string(ibdev->dev.parent),				dev_name(ibdev->dev.parent),				dev_name(&ibdev->dev),				vaf);	else if (ibdev)		printk("%s%s: %pV",		       level, dev_name(&ibdev->dev), vaf);	else		printk("%s(NULL ib_device): %pV", level, vaf);} #define define_ibdev_printk_level(func, level)                  \void func(const struct ib_device *ibdev, const char *fmt, ...)  \{                                                               \	struct va_format vaf;                                   \	va_list args;                                           \								\	va_start(args, fmt);                                    \								\	vaf.fmt = fmt;                                          \	vaf.va = &args;                                         \								\	__ibdev_printk(level, ibdev, &vaf);                     \								\	va_end(args);                                           \}                                                               \EXPORT_SYMBOL(func); define_ibdev_printk_level(ibdev_emerg, KERN_EMERG);define_ibdev_printk_level(ibdev_alert, KERN_ALERT);define_ibdev_printk_level(ibdev_crit, KERN_CRIT);define_ibdev_printk_level(ibdev_err, KERN_ERR);define_ibdev_printk_level(ibdev_warn, KERN_WARNING);define_ibdev_printk_level(ibdev_notice, KERN_NOTICE);define_ibdev_printk_level(ibdev_info, KERN_INFO); static struct notifier_block ibdev_lsm_nb = {	.notifier_call = ib_security_change,}; static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,				 struct net *net, const char *requested_name,				 const char *fallback_pattern); /* Pointer to the RCU head at the start of the ib_port_data array */struct ib_port_data_rcu {	struct rcu_head rcu_head;	struct ib_port_data pdata[];}; static void ib_device_check_mandatory(struct ib_device *device){#define IB_MANDATORY_FUNC(x) { offsetof(struct ib_device_ops, x), #x }	static const struct {		size_t offset;		char  *name;	} mandatory_table[] = {		IB_MANDATORY_FUNC(query_device),		IB_MANDATORY_FUNC(query_port),		IB_MANDATORY_FUNC(alloc_pd),		IB_MANDATORY_FUNC(dealloc_pd),		IB_MANDATORY_FUNC(create_qp),		IB_MANDATORY_FUNC(modify_qp),		IB_MANDATORY_FUNC(destroy_qp),		IB_MANDATORY_FUNC(post_send),		IB_MANDATORY_FUNC(post_recv),		IB_MANDATORY_FUNC(create_cq),		IB_MANDATORY_FUNC(destroy_cq),		IB_MANDATORY_FUNC(poll_cq),		IB_MANDATORY_FUNC(req_notify_cq),		IB_MANDATORY_FUNC(get_dma_mr),		IB_MANDATORY_FUNC(reg_user_mr),		IB_MANDATORY_FUNC(dereg_mr),		IB_MANDATORY_FUNC(get_port_immutable)	};	int i; 	device->kverbs_provider = true;	for (i = 0; i < ARRAY_SIZE(mandatory_table); ++i) {		if (!*(void **) ((void *) &device->ops +				 mandatory_table[i].offset)) {			device->kverbs_provider = false;			break;		}	}} /* * Caller must perform ib_device_put() to return the device reference count * when ib_device_get_by_index() returns valid device pointer. */struct ib_device *ib_device_get_by_index(const struct net *net, u32 index){	struct ib_device *device; 	down_read(&devices_rwsem);	device = xa_load(&devices, index);	if (device) {		if (!rdma_dev_access_netns(device, net)) {			device = NULL;			goto out;		} 		if (!ib_device_try_get(device))			device = NULL;	}out:	up_read(&devices_rwsem);	return device;} /** * ib_device_put - Release IB device reference * @device: device whose reference to be released * * ib_device_put() releases reference to the IB device to allow it to be * unregistered and eventually free. */void ib_device_put(struct ib_device *device){	if (refcount_dec_and_test(&device->refcount))		complete(&device->unreg_completion);}EXPORT_SYMBOL(ib_device_put); static struct ib_device *__ib_device_get_by_name(const char *name,						 const struct net *net){	struct ib_device *device;	unsigned long index; 	xa_for_each (&devices, index, device)		if (rdma_dev_access_netns(device, net) &&		    !strcmp(name, dev_name(&device->dev)))			return device; 	return NULL;} static int rename_compat_devs(struct ib_device *device){	struct ib_core_device *cdev;	unsigned long index;	int ret = 0; 	mutex_lock(&device->compat_devs_mutex);	xa_for_each (&device->compat_devs, index, cdev) {		ret = device_rename(&cdev->dev, dev_name(&device->dev));		if (ret) {			dev_warn(&cdev->dev,				 "Fail to rename compatdev to new name %s\n",				 dev_name(&device->dev));			break;		}	}	mutex_unlock(&device->compat_devs_mutex);	return ret;} int ib_device_rename(struct ib_device *ibdev, const char *name){	unsigned long index;	void *client_data;	int ret; 	down_write(&devices_rwsem);	if (!strcmp(name, dev_name(&ibdev->dev))) {		up_write(&devices_rwsem);		return 0;	} 	if (__ib_device_get_by_name(name, rdma_dev_net(ibdev))) {		up_write(&devices_rwsem);		return -EEXIST;	} 	ret = device_rename(&ibdev->dev, name);	if (ret) {		up_write(&devices_rwsem);		return ret;	} 	strscpy(ibdev->name, name, IB_DEVICE_NAME_MAX);	ret = rename_compat_devs(ibdev); 	downgrade_write(&devices_rwsem);	down_read(&ibdev->client_data_rwsem);	xan_for_each_marked(&ibdev->client_data, index, client_data,			    CLIENT_DATA_REGISTERED) {		struct ib_client *client = xa_load(&clients, index); 		if (!client || !client->rename)			continue; 		client->rename(ibdev, client_data);	}	up_read(&ibdev->client_data_rwsem);	rdma_nl_notify_event(ibdev, 0, RDMA_RENAME_EVENT);	up_read(&devices_rwsem);	return 0;} int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim){	if (use_dim > 1)		return -EINVAL;	ibdev->use_cq_dim = use_dim; 	return 0;} /* * Pick a free index for the '%d' style @name pattern within net namespace * @net. Returns the index on success or a negative errno. The caller builds * the final unique device name from the returned index. */static int __alloc_name_id(struct net *net, const char *name,			   const struct ib_device *skip){	struct ib_device *device;	unsigned long index;	struct ida inuse;	int rc;	int i; 	lockdep_assert_held_write(&devices_rwsem);	ida_init(&inuse);	xa_for_each (&devices, index, device) {		char buf[IB_DEVICE_NAME_MAX]; 		if (device == skip || !rdma_dev_access_netns(device, net))			continue;		if (sscanf(dev_name(&device->dev), name, &i) != 1)			continue;		if (i < 0 || i >= INT_MAX)			continue;		snprintf(buf, sizeof buf, name, i);		if (strcmp(buf, dev_name(&device->dev)) != 0)			continue; 		rc = ida_alloc_range(&inuse, i, i, GFP_KERNEL);		if (rc < 0)			goto out;	} 	rc = ida_alloc(&inuse, GFP_KERNEL);out:	ida_destroy(&inuse);	return rc;} static int alloc_name_id(struct net *net, const char *name){	return __alloc_name_id(net, name, NULL);} static int alloc_name(struct ib_device *ibdev, const char *name){	int id; 	id = alloc_name_id(rdma_dev_net(ibdev), name);	if (id < 0)		return id; 	return dev_set_name(&ibdev->dev, name, id);} static void ib_device_release(struct device *device){	struct ib_device *dev = container_of(device, struct ib_device, dev); 

Lines 1–500 of 3346.