Import 2.2.3pre2
[davej-history.git] / fs / smbfs / cache.c
blob292493dacb18049afb06bb9f5775f624b0a6647f
1 /*
2 * cache.c
4 * Copyright (C) 1997 by Bill Hawes
6 * Routines to support directory cacheing using the page cache.
7 * Right now this only works for smbfs, but will be generalized
8 * for use with other filesystems.
9 */
11 #include <linux/sched.h>
12 #include <linux/errno.h>
13 #include <linux/kernel.h>
14 #include <linux/mm.h>
15 #include <linux/errno.h>
16 #include <linux/dirent.h>
17 #include <linux/smb_fs.h>
19 #include <asm/page.h>
21 #define SMBFS_PARANOIA 1
22 /* #define SMBFS_DEBUG_VERBOSE 1 */
24 static inline struct inode *
25 get_cache_inode(struct cache_head *cachep)
27 return (mem_map + MAP_NR((unsigned long) cachep))->inode;
31 * Get a pointer to the cache_head structure,
32 * mapped as the page at offset 0. The page is
33 * kept locked while we're using the cache.
35 struct cache_head *
36 smb_get_dircache(struct dentry * dentry)
38 struct inode * inode = dentry->d_inode;
39 struct cache_head * cachep;
41 #ifdef SMBFS_DEBUG_VERBOSE
42 printk("smb_get_dircache: finding cache for %s/%s\n",
43 dentry->d_parent->d_name.name, dentry->d_name.name);
44 #endif
45 cachep = (struct cache_head *) get_cached_page(inode, 0, 1);
46 if (!cachep)
47 goto out;
48 if (cachep->valid)
50 struct cache_index * index = cachep->index;
51 struct cache_block * block;
52 unsigned long offset;
53 int i;
55 cachep->valid = 0;
57 * Here we only want to find existing cache blocks,
58 * not add new ones.
60 for (i = 0; i < cachep->pages; i++, index++) {
61 #ifdef SMBFS_PARANOIA
62 if (index->block)
63 printk("smb_get_dircache: cache %s/%s has existing block!\n",
64 dentry->d_parent->d_name.name, dentry->d_name.name);
65 #endif
66 offset = PAGE_SIZE + (i << PAGE_SHIFT);
67 block = (struct cache_block *) get_cached_page(inode,
68 offset, 0);
69 if (!block)
70 goto out;
71 index->block = block;
73 cachep->valid = 1;
75 out:
76 return cachep;
80 * Unlock and release the data blocks.
82 static void
83 smb_free_cache_blocks(struct cache_head * cachep)
85 struct cache_index * index = cachep->index;
86 int i;
88 #ifdef SMBFS_DEBUG_VERBOSE
89 printk("smb_free_cache_blocks: freeing %d blocks\n", cachep->pages);
90 #endif
91 for (i = 0; i < cachep->pages; i++, index++)
93 if (index->block)
95 put_cached_page((unsigned long) index->block);
96 index->block = NULL;
102 * Unlocks and releases the dircache.
104 void
105 smb_free_dircache(struct cache_head * cachep)
107 #ifdef SMBFS_DEBUG_VERBOSE
108 printk("smb_free_dircache: freeing cache\n");
109 #endif
110 smb_free_cache_blocks(cachep);
111 put_cached_page((unsigned long) cachep);
115 * Initializes the dircache. We release any existing data blocks,
116 * and then clear the cache_head structure.
118 void
119 smb_init_dircache(struct cache_head * cachep)
121 #ifdef SMBFS_DEBUG_VERBOSE
122 printk("smb_init_dircache: initializing cache, %d blocks\n", cachep->pages);
123 #endif
124 smb_free_cache_blocks(cachep);
125 memset(cachep, 0, sizeof(struct cache_head));
129 * Add a new entry to the cache. This assumes that the
130 * entries are coming in order and are added to the end.
132 void
133 smb_add_to_cache(struct cache_head * cachep, struct cache_dirent *entry,
134 off_t fpos)
136 struct inode * inode = get_cache_inode(cachep);
137 struct cache_index * index;
138 struct cache_block * block;
139 unsigned long page_off;
140 unsigned int nent, offset, len = entry->len;
141 unsigned int needed = len + sizeof(struct cache_entry);
143 #ifdef SMBFS_DEBUG_VERBOSE
144 printk("smb_add_to_cache: cache inode %p, status %d, adding %s at %ld\n",
145 inode, cachep->status, entry->d_name, fpos);
146 #endif
148 * Don't do anything if we've had an error ...
150 if (cachep->status)
151 goto out;
153 index = &cachep->index[cachep->idx];
154 if (!index->block)
155 goto get_block;
157 /* space available? */
158 if (needed < index->space)
160 add_entry:
161 nent = index->num_entries;
162 index->num_entries++;
163 index->space -= needed;
164 offset = index->space +
165 index->num_entries * sizeof(struct cache_entry);
166 block = index->block;
167 memcpy(&block->cb_data.names[offset], entry->name, len);
168 block->cb_data.table[nent].namelen = len;
169 block->cb_data.table[nent].offset = offset;
170 block->cb_data.table[nent].ino = entry->ino;
171 cachep->entries++;
172 #ifdef SMBFS_DEBUG_VERBOSE
173 printk("smb_add_to_cache: added entry %s, len=%d, pos=%ld, entries=%d\n",
174 entry->d_name, len, fpos, cachep->entries);
175 #endif
176 return;
179 * This block is full ... advance the index.
181 cachep->idx++;
182 if (cachep->idx > NINDEX) /* not likely */
183 goto out_full;
184 index++;
185 #ifdef SMBFS_PARANOIA
186 if (index->block)
187 printk("smb_add_to_cache: new index already has block!\n");
188 #endif
191 * Get the next cache block
193 get_block:
194 cachep->pages++;
195 page_off = PAGE_SIZE + (cachep->idx << PAGE_SHIFT);
196 block = (struct cache_block *) get_cached_page(inode, page_off, 1);
197 if (block)
199 index->block = block;
200 index->space = PAGE_SIZE;
201 #ifdef SMBFS_DEBUG_VERBOSE
202 printk("smb_add_to_cache: inode=%p, pages=%d, block at %ld\n",
203 inode, cachep->pages, page_off);
204 #endif
205 goto add_entry;
208 * On failure, just set the return status ...
210 out_full:
211 cachep->status = -ENOMEM;
212 out:
213 return;
217 smb_find_in_cache(struct cache_head * cachep, off_t pos,
218 struct cache_dirent *entry)
220 struct cache_index * index = cachep->index;
221 struct cache_block * block;
222 unsigned int i, nent, offset = 0;
223 off_t next_pos = 2;
225 #ifdef SMBFS_DEBUG_VERBOSE
226 printk("smb_find_in_cache: cache %p, looking for pos=%ld\n", cachep, pos);
227 #endif
228 for (i = 0; i < cachep->pages; i++, index++)
230 if (pos < next_pos)
231 break;
232 nent = pos - next_pos;
233 next_pos += index->num_entries;
234 if (pos >= next_pos)
235 continue;
237 * The entry is in this block. Note: we return
238 * then name as a reference with _no_ null byte.
240 block = index->block;
241 entry->ino = block->cb_data.table[nent].ino;
242 entry->len = block->cb_data.table[nent].namelen;
243 offset = block->cb_data.table[nent].offset;
244 entry->name = &block->cb_data.names[offset];
245 #ifdef SMBFS_DEBUG_VERBOSE
246 printk("smb_find_in_cache: found %s, len=%d, pos=%ld\n",
247 entry->name, entry->len, pos);
248 #endif
249 break;
251 return offset;
255 smb_refill_dircache(struct cache_head * cachep, struct dentry *dentry)
257 struct inode * inode = dentry->d_inode;
258 int result;
260 #ifdef SMBFS_DEBUG_VERBOSE
261 printk("smb_refill_dircache: cache %s/%s, blocks=%d\n",
262 dentry->d_parent->d_name.name, dentry->d_name.name, cachep->pages);
263 #endif
265 * Fill the cache, starting at position 2.
267 retry:
268 inode->u.smbfs_i.cache_valid |= SMB_F_CACHEVALID;
269 result = smb_proc_readdir(dentry, 2, cachep);
270 if (result < 0)
272 #ifdef SMBFS_PARANOIA
273 printk("smb_refill_dircache: readdir failed, result=%d\n", result);
274 #endif
275 goto out;
279 * Check whether the cache was invalidated while
280 * we were doing the scan ...
282 if (!(inode->u.smbfs_i.cache_valid & SMB_F_CACHEVALID))
284 #ifdef SMBFS_PARANOIA
285 printk("smb_refill_dircache: cache invalidated, retrying\n");
286 #endif
287 goto retry;
290 result = cachep->status;
291 if (!result)
293 cachep->valid = 1;
295 #ifdef SMBFS_DEBUG_VERBOSE
296 printk("smb_refill_cache: cache %s/%s status=%d, entries=%d\n",
297 dentry->d_parent->d_name.name, dentry->d_name.name,
298 cachep->status, cachep->entries);
299 #endif
301 out:
302 return result;
305 void
306 smb_invalid_dir_cache(struct inode * dir)
309 * Get rid of any unlocked pages, and clear the
310 * 'valid' flag in case a scan is in progress.
312 invalidate_inode_pages(dir);
313 dir->u.smbfs_i.cache_valid &= ~SMB_F_CACHEVALID;
314 dir->u.smbfs_i.oldmtime = 0;