summaryrefslogtreecommitdiffstats
path: root/fs/smbfs/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/smbfs/cache.c')
-rw-r--r--fs/smbfs/cache.c55
1 files changed, 10 insertions, 45 deletions
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c
index e3e9c044f..3dc17d229 100644
--- a/fs/smbfs/cache.c
+++ b/fs/smbfs/cache.c
@@ -48,6 +48,7 @@ out_unlock:
UnlockPage(page);
page_cache_release(page);
out:
+ return;
}
/*
@@ -71,47 +72,6 @@ smb_invalidate_dircache_entries(struct dentry *parent)
spin_unlock(&dcache_lock);
}
-
-static int
-smb_d_validate(struct dentry *dentry)
-{
- unsigned long dent_addr = (unsigned long) dentry;
- unsigned long min_addr = PAGE_OFFSET;
- unsigned long align_mask = 0x0F;
- unsigned int len;
- int valid = 0;
-
- if (dent_addr < min_addr)
- goto bad_addr;
- if (dent_addr > (unsigned long)high_memory - sizeof(struct dentry))
- goto bad_addr;
- if ((dent_addr & ~align_mask) != dent_addr)
- goto bad_align;
- if ((!kern_addr_valid(dent_addr)) || (!kern_addr_valid(dent_addr -1 +
- sizeof(struct dentry))))
- goto bad_addr;
- /*
- * Looks safe enough to dereference ...
- */
- len = dentry->d_name.len;
- if (len > SMB_MAXPATHLEN)
- goto out;
- /*
- * Note: d_validate doesn't dereference the parent pointer ...
- * just combines it with the name hash to find the hash chain.
- */
- valid = d_validate(dentry, dentry->d_parent, dentry->d_name.hash, len);
-out:
- return valid;
-
-bad_addr:
- printk(KERN_ERR "smb_d_validate: invalid address %lx\n", dent_addr);
- goto out;
-bad_align:
- printk(KERN_ERR "smb_d_validate: unaligned address %lx\n", dent_addr);
- goto out;
-}
-
/*
* dget, but require that fpos and parent matches what the dentry contains.
* dentry is not known to be a valid pointer at entry.
@@ -122,8 +82,8 @@ smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
struct dentry *dent = dentry;
struct list_head *next;
- if (smb_d_validate(dent)) {
- if (dent->d_parent == parent &&
+ if (d_validate(dent, parent)) {
+ if (dent->d_name.len <= SMB_MAXPATHLEN &&
(unsigned long)dent->d_fsdata == fpos) {
if (!dent->d_inode) {
dput(dent);
@@ -167,6 +127,7 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
struct inode *newino, *inode = dentry->d_inode;
struct smb_cache_control ctl = *ctrl;
int valid = 0;
+ int hashed = 0;
ino_t ino = 0;
qname->hash = full_name_hash(qname->name, qname->len);
@@ -181,9 +142,11 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
newdent = d_alloc(dentry, qname);
if (!newdent)
goto end_advance;
- } else
+ } else {
+ hashed = 1;
memcpy((char *) newdent->d_name.name, qname->name,
newdent->d_name.len);
+ }
if (!newdent->d_inode) {
smb_renew_times(newdent);
@@ -191,7 +154,9 @@ smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
newino = smb_iget(inode->i_sb, entry);
if (newino) {
smb_new_dentry(newdent);
- d_add(newdent, newino);
+ d_instantiate(newdent, newino);
+ if (!hashed)
+ d_rehash(newdent);
}
} else
smb_set_inode_attr(newdent->d_inode, entry);