First Support on Ginger and OMAP TI
[linux-ginger.git] / drivers / staging / pohmelfs / mcache.c
blobe22665cdd16c67b0005a4274386824c12807abba
1 /*
2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/mempool.h>
20 #include "netfs.h"
22 static struct kmem_cache *pohmelfs_mcache_cache;
23 static mempool_t *pohmelfs_mcache_pool;
25 static inline int pohmelfs_mcache_cmp(u64 gen, u64 new)
27 if (gen < new)
28 return 1;
29 if (gen > new)
30 return -1;
31 return 0;
34 struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen)
36 struct rb_root *root = &psb->mcache_root;
37 struct rb_node *n = root->rb_node;
38 struct pohmelfs_mcache *tmp, *ret = NULL;
39 int cmp;
41 while (n) {
42 tmp = rb_entry(n, struct pohmelfs_mcache, mcache_entry);
44 cmp = pohmelfs_mcache_cmp(tmp->gen, gen);
45 if (cmp < 0)
46 n = n->rb_left;
47 else if (cmp > 0)
48 n = n->rb_right;
49 else {
50 ret = tmp;
51 pohmelfs_mcache_get(ret);
52 break;
56 return ret;
59 static int pohmelfs_mcache_insert(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
61 struct rb_root *root = &psb->mcache_root;
62 struct rb_node **n = &root->rb_node, *parent = NULL;
63 struct pohmelfs_mcache *ret = NULL, *tmp;
64 int cmp;
66 while (*n) {
67 parent = *n;
69 tmp = rb_entry(parent, struct pohmelfs_mcache, mcache_entry);
71 cmp = pohmelfs_mcache_cmp(tmp->gen, m->gen);
72 if (cmp < 0)
73 n = &parent->rb_left;
74 else if (cmp > 0)
75 n = &parent->rb_right;
76 else {
77 ret = tmp;
78 break;
82 if (ret)
83 return -EEXIST;
85 rb_link_node(&m->mcache_entry, parent, n);
86 rb_insert_color(&m->mcache_entry, root);
88 return 0;
91 static int pohmelfs_mcache_remove(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
93 if (m && m->mcache_entry.rb_parent_color) {
94 rb_erase(&m->mcache_entry, &psb->mcache_root);
95 m->mcache_entry.rb_parent_color = 0;
96 return 1;
98 return 0;
101 void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
103 mutex_lock(&psb->mcache_lock);
104 pohmelfs_mcache_remove(psb, m);
105 mutex_unlock(&psb->mcache_lock);
108 struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start,
109 unsigned int size, void *data)
111 struct pohmelfs_mcache *m;
112 int err = -ENOMEM;
114 m = mempool_alloc(pohmelfs_mcache_pool, GFP_KERNEL);
115 if (!m)
116 goto err_out_exit;
118 init_completion(&m->complete);
119 m->err = 0;
120 atomic_set(&m->refcnt, 1);
121 m->data = data;
122 m->start = start;
123 m->size = size;
124 m->gen = atomic_long_inc_return(&psb->mcache_gen);
126 mutex_lock(&psb->mcache_lock);
127 err = pohmelfs_mcache_insert(psb, m);
128 mutex_unlock(&psb->mcache_lock);
129 if (err)
130 goto err_out_free;
132 return m;
134 err_out_free:
135 mempool_free(m, pohmelfs_mcache_pool);
136 err_out_exit:
137 return ERR_PTR(err);
140 void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m)
142 pohmelfs_mcache_remove_locked(psb, m);
144 mempool_free(m, pohmelfs_mcache_pool);
147 int __init pohmelfs_mcache_init(void)
149 pohmelfs_mcache_cache = kmem_cache_create("pohmelfs_mcache_cache",
150 sizeof(struct pohmelfs_mcache),
151 0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), NULL);
152 if (!pohmelfs_mcache_cache)
153 goto err_out_exit;
155 pohmelfs_mcache_pool = mempool_create_slab_pool(256, pohmelfs_mcache_cache);
156 if (!pohmelfs_mcache_pool)
157 goto err_out_free;
159 return 0;
161 err_out_free:
162 kmem_cache_destroy(pohmelfs_mcache_cache);
163 err_out_exit:
164 return -ENOMEM;
167 void pohmelfs_mcache_exit(void)
169 mempool_destroy(pohmelfs_mcache_pool);
170 kmem_cache_destroy(pohmelfs_mcache_cache);