From d4ddf1a161b38a8dc95717cb538d4dd826fb3bb8 Mon Sep 17 00:00:00 2001 From: rd235 Date: Fri, 18 Jan 2008 09:56:07 +0000 Subject: [PATCH] ipn_msgbuf added (management of shared stubs for networks having the same MTU) git-svn-id: https://vde.svn.sourceforge.net/svnroot/vde/trunk@225 d37a7db1-d92d-0410-89df-f68f52f87b57 --- ipn/Makefile | 2 +- ipn/af_ipn.c | 25 +++++++++---- ipn/ipn_msgbuf.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ipn/ipn_msgbuf.h | 30 ++++++++++++++++ 4 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 ipn/ipn_msgbuf.c create mode 100644 ipn/ipn_msgbuf.h diff --git a/ipn/Makefile b/ipn/Makefile index 1d4d20b..000b589 100644 --- a/ipn/Makefile +++ b/ipn/Makefile @@ -9,7 +9,7 @@ ifneq ($(KERNELRELEASE),) obj-m += ipn.o - ipn-objs := af_ipn.o ipn_netdev.o + ipn-objs := af_ipn.o ipn_netdev.o ipn_msgbuf.o else KERNELDIR ?= /lib/modules/$(shell uname -r)/build diff --git a/ipn/af_ipn.c b/ipn/af_ipn.c index 035b322..19387e4 100644 --- a/ipn/af_ipn.c +++ b/ipn/af_ipn.c @@ -32,6 +32,7 @@ */ #include "af_ipn.h" #include "ipn_netdev.h" +#include "ipn_msgbuf.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("VIEW-OS TEAM"); @@ -391,7 +392,8 @@ static int ipn_terminate_node(struct ipn_node *ipn_node) mntput(ipnn->mnt); } if (ipnn->msgpool_cache) - kmem_cache_destroy(ipnn->msgpool_cache); + /*kmem_cache_destroy(ipnn->msgpool_cache);*/ + ipn_msgbuf_put(ipnn->msgpool_cache); if (ipnn->connport) kfree(ipnn->connport); kmem_cache_free(ipn_network_cache, ipnn); @@ -584,7 +586,8 @@ static int ipn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) } memcpy(&ipnn->sunaddr,sunaddr,addr_len); ipnn->mtu=parms.mtu; - ipnn->msgpool_cache=kmem_cache_create(ipnn->sunaddr.sun_path,sizeof(struct msgpool_item)+ipnn->mtu,0,0,NULL); + /*ipnn->msgpool_cache=kmem_cache_create(ipnn->sunaddr.sun_path,sizeof(struct msgpool_item)+ipnn->mtu,0,0,NULL);*/ + ipnn->msgpool_cache=ipn_msgbuf_get(ipnn->mtu); if (!ipnn->msgpool_cache) { err=-ENOMEM; goto out_mknod_dput_putmodule; @@ -1557,11 +1560,18 @@ static int ipn_init(void) goto out_net_node; } + rc=ipn_msgbuf_init(); + if (rc != 0) { + printk(KERN_CRIT "%s: Cannot create ipn_msgbuf SLAB cache\n", + __FUNCTION__); + goto out_net_node_msg; + } + rc=proto_register(&ipn_proto,1); if (rc != 0) { printk(KERN_CRIT "%s: Cannot register the protocol!\n", __FUNCTION__); - goto out_net_node_msg; + goto out_net_node_msg_msgbuf; } sock_register(&ipn_family_ops); @@ -1569,12 +1579,14 @@ static int ipn_init(void) printk(KERN_INFO "IPN: Virtual Square Project, University of Bologna 2007\n"); return 0; +out_net_node_msg_msgbuf: + ipn_msgbuf_fini(); out_net_node_msg: - kmem_cache_destroy(ipn_msgitem_cache); + kmem_cache_destroy(ipn_msgitem_cache); out_net_node: - kmem_cache_destroy(ipn_node_cache); + kmem_cache_destroy(ipn_node_cache); out_net: - kmem_cache_destroy(ipn_network_cache); + kmem_cache_destroy(ipn_network_cache); out: return rc; } @@ -1589,6 +1601,7 @@ static void ipn_exit(void) kmem_cache_destroy(ipn_node_cache); if (ipn_network_cache) kmem_cache_destroy(ipn_network_cache); + ipn_msgbuf_fini(); sock_unregister(PF_IPN); proto_unregister(&ipn_proto); printk(KERN_INFO "IPN removed\n"); diff --git a/ipn/ipn_msgbuf.c b/ipn/ipn_msgbuf.c new file mode 100644 index 0000000..087cfd7 --- /dev/null +++ b/ipn/ipn_msgbuf.c @@ -0,0 +1,108 @@ +/* + * Inter process networking (virtual distributed ethernet) module + * management of ipn_msgbuf (one slab for each MTU) + * (part of the View-OS project: wiki.virtualsquare.org) + * + * N.B. all these functions need global locking! (ipn_glob_lock) + * + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Due to this file being licensed under the GPL there is controversy over + * whether this permits you to write a module that #includes this file + * without placing your module under the GPL. Please consult a lawyer for + * advice before doing this. + * + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL + * + */ + +#include +#include + +#include "af_ipn.h" +#include "ipn_netdev.h" + +struct ipn_msgbuf { + struct list_head list; + int mtu; + int refcnt; + char cachename[12]; + struct kmem_cache *cache; +}; + +static LIST_HEAD(ipn_msgbufh); +static struct kmem_cache *ipn_msgbuf_cache; + +/* get a kmem_cache pointer for a given mtu. + * it is a cache for struct msgpool_item elements (the latter field of + * the struct, i.e. the payload, has variable length depending on the mtu) + * if it exists already a cache with the given mtu, ipn_msgbuf_get creates + * one more reference for that cache, otherwise a new one is created. + */ +struct kmem_cache *ipn_msgbuf_get(int mtu) +{ + struct ipn_msgbuf *ipn_msgbuf; + list_for_each_entry(ipn_msgbuf, &ipn_msgbufh, list) { + if (mtu == ipn_msgbuf->mtu) { + ipn_msgbuf->refcnt++; + return ipn_msgbuf->cache; + } + } + ipn_msgbuf=kmem_cache_alloc(ipn_msgbuf_cache,GFP_KERNEL); + if (ipn_msgbuf == NULL) + return NULL; + else { + ipn_msgbuf->mtu=mtu; + ipn_msgbuf->refcnt=1; + snprintf(ipn_msgbuf->cachename,12,"ipn%d",mtu); + ipn_msgbuf->cache=kmem_cache_create(ipn_msgbuf->cachename,sizeof(struct msgpool_item)+mtu,0,0,NULL); + list_add_tail(&ipn_msgbuf->list,&ipn_msgbufh); + return ipn_msgbuf->cache; + } +} + +/* release a reference of a msgbuf cache (a network with a given mtu + * is terminating). + * the last reference for a given mtu releases the slub*/ +void ipn_msgbuf_put(struct kmem_cache *cache) +{ + struct ipn_msgbuf *ipn_msgbuf; + list_for_each_entry(ipn_msgbuf, &ipn_msgbufh, list) { + if (ipn_msgbuf->cache == cache) { + ipn_msgbuf->refcnt--; + if (ipn_msgbuf->refcnt == 0) { + kmem_cache_destroy(ipn_msgbuf->cache); + list_del(&ipn_msgbuf->list); + kmem_cache_free(ipn_msgbuf_cache,ipn_msgbuf); + return; + } + } + } +} + +int ipn_msgbuf_init(void) +{ + ipn_msgbuf_cache=kmem_cache_create("ipn_msgbuf",sizeof(struct ipn_msgbuf),0,0,NULL); + if (!ipn_msgbuf_cache) + return -ENOMEM; + else + return 0; +} + +void ipn_msgbuf_fini(void) +{ + if (ipn_msgbuf_cache) { + while (!list_empty(&ipn_msgbufh)) { + struct ipn_msgbuf *ipn_msgbuf=list_first_entry(&ipn_msgbufh, struct ipn_msgbuf, list); + list_del(&ipn_msgbuf->list); + kmem_cache_destroy(ipn_msgbuf->cache); + kmem_cache_free(ipn_msgbuf_cache,ipn_msgbuf); + } + kmem_cache_destroy(ipn_msgbuf_cache); + } +} diff --git a/ipn/ipn_msgbuf.h b/ipn/ipn_msgbuf.h new file mode 100644 index 0000000..a72a417 --- /dev/null +++ b/ipn/ipn_msgbuf.h @@ -0,0 +1,30 @@ +/* + * Inter process networking (virtual distributed ethernet) module + * management of msgbuf (one slab for each MTU) + * (part of the View-OS project: wiki.virtualsquare.org) + * + * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Due to this file being licensed under the GPL there is controversy over + * whether this permits you to write a module that #includes this file + * without placing your module under the GPL. Please consult a lawyer for + * advice before doing this. + * + * WARNING: THIS CODE IS ALREADY EXPERIMENTAL + * + */ + +#ifndef _IPN_MSGBUF_H +#define _IPN_MSGBUF_H + +struct kmem_cache *ipn_msgbuf_get(int mtu); +void ipn_msgbuf_put(struct kmem_cache *cache); +int ipn_msgbuf_init(void); +void ipn_msgbuf_fini(void); + +#endif -- 2.11.4.GIT