⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccid.c

📁 linux 内核源代码
💻 C
字号:
/* *  net/dccp/ccid.c * *  An implementation of the DCCP protocol *  Arnaldo Carvalho de Melo <acme@conectiva.com.br> * *  CCID infrastructure * *	This program is free software; you can redistribute it and/or modify it *	under the terms of the GNU General Public License version 2 as *	published by the Free Software Foundation. */#include "ccid.h"static struct ccid_operations *ccids[CCID_MAX];#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)static atomic_t ccids_lockct = ATOMIC_INIT(0);static DEFINE_SPINLOCK(ccids_lock);/* * The strategy is: modifications ccids vector are short, do not sleep and * veeery rare, but read access should be free of any exclusive locks. */static void ccids_write_lock(void){	spin_lock(&ccids_lock);	while (atomic_read(&ccids_lockct) != 0) {		spin_unlock(&ccids_lock);		yield();		spin_lock(&ccids_lock);	}}static inline void ccids_write_unlock(void){	spin_unlock(&ccids_lock);}static inline void ccids_read_lock(void){	atomic_inc(&ccids_lockct);	smp_mb__after_atomic_inc();	spin_unlock_wait(&ccids_lock);}static inline void ccids_read_unlock(void){	atomic_dec(&ccids_lockct);}#else#define ccids_write_lock() do { } while(0)#define ccids_write_unlock() do { } while(0)#define ccids_read_lock() do { } while(0)#define ccids_read_unlock() do { } while(0)#endifstatic struct kmem_cache *ccid_kmem_cache_create(int obj_size, const char *fmt,...){	struct kmem_cache *slab;	char slab_name_fmt[32], *slab_name;	va_list args;	va_start(args, fmt);	vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args);	va_end(args);	slab_name = kstrdup(slab_name_fmt, GFP_KERNEL);	if (slab_name == NULL)		return NULL;	slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0,				 SLAB_HWCACHE_ALIGN, NULL);	if (slab == NULL)		kfree(slab_name);	return slab;}static void ccid_kmem_cache_destroy(struct kmem_cache *slab){	if (slab != NULL) {		const char *name = kmem_cache_name(slab);		kmem_cache_destroy(slab);		kfree(name);	}}int ccid_register(struct ccid_operations *ccid_ops){	int err = -ENOBUFS;	ccid_ops->ccid_hc_rx_slab =			ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size,					       "%s_hc_rx_sock",					       ccid_ops->ccid_name);	if (ccid_ops->ccid_hc_rx_slab == NULL)		goto out;	ccid_ops->ccid_hc_tx_slab =			ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size,					       "%s_hc_tx_sock",					       ccid_ops->ccid_name);	if (ccid_ops->ccid_hc_tx_slab == NULL)		goto out_free_rx_slab;	ccids_write_lock();	err = -EEXIST;	if (ccids[ccid_ops->ccid_id] == NULL) {		ccids[ccid_ops->ccid_id] = ccid_ops;		err = 0;	}	ccids_write_unlock();	if (err != 0)		goto out_free_tx_slab;	pr_info("CCID: Registered CCID %d (%s)\n",		ccid_ops->ccid_id, ccid_ops->ccid_name);out:	return err;out_free_tx_slab:	ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);	ccid_ops->ccid_hc_tx_slab = NULL;	goto out;out_free_rx_slab:	ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);	ccid_ops->ccid_hc_rx_slab = NULL;	goto out;}EXPORT_SYMBOL_GPL(ccid_register);int ccid_unregister(struct ccid_operations *ccid_ops){	ccids_write_lock();	ccids[ccid_ops->ccid_id] = NULL;	ccids_write_unlock();	ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);	ccid_ops->ccid_hc_tx_slab = NULL;	ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);	ccid_ops->ccid_hc_rx_slab = NULL;	pr_info("CCID: Unregistered CCID %d (%s)\n",		ccid_ops->ccid_id, ccid_ops->ccid_name);	return 0;}EXPORT_SYMBOL_GPL(ccid_unregister);struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp){	struct ccid_operations *ccid_ops;	struct ccid *ccid = NULL;	ccids_read_lock();#ifdef CONFIG_KMOD	if (ccids[id] == NULL) {		/* We only try to load if in process context */		ccids_read_unlock();		if (gfp & GFP_ATOMIC)			goto out;		request_module("net-dccp-ccid-%d", id);		ccids_read_lock();	}#endif	ccid_ops = ccids[id];	if (ccid_ops == NULL)		goto out_unlock;	if (!try_module_get(ccid_ops->ccid_owner))		goto out_unlock;	ccids_read_unlock();	ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab :				     ccid_ops->ccid_hc_tx_slab, gfp);	if (ccid == NULL)		goto out_module_put;	ccid->ccid_ops = ccid_ops;	if (rx) {		memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size);		if (ccid->ccid_ops->ccid_hc_rx_init != NULL &&		    ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0)			goto out_free_ccid;	} else {		memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size);		if (ccid->ccid_ops->ccid_hc_tx_init != NULL &&		    ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0)			goto out_free_ccid;	}out:	return ccid;out_unlock:	ccids_read_unlock();	goto out;out_free_ccid:	kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab :			ccid_ops->ccid_hc_tx_slab, ccid);	ccid = NULL;out_module_put:	module_put(ccid_ops->ccid_owner);	goto out;}EXPORT_SYMBOL_GPL(ccid_new);struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp){	return ccid_new(id, sk, 1, gfp);}EXPORT_SYMBOL_GPL(ccid_hc_rx_new);struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk,  gfp_t gfp){	return ccid_new(id, sk, 0, gfp);}EXPORT_SYMBOL_GPL(ccid_hc_tx_new);static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx){	struct ccid_operations *ccid_ops;	if (ccid == NULL)		return;	ccid_ops = ccid->ccid_ops;	if (rx) {		if (ccid_ops->ccid_hc_rx_exit != NULL)			ccid_ops->ccid_hc_rx_exit(sk);		kmem_cache_free(ccid_ops->ccid_hc_rx_slab,  ccid);	} else {		if (ccid_ops->ccid_hc_tx_exit != NULL)			ccid_ops->ccid_hc_tx_exit(sk);		kmem_cache_free(ccid_ops->ccid_hc_tx_slab,  ccid);	}	ccids_read_lock();	if (ccids[ccid_ops->ccid_id] != NULL)		module_put(ccid_ops->ccid_owner);	ccids_read_unlock();}void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk){	ccid_delete(ccid, sk, 1);}EXPORT_SYMBOL_GPL(ccid_hc_rx_delete);void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk){	ccid_delete(ccid, sk, 0);}EXPORT_SYMBOL_GPL(ccid_hc_tx_delete);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -