1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#define __NO_VERSION__
24#include <linux/module.h>
25#include <stdarg.h>
26#include <asm/bitops.h>
27#include <asm/uaccess.h>
28#include <asm/system.h>
29
30#include <linux/errno.h>
31#include <linux/fs.h>
32#include <linux/ext2_fs.h>
33#include <linux/slab.h>
34#include <linux/vmalloc.h>
35#include <linux/sched.h>
36#include <linux/stat.h>
37#include <linux/string.h>
38#include <linux/locks.h>
39#include <linux/blkdev.h>
40#include <linux/init.h>
41
42#include <linux/intermezzo_fs.h>
43#include <linux/intermezzo_psdev.h>
44
45
46
47
48
49
50
51
52
53extern kmem_cache_t * presto_dentry_slab;
54
55
56#define CACHES_BITS 8
57#define CACHES_SIZE (1 << CACHES_BITS)
58#define CACHES_MASK CACHES_SIZE - 1
59static struct list_head presto_caches[CACHES_SIZE];
60
61static inline int presto_cache_hash(kdev_t dev)
62{
63 return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
64}
65
66inline void presto_cache_add(struct presto_cache *cache, kdev_t dev)
67{
68 list_add(&cache->cache_chain,
69 &presto_caches[presto_cache_hash(dev)]);
70 cache->cache_dev = dev;
71}
72
73inline void presto_cache_init_hash(void)
74{
75 int i;
76 for ( i = 0; i < CACHES_SIZE; i++ ) {
77 INIT_LIST_HEAD(&presto_caches[i]);
78 }
79}
80
81int izo_ioctl_packlen(struct izo_ioctl_data *data)
82{
83 int len = sizeof(struct izo_ioctl_data);
84 len += size_round(data->ioc_inllen1);
85 len += size_round(data->ioc_inllen2);
86 return len;
87}
88
89
90struct presto_cache *presto_cache_find(kdev_t dev)
91{
92 struct presto_cache *cache;
93 struct list_head *lh, *tmp;
94
95 lh = tmp = &(presto_caches[presto_cache_hash(dev)]);
96 while ( (tmp = lh->next) != lh ) {
97 cache = list_entry(tmp, struct presto_cache, cache_chain);
98 if ( cache->cache_dev == dev ) {
99 return cache;
100 }
101 }
102 return NULL;
103}
104
105
106
107struct presto_cache *presto_get_cache(struct inode *inode)
108{
109 struct presto_cache *cache;
110 ENTRY;
111
112 cache = presto_cache_find(inode->i_dev);
113 if ( !cache ) {
114 CERROR("WARNING: no presto cache for dev %x, ino %ld\n",
115 inode->i_dev, inode->i_ino);
116 EXIT;
117 return NULL;
118 }
119 EXIT;
120 return cache;
121}
122
123
124int presto_ispresto(struct inode *inode)
125{
126 struct presto_cache *cache;
127
128 if ( !inode )
129 return 0;
130 cache = presto_get_cache(inode);
131 if ( !cache )
132 return 0;
133 return (inode->i_dev == cache->cache_dev);
134}
135
136
137struct presto_cache *presto_cache_init(void)
138{
139 struct presto_cache *cache;
140
141 PRESTO_ALLOC(cache, sizeof(struct presto_cache));
142 if ( cache ) {
143 memset(cache, 0, sizeof(struct presto_cache));
144 INIT_LIST_HEAD(&cache->cache_chain);
145 INIT_LIST_HEAD(&cache->cache_fset_list);
146 cache->cache_lock = SPIN_LOCK_UNLOCKED;
147 cache->cache_reserved = 0;
148 }
149 return cache;
150}
151
152
153inline void presto_free_cache(struct presto_cache *cache)
154{
155 if (!cache)
156 return;
157
158 list_del(&cache->cache_chain);
159 if (cache->cache_sb && cache->cache_sb->s_root &&
160 presto_d2d(cache->cache_sb->s_root)) {
161 kmem_cache_free(presto_dentry_slab,
162 presto_d2d(cache->cache_sb->s_root));
163 cache->cache_sb->s_root->d_fsdata = NULL;
164 }
165
166 if (cache->cache_type)
167 PRESTO_FREE(cache->cache_type, strlen(cache->cache_type) + 1 );
168
169 PRESTO_FREE(cache, sizeof(struct presto_cache));
170}
171
172int presto_reserve_space(struct presto_cache *cache, loff_t req)
173{
174 struct filter_fs *filter;
175 loff_t avail;
176 struct super_block *sb = cache->cache_sb;
177 filter = cache->cache_filter;
178 if (!filter ) {
179 EXIT;
180 return 0;
181 }
182 if (!filter->o_trops ) {
183 EXIT;
184 return 0;
185 }
186 if (!filter->o_trops->tr_avail ) {
187 EXIT;
188 return 0;
189 }
190
191 spin_lock(&cache->cache_lock);
192 avail = filter->o_trops->tr_avail(cache, sb);
193 CDEBUG(D_SUPER, "ESC::%ld +++> %ld \n", (long) cache->cache_reserved,
194 (long) (cache->cache_reserved + req));
195 CDEBUG(D_SUPER, "ESC::Avail::%ld \n", (long) avail);
196 if (req + cache->cache_reserved > avail) {
197 spin_unlock(&cache->cache_lock);
198 EXIT;
199 return -ENOSPC;
200 }
201 cache->cache_reserved += req;
202 spin_unlock(&cache->cache_lock);
203
204 EXIT;
205 return 0;
206}
207
208void presto_release_space(struct presto_cache *cache, loff_t req)
209{
210 CDEBUG(D_SUPER, "ESC::%ld ---> %ld \n", (long) cache->cache_reserved,
211 (long) (cache->cache_reserved - req));
212 spin_lock(&cache->cache_lock);
213 cache->cache_reserved -= req;
214 spin_unlock(&cache->cache_lock);
215}
216