vdetelweb: wrong char count on write+it looped if the switch terminated during svdete...
[vde.git] / ipn / ipn_msgbuf.c
blob087cfd7cad2fc1995a9d8611ccaacc33bc47815c
1 /*
2 * Inter process networking (virtual distributed ethernet) module
3 * management of ipn_msgbuf (one slab for each MTU)
4 * (part of the View-OS project: wiki.virtualsquare.org)
6 * N.B. all these functions need global locking! (ipn_glob_lock)
8 * Copyright (C) 2007 Renzo Davoli (renzo@cs.unibo.it)
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * Due to this file being licensed under the GPL there is controversy over
16 * whether this permits you to write a module that #includes this file
17 * without placing your module under the GPL. Please consult a lawyer for
18 * advice before doing this.
20 * WARNING: THIS CODE IS ALREADY EXPERIMENTAL
24 #include <linux/init.h>
25 #include <linux/module.h>
27 #include "af_ipn.h"
28 #include "ipn_netdev.h"
30 struct ipn_msgbuf {
31 struct list_head list;
32 int mtu;
33 int refcnt;
34 char cachename[12];
35 struct kmem_cache *cache;
38 static LIST_HEAD(ipn_msgbufh);
39 static struct kmem_cache *ipn_msgbuf_cache;
41 /* get a kmem_cache pointer for a given mtu.
42 * it is a cache for struct msgpool_item elements (the latter field of
43 * the struct, i.e. the payload, has variable length depending on the mtu)
44 * if it exists already a cache with the given mtu, ipn_msgbuf_get creates
45 * one more reference for that cache, otherwise a new one is created.
47 struct kmem_cache *ipn_msgbuf_get(int mtu)
49 struct ipn_msgbuf *ipn_msgbuf;
50 list_for_each_entry(ipn_msgbuf, &ipn_msgbufh, list) {
51 if (mtu == ipn_msgbuf->mtu) {
52 ipn_msgbuf->refcnt++;
53 return ipn_msgbuf->cache;
56 ipn_msgbuf=kmem_cache_alloc(ipn_msgbuf_cache,GFP_KERNEL);
57 if (ipn_msgbuf == NULL)
58 return NULL;
59 else {
60 ipn_msgbuf->mtu=mtu;
61 ipn_msgbuf->refcnt=1;
62 snprintf(ipn_msgbuf->cachename,12,"ipn%d",mtu);
63 ipn_msgbuf->cache=kmem_cache_create(ipn_msgbuf->cachename,sizeof(struct msgpool_item)+mtu,0,0,NULL);
64 list_add_tail(&ipn_msgbuf->list,&ipn_msgbufh);
65 return ipn_msgbuf->cache;
69 /* release a reference of a msgbuf cache (a network with a given mtu
70 * is terminating).
71 * the last reference for a given mtu releases the slub*/
72 void ipn_msgbuf_put(struct kmem_cache *cache)
74 struct ipn_msgbuf *ipn_msgbuf;
75 list_for_each_entry(ipn_msgbuf, &ipn_msgbufh, list) {
76 if (ipn_msgbuf->cache == cache) {
77 ipn_msgbuf->refcnt--;
78 if (ipn_msgbuf->refcnt == 0) {
79 kmem_cache_destroy(ipn_msgbuf->cache);
80 list_del(&ipn_msgbuf->list);
81 kmem_cache_free(ipn_msgbuf_cache,ipn_msgbuf);
82 return;
88 int ipn_msgbuf_init(void)
90 ipn_msgbuf_cache=kmem_cache_create("ipn_msgbuf",sizeof(struct ipn_msgbuf),0,0,NULL);
91 if (!ipn_msgbuf_cache)
92 return -ENOMEM;
93 else
94 return 0;
97 void ipn_msgbuf_fini(void)
99 if (ipn_msgbuf_cache) {
100 while (!list_empty(&ipn_msgbufh)) {
101 struct ipn_msgbuf *ipn_msgbuf=list_first_entry(&ipn_msgbufh, struct ipn_msgbuf, list);
102 list_del(&ipn_msgbuf->list);
103 kmem_cache_destroy(ipn_msgbuf->cache);
104 kmem_cache_free(ipn_msgbuf_cache,ipn_msgbuf);
106 kmem_cache_destroy(ipn_msgbuf_cache);