2 * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
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>
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)
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
;
42 tmp
= rb_entry(n
, struct pohmelfs_mcache
, mcache_entry
);
44 cmp
= pohmelfs_mcache_cmp(tmp
->gen
, gen
);
51 pohmelfs_mcache_get(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
;
69 tmp
= rb_entry(parent
, struct pohmelfs_mcache
, mcache_entry
);
71 cmp
= pohmelfs_mcache_cmp(tmp
->gen
, m
->gen
);
75 n
= &parent
->rb_right
;
85 rb_link_node(&m
->mcache_entry
, parent
, n
);
86 rb_insert_color(&m
->mcache_entry
, root
);
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;
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
;
114 m
= mempool_alloc(pohmelfs_mcache_pool
, GFP_KERNEL
);
118 init_completion(&m
->complete
);
120 atomic_set(&m
->refcnt
, 1);
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
);
135 mempool_free(m
, pohmelfs_mcache_pool
);
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
)
155 pohmelfs_mcache_pool
= mempool_create_slab_pool(256, pohmelfs_mcache_cache
);
156 if (!pohmelfs_mcache_pool
)
162 kmem_cache_destroy(pohmelfs_mcache_cache
);
167 void pohmelfs_mcache_exit(void)
169 mempool_destroy(pohmelfs_mcache_pool
);
170 kmem_cache_destroy(pohmelfs_mcache_cache
);