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/smb_fs.h>
17 #include <linux/pagemap.h>
18 #include <linux/net.h>
22 #include "smb_debug.h"
26 * Force the next attempt to use the cache to be a timeout.
27 * If we can't find the page that's fine, it will cause a refresh.
30 smb_invalid_dir_cache(struct inode
* dir
)
32 struct smb_sb_info
*server
= server_from_inode(dir
);
33 union smb_dir_cache
*cache
= NULL
;
34 struct page
*page
= NULL
;
36 page
= grab_cache_page(&dir
->i_data
, 0);
40 if (!PageUptodate(page
))
44 cache
->head
.time
= jiffies
- SMB_MAX_AGE(server
);
47 SetPageUptodate(page
);
50 page_cache_release(page
);
56 * Mark all dentries for 'parent' as invalid, forcing them to be re-read
59 smb_invalidate_dircache_entries(struct dentry
*parent
)
61 struct smb_sb_info
*server
= server_from_dentry(parent
);
62 struct list_head
*next
;
63 struct dentry
*dentry
;
65 spin_lock(&dcache_lock
);
66 next
= parent
->d_subdirs
.next
;
67 while (next
!= &parent
->d_subdirs
) {
68 dentry
= list_entry(next
, struct dentry
, d_u
.d_child
);
69 dentry
->d_fsdata
= NULL
;
70 smb_age_dentry(server
, dentry
);
73 spin_unlock(&dcache_lock
);
77 * dget, but require that fpos and parent matches what the dentry contains.
78 * dentry is not known to be a valid pointer at entry.
81 smb_dget_fpos(struct dentry
*dentry
, struct dentry
*parent
, unsigned long fpos
)
83 struct dentry
*dent
= dentry
;
84 struct list_head
*next
;
86 if (d_validate(dent
, parent
)) {
87 if (dent
->d_name
.len
<= SMB_MAXNAMELEN
&&
88 (unsigned long)dent
->d_fsdata
== fpos
) {
98 /* If a pointer is invalid, we search the dentry. */
99 spin_lock(&dcache_lock
);
100 next
= parent
->d_subdirs
.next
;
101 while (next
!= &parent
->d_subdirs
) {
102 dent
= list_entry(next
, struct dentry
, d_u
.d_child
);
103 if ((unsigned long)dent
->d_fsdata
== fpos
) {
114 spin_unlock(&dcache_lock
);
120 * Create dentry/inode for this file and add it to the dircache.
123 smb_fill_cache(struct file
*filp
, void *dirent
, filldir_t filldir
,
124 struct smb_cache_control
*ctrl
, struct qstr
*qname
,
125 struct smb_fattr
*entry
)
127 struct dentry
*newdent
, *dentry
= filp
->f_path
.dentry
;
128 struct inode
*newino
, *inode
= dentry
->d_inode
;
129 struct smb_cache_control ctl
= *ctrl
;
134 qname
->hash
= full_name_hash(qname
->name
, qname
->len
);
136 if (dentry
->d_op
&& dentry
->d_op
->d_hash
)
137 if (dentry
->d_op
->d_hash(dentry
, qname
) != 0)
140 newdent
= d_lookup(dentry
, qname
);
143 newdent
= d_alloc(dentry
, qname
);
148 memcpy((char *) newdent
->d_name
.name
, qname
->name
,
149 newdent
->d_name
.len
);
152 if (!newdent
->d_inode
) {
153 smb_renew_times(newdent
);
154 entry
->f_ino
= iunique(inode
->i_sb
, 2);
155 newino
= smb_iget(inode
->i_sb
, entry
);
157 smb_new_dentry(newdent
);
158 d_instantiate(newdent
, newino
);
163 smb_set_inode_attr(newdent
->d_inode
, entry
);
165 if (newdent
->d_inode
) {
166 ino
= newdent
->d_inode
->i_ino
;
167 newdent
->d_fsdata
= (void *) ctl
.fpos
;
168 smb_new_dentry(newdent
);
171 if (ctl
.idx
>= SMB_DIRCACHE_SIZE
) {
174 SetPageUptodate(ctl
.page
);
175 unlock_page(ctl
.page
);
176 page_cache_release(ctl
.page
);
179 ctl
.idx
-= SMB_DIRCACHE_SIZE
;
181 ctl
.page
= grab_cache_page(&inode
->i_data
, ctl
.ofs
);
183 ctl
.cache
= kmap(ctl
.page
);
186 ctl
.cache
->dentry
[ctl
.idx
] = newdent
;
194 if (!ctl
.filled
&& (ctl
.fpos
== filp
->f_pos
)) {
196 ino
= find_inode_number(dentry
, qname
);
198 ino
= iunique(inode
->i_sb
, 2);
199 ctl
.filled
= filldir(dirent
, qname
->name
, qname
->len
,
200 filp
->f_pos
, ino
, DT_UNKNOWN
);
207 return (ctl
.valid
|| !ctl
.filled
);