X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fdccp%2Fccid.c;h=9d8fc0e289ea51c5cdecb924e26b2ce4c3d79150;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=ff05e59043cdb33769f810d16a8a667320d9e075;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index ff05e5904..9d8fc0e28 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c @@ -13,7 +13,7 @@ #include "ccid.h" -static struct ccid_operations *ccids[CCID_MAX]; +static struct ccid *ccids[CCID_MAX]; #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) static atomic_t ccids_lockct = ATOMIC_INIT(0); static DEFINE_SPINLOCK(ccids_lock); @@ -55,202 +55,85 @@ static inline void ccids_read_unlock(void) #define ccids_read_unlock() do { } while(0) #endif -static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...) +int ccid_register(struct ccid *ccid) { - kmem_cache_t *slab; - char slab_name_fmt[32], *slab_name; - va_list args; + int err; - 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, NULL); - if (slab == NULL) - kfree(slab_name); - return slab; -} - -static void ccid_kmem_cache_destroy(kmem_cache_t *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; + if (ccid->ccid_init == NULL) + return -1; ccids_write_lock(); err = -EEXIST; - if (ccids[ccid_ops->ccid_id] == NULL) { - ccids[ccid_ops->ccid_id] = ccid_ops; + if (ccids[ccid->ccid_id] == NULL) { + ccids[ccid->ccid_id] = ccid; 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: + if (err == 0) + pr_info("CCID: Registered CCID %d (%s)\n", + ccid->ccid_id, ccid->ccid_name); 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) +int ccid_unregister(struct ccid *ccid) { ccids_write_lock(); - ccids[ccid_ops->ccid_id] = NULL; + ccids[ccid->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); + ccid->ccid_id, ccid->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 *ccid_init(unsigned char id, struct sock *sk) { - struct ccid_operations *ccid_ops; - struct ccid *ccid = NULL; + struct ccid *ccid; - 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; + if (ccids[id] == NULL) request_module("net-dccp-ccid-%d", id); - ccids_read_lock(); - } #endif - ccid_ops = ccids[id]; - if (ccid_ops == NULL) - goto out_unlock; + ccids_read_lock(); - if (!try_module_get(ccid_ops->ccid_owner)) - goto out_unlock; + ccid = ccids[id]; + if (ccid == NULL) + goto out; - ccids_read_unlock(); + if (!try_module_get(ccid->ccid_owner)) + goto out_err; - ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab : - ccid_ops->ccid_hc_tx_slab, gfp); - if (ccid == NULL) + if (ccid->ccid_init(sk) != 0) 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; + return ccid; out_module_put: - module_put(ccid_ops->ccid_owner); + module_put(ccid->ccid_owner); +out_err: + ccid = NULL; 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); +EXPORT_SYMBOL_GPL(ccid_init); -static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx) +void ccid_exit(struct ccid *ccid, struct sock *sk) { - 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); + if (ccids[ccid->ccid_id] != NULL) { + if (ccid->ccid_exit != NULL) + ccid->ccid_exit(sk); + module_put(ccid->ccid_owner); + } -void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk) -{ - ccid_delete(ccid, sk, 0); + ccids_read_unlock(); } -EXPORT_SYMBOL_GPL(ccid_hc_tx_delete); +EXPORT_SYMBOL_GPL(ccid_exit);