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.
11 #include <linux/sched.h>
12 #include <linux/errno.h>
13 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/dirent.h>
17 #include <linux/smb_fs.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.
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
);
45 cachep
= (struct cache_head
*) get_cached_page(inode
, 0, 1);
50 struct cache_index
* index
= cachep
->index
;
51 struct cache_block
* block
;
57 * Here we only want to find existing cache blocks,
60 for (i
= 0; i
< cachep
->pages
; i
++, index
++) {
63 printk("smb_get_dircache: cache %s/%s has existing block!\n",
64 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
66 offset
= PAGE_SIZE
+ (i
<< PAGE_SHIFT
);
67 block
= (struct cache_block
*) get_cached_page(inode
,
80 * Unlock and release the data blocks.
83 smb_free_cache_blocks(struct cache_head
* cachep
)
85 struct cache_index
* index
= cachep
->index
;
88 #ifdef SMBFS_DEBUG_VERBOSE
89 printk("smb_free_cache_blocks: freeing %d blocks\n", cachep
->pages
);
91 for (i
= 0; i
< cachep
->pages
; i
++, index
++)
95 put_cached_page((unsigned long) index
->block
);
102 * Unlocks and releases the dircache.
105 smb_free_dircache(struct cache_head
* cachep
)
107 #ifdef SMBFS_DEBUG_VERBOSE
108 printk("smb_free_dircache: freeing cache\n");
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.
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
);
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.
133 smb_add_to_cache(struct cache_head
* cachep
, struct cache_dirent
*entry
,
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
);
148 * Don't do anything if we've had an error ...
153 index
= &cachep
->index
[cachep
->idx
];
157 /* space available? */
158 if (needed
< index
->space
)
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
;
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
);
179 * This block is full ... advance the index.
182 if (cachep
->idx
> NINDEX
) /* not likely */
185 #ifdef SMBFS_PARANOIA
187 printk("smb_add_to_cache: new index already has block!\n");
191 * Get the next cache block
195 page_off
= PAGE_SIZE
+ (cachep
->idx
<< PAGE_SHIFT
);
196 block
= (struct cache_block
*) get_cached_page(inode
, page_off
, 1);
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
);
208 * On failure, just set the return status ...
211 cachep
->status
= -ENOMEM
;
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;
225 #ifdef SMBFS_DEBUG_VERBOSE
226 printk("smb_find_in_cache: cache %p, looking for pos=%ld\n", cachep
, pos
);
228 for (i
= 0; i
< cachep
->pages
; i
++, index
++)
232 nent
= pos
- next_pos
;
233 next_pos
+= index
->num_entries
;
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
);
255 smb_refill_dircache(struct cache_head
* cachep
, struct dentry
*dentry
)
257 struct inode
* inode
= dentry
->d_inode
;
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
);
265 * Fill the cache, starting at position 2.
268 inode
->u
.smbfs_i
.cache_valid
|= SMB_F_CACHEVALID
;
269 result
= smb_proc_readdir(dentry
, 2, cachep
);
272 #ifdef SMBFS_PARANOIA
273 printk("smb_refill_dircache: readdir failed, result=%d\n", result
);
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");
290 result
= cachep
->status
;
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
);
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;