4 * Copyright (C) 1997 by Bill Hawes
6 * Routines to support directory cacheing using the page cache.
7 * This cache code is almost directly taken from ncpfs.
9 * Please add a note about your changes to smbfs in the ChangeLog file.
12 #include <linux/time.h>
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
16 #include <linux/dirent.h>
17 #include <linux/smb_fs.h>
18 #include <linux/pagemap.h>
19 #include <linux/net.h>
23 #include "smb_debug.h"
27 * Force the next attempt to use the cache to be a timeout.
28 * If we can't find the page that's fine, it will cause a refresh.
31 smb_invalid_dir_cache(struct inode
* dir
)
33 struct smb_sb_info
*server
= server_from_inode(dir
);
34 union smb_dir_cache
*cache
= NULL
;
35 struct page
*page
= NULL
;
37 page
= grab_cache_page(&dir
->i_data
, 0);
41 if (!PageUptodate(page
))
45 cache
->head
.time
= jiffies
- SMB_MAX_AGE(server
);
48 SetPageUptodate(page
);
51 page_cache_release(page
);
57 * Mark all dentries for 'parent' as invalid, forcing them to be re-read
60 smb_invalidate_dircache_entries(struct dentry
*parent
)
62 struct smb_sb_info
*server
= server_from_dentry(parent
);
63 struct list_head
*next
;
64 struct dentry
*dentry
;
66 spin_lock(&dcache_lock
);
67 next
= parent
->d_subdirs
.next
;
68 while (next
!= &parent
->d_subdirs
) {
69 dentry
= list_entry(next
, struct dentry
, d_u
.d_child
);
70 dentry
->d_fsdata
= NULL
;
71 smb_age_dentry(server
, dentry
);
74 spin_unlock(&dcache_lock
);
78 * dget, but require that fpos and parent matches what the dentry contains.
79 * dentry is not known to be a valid pointer at entry.
82 smb_dget_fpos(struct dentry
*dentry
, struct dentry
*parent
, unsigned long fpos
)
84 struct dentry
*dent
= dentry
;
85 struct list_head
*next
;
87 if (d_validate(dent
, parent
)) {
88 if (dent
->d_name
.len
<= SMB_MAXNAMELEN
&&
89 (unsigned long)dent
->d_fsdata
== fpos
) {
99 /* If a pointer is invalid, we search the dentry. */
100 spin_lock(&dcache_lock
);
101 next
= parent
->d_subdirs
.next
;
102 while (next
!= &parent
->d_subdirs
) {
103 dent
= list_entry(next
, struct dentry
, d_u
.d_child
);
104 if ((unsigned long)dent
->d_fsdata
== fpos
) {
115 spin_unlock(&dcache_lock
);
121 * Create dentry/inode for this file and add it to the dircache.
124 smb_fill_cache(struct file
*filp
, void *dirent
, filldir_t filldir
,
125 struct smb_cache_control
*ctrl
, struct qstr
*qname
,
126 struct smb_fattr
*entry
)
128 struct dentry
*newdent
, *dentry
= filp
->f_dentry
;
129 struct inode
*newino
, *inode
= dentry
->d_inode
;
130 struct smb_cache_control ctl
= *ctrl
;
135 qname
->hash
= full_name_hash(qname
->name
, qname
->len
);
137 if (dentry
->d_op
&& dentry
->d_op
->d_hash
)
138 if (dentry
->d_op
->d_hash(dentry
, qname
) != 0)
141 newdent
= d_lookup(dentry
, qname
);
144 newdent
= d_alloc(dentry
, qname
);
149 memcpy((char *) newdent
->d_name
.name
, qname
->name
,
150 newdent
->d_name
.len
);
153 if (!newdent
->d_inode
) {
154 smb_renew_times(newdent
);
155 entry
->f_ino
= iunique(inode
->i_sb
, 2);
156 newino
= smb_iget(inode
->i_sb
, entry
);
158 smb_new_dentry(newdent
);
159 d_instantiate(newdent
, newino
);
164 smb_set_inode_attr(newdent
->d_inode
, entry
);
166 if (newdent
->d_inode
) {
167 ino
= newdent
->d_inode
->i_ino
;
168 newdent
->d_fsdata
= (void *) ctl
.fpos
;
169 smb_new_dentry(newdent
);
172 if (ctl
.idx
>= SMB_DIRCACHE_SIZE
) {
175 SetPageUptodate(ctl
.page
);
176 unlock_page(ctl
.page
);
177 page_cache_release(ctl
.page
);
180 ctl
.idx
-= SMB_DIRCACHE_SIZE
;
182 ctl
.page
= grab_cache_page(&inode
->i_data
, ctl
.ofs
);
184 ctl
.cache
= kmap(ctl
.page
);
187 ctl
.cache
->dentry
[ctl
.idx
] = newdent
;
195 if (!ctl
.filled
&& (ctl
.fpos
== filp
->f_pos
)) {
197 ino
= find_inode_number(dentry
, qname
);
199 ino
= iunique(inode
->i_sb
, 2);
200 ctl
.filled
= filldir(dirent
, qname
->name
, qname
->len
,
201 filp
->f_pos
, ino
, DT_UNKNOWN
);
208 return (ctl
.valid
|| !ctl
.filled
);